Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | * Muxer/output file setup. | ||
3 | * | ||
4 | * This file is part of FFmpeg. | ||
5 | * | ||
6 | * FFmpeg is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU Lesser General Public | ||
8 | * License as published by the Free Software Foundation; either | ||
9 | * version 2.1 of the License, or (at your option) any later version. | ||
10 | * | ||
11 | * FFmpeg is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * Lesser General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU Lesser General Public | ||
17 | * License along with FFmpeg; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
19 | */ | ||
20 | |||
21 | #include <string.h> | ||
22 | |||
23 | #include "cmdutils.h" | ||
24 | #include "ffmpeg.h" | ||
25 | #include "ffmpeg_mux.h" | ||
26 | #include "ffmpeg_sched.h" | ||
27 | #include "fopen_utf8.h" | ||
28 | |||
29 | #include "libavformat/avformat.h" | ||
30 | #include "libavformat/avio.h" | ||
31 | |||
32 | #include "libavcodec/avcodec.h" | ||
33 | |||
34 | #include "libavfilter/avfilter.h" | ||
35 | |||
36 | #include "libavutil/avassert.h" | ||
37 | #include "libavutil/avstring.h" | ||
38 | #include "libavutil/avutil.h" | ||
39 | #include "libavutil/bprint.h" | ||
40 | #include "libavutil/dict.h" | ||
41 | #include "libavutil/display.h" | ||
42 | #include "libavutil/getenv_utf8.h" | ||
43 | #include "libavutil/iamf.h" | ||
44 | #include "libavutil/intreadwrite.h" | ||
45 | #include "libavutil/log.h" | ||
46 | #include "libavutil/mem.h" | ||
47 | #include "libavutil/opt.h" | ||
48 | #include "libavutil/parseutils.h" | ||
49 | #include "libavutil/pixdesc.h" | ||
50 | |||
51 | #define DEFAULT_PASS_LOGFILENAME_PREFIX "ffmpeg2pass" | ||
52 | |||
53 | 9686 | static int check_opt_bitexact(void *ctx, const AVDictionary *opts, | |
54 | const char *opt_name, int flag) | ||
55 | { | ||
56 | 9686 | const AVDictionaryEntry *e = av_dict_get(opts, opt_name, NULL, 0); | |
57 | |||
58 |
2/2✓ Branch 0 taken 7845 times.
✓ Branch 1 taken 1841 times.
|
9686 | if (e) { |
59 | 7845 | const AVOption *o = av_opt_find(ctx, opt_name, NULL, 0, 0); | |
60 | 7845 | int val = 0; | |
61 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7845 times.
|
7845 | if (!o) |
62 | ✗ | return 0; | |
63 | 7845 | av_opt_eval_flags(ctx, o, e->value, &val); | |
64 | 7845 | return !!(val & flag); | |
65 | } | ||
66 | 1841 | return 0; | |
67 | } | ||
68 | |||
69 | 7099 | static int choose_encoder(const OptionsContext *o, AVFormatContext *s, | |
70 | OutputStream *ost, const AVCodec **enc) | ||
71 | { | ||
72 | 7099 | enum AVMediaType type = ost->type; | |
73 | 7099 | char *codec_name = NULL; | |
74 | |||
75 | 7099 | *enc = NULL; | |
76 | |||
77 |
16/20✓ Branch 1 taken 4283 times.
✓ Branch 2 taken 194 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 194 times.
✓ Branch 5 taken 4477 times.
✓ Branch 6 taken 7099 times.
✓ Branch 7 taken 62 times.
✓ Branch 8 taken 7037 times.
✓ Branch 9 taken 62 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 62 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 61 times.
✓ Branch 14 taken 1 times.
✓ Branch 15 taken 62 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 310 times.
✓ Branch 19 taken 62 times.
✓ Branch 20 taken 61 times.
✓ Branch 21 taken 1 times.
|
11886 | MATCH_PER_STREAM_OPT(codec_names, str, codec_name, s, ost->st); |
78 | |||
79 |
4/4✓ Branch 0 taken 1576 times.
✓ Branch 1 taken 5523 times.
✓ Branch 2 taken 82 times.
✓ Branch 3 taken 1494 times.
|
7099 | if (type != AVMEDIA_TYPE_VIDEO && |
80 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 71 times.
|
82 | type != AVMEDIA_TYPE_AUDIO && |
81 | type != AVMEDIA_TYPE_SUBTITLE) { | ||
82 |
3/4✓ Branch 0 taken 4 times.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
|
11 | if (codec_name && strcmp(codec_name, "copy")) { |
83 | ✗ | const char *type_str = av_get_media_type_string(type); | |
84 | ✗ | av_log(ost, AV_LOG_FATAL, | |
85 | "Encoder '%s' specified, but only '-codec copy' supported " | ||
86 | "for %s streams\n", codec_name, type_str); | ||
87 | ✗ | return AVERROR(ENOSYS); | |
88 | } | ||
89 | 11 | return 0; | |
90 | } | ||
91 | |||
92 |
2/2✓ Branch 0 taken 2871 times.
✓ Branch 1 taken 4217 times.
|
7088 | if (!codec_name) { |
93 | 2871 | ost->par_in->codec_id = av_guess_codec(s->oformat, NULL, s->url, NULL, ost->type); | |
94 | 2871 | *enc = avcodec_find_encoder(ost->par_in->codec_id); | |
95 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2871 times.
|
2871 | if (!*enc) { |
96 | ✗ | av_log(ost, AV_LOG_FATAL, "Automatic encoder selection failed " | |
97 | "Default encoder for format %s (codec %s) is " | ||
98 | "probably disabled. Please choose an encoder manually.\n", | ||
99 | ✗ | s->oformat->name, avcodec_get_name(ost->par_in->codec_id)); | |
100 | ✗ | return AVERROR_ENCODER_NOT_FOUND; | |
101 | } | ||
102 |
2/2✓ Branch 0 taken 3600 times.
✓ Branch 1 taken 617 times.
|
4217 | } else if (strcmp(codec_name, "copy")) { |
103 | 3600 | int ret = find_codec(ost, codec_name, ost->type, 1, enc); | |
104 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3600 times.
|
3600 | if (ret < 0) |
105 | ✗ | return ret; | |
106 | 3600 | ost->par_in->codec_id = (*enc)->id; | |
107 | } | ||
108 | |||
109 | 7088 | return 0; | |
110 | } | ||
111 | |||
112 | ✗ | static char *get_line(AVIOContext *s, AVBPrint *bprint) | |
113 | { | ||
114 | char c; | ||
115 | |||
116 | ✗ | while ((c = avio_r8(s)) && c != '\n') | |
117 | ✗ | av_bprint_chars(bprint, c, 1); | |
118 | |||
119 | ✗ | if (!av_bprint_is_complete(bprint)) | |
120 | ✗ | return NULL; | |
121 | |||
122 | ✗ | return bprint->str; | |
123 | } | ||
124 | |||
125 | ✗ | static int get_preset_file_2(const char *preset_name, const char *codec_name, AVIOContext **s) | |
126 | { | ||
127 | ✗ | int i, ret = -1; | |
128 | char filename[1000]; | ||
129 | ✗ | char *env_avconv_datadir = getenv_utf8("AVCONV_DATADIR"); | |
130 | ✗ | char *env_home = getenv_utf8("HOME"); | |
131 | ✗ | const char *base[3] = { env_avconv_datadir, | |
132 | env_home, | ||
133 | AVCONV_DATADIR, | ||
134 | }; | ||
135 | |||
136 | ✗ | for (i = 0; i < FF_ARRAY_ELEMS(base) && ret < 0; i++) { | |
137 | ✗ | if (!base[i]) | |
138 | ✗ | continue; | |
139 | ✗ | if (codec_name) { | |
140 | ✗ | snprintf(filename, sizeof(filename), "%s%s/%s-%s.avpreset", base[i], | |
141 | i != 1 ? "" : "/.avconv", codec_name, preset_name); | ||
142 | ✗ | ret = avio_open2(s, filename, AVIO_FLAG_READ, &int_cb, NULL); | |
143 | } | ||
144 | ✗ | if (ret < 0) { | |
145 | ✗ | snprintf(filename, sizeof(filename), "%s%s/%s.avpreset", base[i], | |
146 | i != 1 ? "" : "/.avconv", preset_name); | ||
147 | ✗ | ret = avio_open2(s, filename, AVIO_FLAG_READ, &int_cb, NULL); | |
148 | } | ||
149 | } | ||
150 | ✗ | freeenv_utf8(env_home); | |
151 | ✗ | freeenv_utf8(env_avconv_datadir); | |
152 | ✗ | return ret; | |
153 | } | ||
154 | |||
155 | typedef struct EncStatsFile { | ||
156 | char *path; | ||
157 | AVIOContext *io; | ||
158 | } EncStatsFile; | ||
159 | |||
160 | static EncStatsFile *enc_stats_files; | ||
161 | static int nb_enc_stats_files; | ||
162 | |||
163 | ✗ | static int enc_stats_get_file(AVIOContext **io, const char *path) | |
164 | { | ||
165 | EncStatsFile *esf; | ||
166 | int ret; | ||
167 | |||
168 | ✗ | for (int i = 0; i < nb_enc_stats_files; i++) | |
169 | ✗ | if (!strcmp(path, enc_stats_files[i].path)) { | |
170 | ✗ | *io = enc_stats_files[i].io; | |
171 | ✗ | return 0; | |
172 | } | ||
173 | |||
174 | ✗ | ret = GROW_ARRAY(enc_stats_files, nb_enc_stats_files); | |
175 | ✗ | if (ret < 0) | |
176 | ✗ | return ret; | |
177 | |||
178 | ✗ | esf = &enc_stats_files[nb_enc_stats_files - 1]; | |
179 | |||
180 | ✗ | ret = avio_open2(&esf->io, path, AVIO_FLAG_WRITE, &int_cb, NULL); | |
181 | ✗ | if (ret < 0) { | |
182 | ✗ | av_log(NULL, AV_LOG_ERROR, "Error opening stats file '%s': %s\n", | |
183 | ✗ | path, av_err2str(ret)); | |
184 | ✗ | return ret; | |
185 | } | ||
186 | |||
187 | ✗ | esf->path = av_strdup(path); | |
188 | ✗ | if (!esf->path) | |
189 | ✗ | return AVERROR(ENOMEM); | |
190 | |||
191 | ✗ | *io = esf->io; | |
192 | |||
193 | ✗ | return 0; | |
194 | } | ||
195 | |||
196 | 6756 | void of_enc_stats_close(void) | |
197 | { | ||
198 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6756 times.
|
6756 | for (int i = 0; i < nb_enc_stats_files; i++) { |
199 | ✗ | av_freep(&enc_stats_files[i].path); | |
200 | ✗ | avio_closep(&enc_stats_files[i].io); | |
201 | } | ||
202 | 6756 | av_freep(&enc_stats_files); | |
203 | 6756 | nb_enc_stats_files = 0; | |
204 | 6756 | } | |
205 | |||
206 | ✗ | static int unescape(char **pdst, size_t *dst_len, | |
207 | const char **pstr, char delim) | ||
208 | { | ||
209 | ✗ | const char *str = *pstr; | |
210 | char *dst; | ||
211 | size_t len, idx; | ||
212 | |||
213 | ✗ | *pdst = NULL; | |
214 | |||
215 | ✗ | len = strlen(str); | |
216 | ✗ | if (!len) | |
217 | ✗ | return 0; | |
218 | |||
219 | ✗ | dst = av_malloc(len + 1); | |
220 | ✗ | if (!dst) | |
221 | ✗ | return AVERROR(ENOMEM); | |
222 | |||
223 | ✗ | for (idx = 0; *str; idx++, str++) { | |
224 | ✗ | if (str[0] == '\\' && str[1]) | |
225 | ✗ | str++; | |
226 | ✗ | else if (*str == delim) | |
227 | ✗ | break; | |
228 | |||
229 | ✗ | dst[idx] = *str; | |
230 | } | ||
231 | ✗ | if (!idx) { | |
232 | ✗ | av_freep(&dst); | |
233 | ✗ | return 0; | |
234 | } | ||
235 | |||
236 | ✗ | dst[idx] = 0; | |
237 | |||
238 | ✗ | *pdst = dst; | |
239 | ✗ | *dst_len = idx; | |
240 | ✗ | *pstr = str; | |
241 | |||
242 | ✗ | return 0; | |
243 | } | ||
244 | |||
245 | ✗ | static int enc_stats_init(OutputStream *ost, EncStats *es, int pre, | |
246 | const char *path, const char *fmt_spec) | ||
247 | { | ||
248 | static const struct { | ||
249 | enum EncStatsType type; | ||
250 | const char *str; | ||
251 | unsigned pre_only:1; | ||
252 | unsigned post_only:1; | ||
253 | unsigned need_input_data:1; | ||
254 | } fmt_specs[] = { | ||
255 | { ENC_STATS_FILE_IDX, "fidx" }, | ||
256 | { ENC_STATS_STREAM_IDX, "sidx" }, | ||
257 | { ENC_STATS_FRAME_NUM, "n" }, | ||
258 | { ENC_STATS_FRAME_NUM_IN, "ni", 0, 0, 1 }, | ||
259 | { ENC_STATS_TIMEBASE, "tb" }, | ||
260 | { ENC_STATS_TIMEBASE_IN, "tbi", 0, 0, 1 }, | ||
261 | { ENC_STATS_PTS, "pts" }, | ||
262 | { ENC_STATS_PTS_TIME, "t" }, | ||
263 | { ENC_STATS_PTS_IN, "ptsi", 0, 0, 1 }, | ||
264 | { ENC_STATS_PTS_TIME_IN, "ti", 0, 0, 1 }, | ||
265 | { ENC_STATS_DTS, "dts", 0, 1 }, | ||
266 | { ENC_STATS_DTS_TIME, "dt", 0, 1 }, | ||
267 | { ENC_STATS_SAMPLE_NUM, "sn", 1 }, | ||
268 | { ENC_STATS_NB_SAMPLES, "samp", 1 }, | ||
269 | { ENC_STATS_PKT_SIZE, "size", 0, 1 }, | ||
270 | { ENC_STATS_BITRATE, "br", 0, 1 }, | ||
271 | { ENC_STATS_AVG_BITRATE, "abr", 0, 1 }, | ||
272 | { ENC_STATS_KEYFRAME, "key", 0, 1 }, | ||
273 | }; | ||
274 | ✗ | const char *next = fmt_spec; | |
275 | |||
276 | int ret; | ||
277 | |||
278 | ✗ | while (*next) { | |
279 | EncStatsComponent *c; | ||
280 | char *val; | ||
281 | size_t val_len; | ||
282 | |||
283 | // get the sequence up until next opening brace | ||
284 | ✗ | ret = unescape(&val, &val_len, &next, '{'); | |
285 | ✗ | if (ret < 0) | |
286 | ✗ | return ret; | |
287 | |||
288 | ✗ | if (val) { | |
289 | ✗ | ret = GROW_ARRAY(es->components, es->nb_components); | |
290 | ✗ | if (ret < 0) { | |
291 | ✗ | av_freep(&val); | |
292 | ✗ | return ret; | |
293 | } | ||
294 | |||
295 | ✗ | c = &es->components[es->nb_components - 1]; | |
296 | ✗ | c->type = ENC_STATS_LITERAL; | |
297 | ✗ | c->str = val; | |
298 | ✗ | c->str_len = val_len; | |
299 | } | ||
300 | |||
301 | ✗ | if (!*next) | |
302 | ✗ | break; | |
303 | ✗ | next++; | |
304 | |||
305 | // get the part inside braces | ||
306 | ✗ | ret = unescape(&val, &val_len, &next, '}'); | |
307 | ✗ | if (ret < 0) | |
308 | ✗ | return ret; | |
309 | |||
310 | ✗ | if (!val) { | |
311 | ✗ | av_log(NULL, AV_LOG_ERROR, | |
312 | "Empty formatting directive in: %s\n", fmt_spec); | ||
313 | ✗ | return AVERROR(EINVAL); | |
314 | } | ||
315 | |||
316 | ✗ | if (!*next) { | |
317 | ✗ | av_log(NULL, AV_LOG_ERROR, | |
318 | "Missing closing brace in: %s\n", fmt_spec); | ||
319 | ✗ | ret = AVERROR(EINVAL); | |
320 | ✗ | goto fail; | |
321 | } | ||
322 | ✗ | next++; | |
323 | |||
324 | ✗ | ret = GROW_ARRAY(es->components, es->nb_components); | |
325 | ✗ | if (ret < 0) | |
326 | ✗ | goto fail; | |
327 | |||
328 | ✗ | c = &es->components[es->nb_components - 1]; | |
329 | |||
330 | ✗ | for (size_t i = 0; i < FF_ARRAY_ELEMS(fmt_specs); i++) { | |
331 | ✗ | if (!strcmp(val, fmt_specs[i].str)) { | |
332 | ✗ | if ((pre && fmt_specs[i].post_only) || (!pre && fmt_specs[i].pre_only)) { | |
333 | ✗ | av_log(NULL, AV_LOG_ERROR, | |
334 | "Format directive '%s' may only be used %s-encoding\n", | ||
335 | val, pre ? "post" : "pre"); | ||
336 | ✗ | ret = AVERROR(EINVAL); | |
337 | ✗ | goto fail; | |
338 | } | ||
339 | |||
340 | ✗ | c->type = fmt_specs[i].type; | |
341 | |||
342 | ✗ | if (fmt_specs[i].need_input_data && !ost->ist) { | |
343 | ✗ | av_log(ost, AV_LOG_WARNING, | |
344 | "Format directive '%s' is unavailable, because " | ||
345 | "this output stream has no associated input stream\n", | ||
346 | val); | ||
347 | } | ||
348 | |||
349 | ✗ | break; | |
350 | } | ||
351 | } | ||
352 | |||
353 | ✗ | if (!c->type) { | |
354 | ✗ | av_log(NULL, AV_LOG_ERROR, "Invalid format directive: %s\n", val); | |
355 | ✗ | ret = AVERROR(EINVAL); | |
356 | ✗ | goto fail; | |
357 | } | ||
358 | |||
359 | ✗ | fail: | |
360 | ✗ | av_freep(&val); | |
361 | ✗ | if (ret < 0) | |
362 | ✗ | return ret; | |
363 | } | ||
364 | |||
365 | ✗ | ret = pthread_mutex_init(&es->lock, NULL); | |
366 | ✗ | if (ret) | |
367 | ✗ | return AVERROR(ret); | |
368 | ✗ | es->lock_initialized = 1; | |
369 | |||
370 | ✗ | ret = enc_stats_get_file(&es->io, path); | |
371 | ✗ | if (ret < 0) | |
372 | ✗ | return ret; | |
373 | |||
374 | ✗ | return 0; | |
375 | } | ||
376 | |||
377 | 31 | static const char *output_stream_item_name(void *obj) | |
378 | { | ||
379 | 31 | const MuxStream *ms = obj; | |
380 | |||
381 | 31 | return ms->log_name; | |
382 | } | ||
383 | |||
384 | static const AVClass output_stream_class = { | ||
385 | .class_name = "OutputStream", | ||
386 | .version = LIBAVUTIL_VERSION_INT, | ||
387 | .item_name = output_stream_item_name, | ||
388 | .category = AV_CLASS_CATEGORY_MUXER, | ||
389 | }; | ||
390 | |||
391 | 7099 | static MuxStream *mux_stream_alloc(Muxer *mux, enum AVMediaType type) | |
392 | { | ||
393 | 7099 | const char *type_str = av_get_media_type_string(type); | |
394 | MuxStream *ms; | ||
395 | |||
396 | 7099 | ms = allocate_array_elem(&mux->of.streams, sizeof(*ms), &mux->of.nb_streams); | |
397 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7099 times.
|
7099 | if (!ms) |
398 | ✗ | return NULL; | |
399 | |||
400 | 7099 | ms->ost.file = &mux->of; | |
401 | 7099 | ms->ost.index = mux->of.nb_streams - 1; | |
402 | 7099 | ms->ost.type = type; | |
403 | |||
404 | 7099 | ms->ost.class = &output_stream_class; | |
405 | |||
406 | 7099 | ms->sch_idx = -1; | |
407 | 7099 | ms->sch_idx_enc = -1; | |
408 | |||
409 |
1/2✓ Branch 0 taken 7099 times.
✗ Branch 1 not taken.
|
7099 | snprintf(ms->log_name, sizeof(ms->log_name), "%cost#%d:%d", |
410 | 7099 | type_str ? *type_str : '?', mux->of.index, ms->ost.index); | |
411 | |||
412 | 7099 | return ms; | |
413 | } | ||
414 | |||
415 | 7017 | static int ost_get_filters(const OptionsContext *o, AVFormatContext *oc, | |
416 | OutputStream *ost, char **dst) | ||
417 | { | ||
418 | 7017 | const char *filters = NULL; | |
419 | #if FFMPEG_OPT_FILTER_SCRIPT | ||
420 | 7017 | const char *filters_script = NULL; | |
421 | |||
422 |
2/20✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 7017 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7017 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
7017 | MATCH_PER_STREAM_OPT(filter_scripts, str, filters_script, oc, ost->st); |
423 | #endif | ||
424 |
6/20✓ Branch 1 taken 3404 times.
✓ Branch 2 taken 91 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 91 times.
✓ Branch 5 taken 3495 times.
✓ Branch 6 taken 7017 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7017 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
10512 | MATCH_PER_STREAM_OPT(filters, str, filters, oc, ost->st); |
425 | |||
426 |
2/2✓ Branch 0 taken 584 times.
✓ Branch 1 taken 6433 times.
|
7017 | if (!ost->enc) { |
427 |
1/2✓ Branch 0 taken 584 times.
✗ Branch 1 not taken.
|
584 | if ( |
428 | #if FFMPEG_OPT_FILTER_SCRIPT | ||
429 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 584 times.
|
584 | filters_script || |
430 | #endif | ||
431 | filters) { | ||
432 | ✗ | av_log(ost, AV_LOG_ERROR, | |
433 | "%s '%s' was specified, but codec copy was selected. " | ||
434 | "Filtering and streamcopy cannot be used together.\n", | ||
435 | #if FFMPEG_OPT_FILTER_SCRIPT | ||
436 | filters ? "Filtergraph" : "Filtergraph script", | ||
437 | filters ? filters : filters_script | ||
438 | #else | ||
439 | "Filtergraph", filters | ||
440 | #endif | ||
441 | ); | ||
442 | ✗ | return AVERROR(ENOSYS); | |
443 | } | ||
444 | 584 | return 0; | |
445 | } | ||
446 | |||
447 |
2/2✓ Branch 0 taken 167 times.
✓ Branch 1 taken 6266 times.
|
6433 | if (!ost->ist) { |
448 |
1/2✓ Branch 0 taken 167 times.
✗ Branch 1 not taken.
|
167 | if ( |
449 | #if FFMPEG_OPT_FILTER_SCRIPT | ||
450 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 167 times.
|
167 | filters_script || |
451 | #endif | ||
452 | filters) { | ||
453 | ✗ | av_log(ost, AV_LOG_ERROR, | |
454 | "%s '%s' was specified for a stream fed from a complex " | ||
455 | "filtergraph. Simple and complex filtering cannot be used " | ||
456 | "together for the same stream.\n", | ||
457 | #if FFMPEG_OPT_FILTER_SCRIPT | ||
458 | filters ? "Filtergraph" : "Filtergraph script", | ||
459 | filters ? filters : filters_script | ||
460 | #else | ||
461 | "Filtergraph", filters | ||
462 | #endif | ||
463 | ); | ||
464 | ✗ | return AVERROR(EINVAL); | |
465 | } | ||
466 | 167 | return 0; | |
467 | } | ||
468 | |||
469 | #if FFMPEG_OPT_FILTER_SCRIPT | ||
470 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 6266 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
6266 | if (filters_script && filters) { |
471 | ✗ | av_log(ost, AV_LOG_ERROR, "Both -filter and -filter_script set\n"); | |
472 | ✗ | return AVERROR(EINVAL); | |
473 | } | ||
474 | |||
475 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6266 times.
|
6266 | if (filters_script) |
476 | ✗ | *dst = file_read(filters_script); | |
477 | else | ||
478 | #endif | ||
479 |
2/2✓ Branch 0 taken 3404 times.
✓ Branch 1 taken 2862 times.
|
6266 | if (filters) |
480 | 3404 | *dst = av_strdup(filters); | |
481 | else | ||
482 |
2/2✓ Branch 0 taken 2282 times.
✓ Branch 1 taken 580 times.
|
2862 | *dst = av_strdup(ost->type == AVMEDIA_TYPE_VIDEO ? "null" : "anull"); |
483 |
1/2✓ Branch 0 taken 6266 times.
✗ Branch 1 not taken.
|
6266 | return *dst ? 0 : AVERROR(ENOMEM); |
484 | } | ||
485 | |||
486 | ✗ | static int parse_matrix_coeffs(void *logctx, uint16_t *dest, const char *str) | |
487 | { | ||
488 | ✗ | const char *p = str; | |
489 | ✗ | for (int i = 0;; i++) { | |
490 | ✗ | dest[i] = atoi(p); | |
491 | ✗ | if (i == 63) | |
492 | ✗ | break; | |
493 | ✗ | p = strchr(p, ','); | |
494 | ✗ | if (!p) { | |
495 | ✗ | av_log(logctx, AV_LOG_FATAL, | |
496 | "Syntax error in matrix \"%s\" at coeff %d\n", str, i); | ||
497 | ✗ | return AVERROR(EINVAL); | |
498 | } | ||
499 | ✗ | p++; | |
500 | } | ||
501 | |||
502 | ✗ | return 0; | |
503 | } | ||
504 | |||
505 | 622 | static int fmt_in_list(const int *formats, int format) | |
506 | { | ||
507 |
1/2✓ Branch 0 taken 3374 times.
✗ Branch 1 not taken.
|
3374 | for (; *formats != -1; formats++) |
508 |
2/2✓ Branch 0 taken 622 times.
✓ Branch 1 taken 2752 times.
|
3374 | if (*formats == format) |
509 | 622 | return 1; | |
510 | ✗ | return 0; | |
511 | } | ||
512 | |||
513 | static enum AVPixelFormat | ||
514 | ✗ | choose_pixel_fmt(const AVCodec *codec, enum AVPixelFormat target) | |
515 | { | ||
516 | ✗ | const enum AVPixelFormat *p = codec->pix_fmts; | |
517 | ✗ | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(target); | |
518 | //FIXME: This should check for AV_PIX_FMT_FLAG_ALPHA after PAL8 pixel format without alpha is implemented | ||
519 | ✗ | int has_alpha = desc ? desc->nb_components % 2 == 0 : 0; | |
520 | ✗ | enum AVPixelFormat best= AV_PIX_FMT_NONE; | |
521 | |||
522 | ✗ | for (; *p != AV_PIX_FMT_NONE; p++) { | |
523 | ✗ | best = av_find_best_pix_fmt_of_2(best, *p, target, has_alpha, NULL); | |
524 | ✗ | if (*p == target) | |
525 | ✗ | break; | |
526 | } | ||
527 | ✗ | if (*p == AV_PIX_FMT_NONE) { | |
528 | ✗ | if (target != AV_PIX_FMT_NONE) | |
529 | ✗ | av_log(NULL, AV_LOG_WARNING, | |
530 | "Incompatible pixel format '%s' for codec '%s', auto-selecting format '%s'\n", | ||
531 | av_get_pix_fmt_name(target), | ||
532 | ✗ | codec->name, | |
533 | av_get_pix_fmt_name(best)); | ||
534 | ✗ | return best; | |
535 | } | ||
536 | ✗ | return target; | |
537 | } | ||
538 | |||
539 | 3733 | static enum AVPixelFormat pix_fmt_parse(OutputStream *ost, const char *name) | |
540 | { | ||
541 | 3733 | const enum AVPixelFormat *fmts = ost->enc_ctx->codec->pix_fmts; | |
542 | enum AVPixelFormat fmt; | ||
543 | |||
544 | 3733 | fmt = av_get_pix_fmt(name); | |
545 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3733 times.
|
3733 | if (fmt == AV_PIX_FMT_NONE) { |
546 | ✗ | av_log(ost, AV_LOG_FATAL, "Unknown pixel format requested: %s.\n", name); | |
547 | ✗ | return AV_PIX_FMT_NONE; | |
548 | } | ||
549 | |||
550 | /* when the user specified-format is an alias for an endianness-specific | ||
551 | * one (e.g. rgb48 -> rgb48be/le), it gets translated into the native | ||
552 | * endianness by av_get_pix_fmt(); | ||
553 | * the following code handles the case when the native endianness is not | ||
554 | * supported by the encoder, but the other one is */ | ||
555 |
3/4✓ Branch 0 taken 311 times.
✓ Branch 1 taken 3422 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 311 times.
|
3733 | if (fmts && !fmt_in_list(fmts, fmt)) { |
556 | ✗ | const char *name_canonical = av_get_pix_fmt_name(fmt); | |
557 | ✗ | int len = strlen(name_canonical); | |
558 | |||
559 | ✗ | if (strcmp(name, name_canonical) && | |
560 | ✗ | (!strcmp(name_canonical + len - 2, "le") || | |
561 | ✗ | !strcmp(name_canonical + len - 2, "be"))) { | |
562 | char name_other[64]; | ||
563 | enum AVPixelFormat fmt_other; | ||
564 | |||
565 | ✗ | snprintf(name_other, sizeof(name_other), "%s%ce", | |
566 | ✗ | name, name_canonical[len - 2] == 'l' ? 'b' : 'l'); | |
567 | ✗ | fmt_other = av_get_pix_fmt(name_other); | |
568 | ✗ | if (fmt_other != AV_PIX_FMT_NONE && fmt_in_list(fmts, fmt_other)) { | |
569 | ✗ | av_log(ost, AV_LOG_VERBOSE, "Mapping pixel format %s->%s\n", | |
570 | name, name_other); | ||
571 | ✗ | fmt = fmt_other; | |
572 | } | ||
573 | } | ||
574 | } | ||
575 | |||
576 |
3/4✓ Branch 0 taken 311 times.
✓ Branch 1 taken 3422 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 311 times.
|
3733 | if (fmts && !fmt_in_list(fmts, fmt)) |
577 | ✗ | fmt = choose_pixel_fmt(ost->enc_ctx->codec, fmt); | |
578 | |||
579 | 3733 | return fmt; | |
580 | } | ||
581 | |||
582 | 5523 | static int new_stream_video(Muxer *mux, const OptionsContext *o, | |
583 | OutputStream *ost) | ||
584 | { | ||
585 | 5523 | AVFormatContext *oc = mux->fc; | |
586 | AVStream *st; | ||
587 | 5523 | char *frame_rate = NULL, *max_frame_rate = NULL, *frame_aspect_ratio = NULL; | |
588 | 5523 | int ret = 0; | |
589 | |||
590 | 5523 | st = ost->st; | |
591 | |||
592 |
4/20✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 22 times.
✓ Branch 6 taken 5523 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5523 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
5545 | MATCH_PER_STREAM_OPT(frame_rates, str, frame_rate, oc, st); |
593 |
3/4✓ Branch 0 taken 22 times.
✓ Branch 1 taken 5501 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 22 times.
|
5523 | if (frame_rate && av_parse_video_rate(&ost->frame_rate, frame_rate) < 0) { |
594 | ✗ | av_log(ost, AV_LOG_FATAL, "Invalid framerate value: %s\n", frame_rate); | |
595 | ✗ | return AVERROR(EINVAL); | |
596 | } | ||
597 | |||
598 |
2/20✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 5523 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5523 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
5523 | MATCH_PER_STREAM_OPT(max_frame_rates, str, max_frame_rate, oc, st); |
599 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 5523 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
5523 | if (max_frame_rate && av_parse_video_rate(&ost->max_frame_rate, max_frame_rate) < 0) { |
600 | ✗ | av_log(ost, AV_LOG_FATAL, "Invalid maximum framerate value: %s\n", max_frame_rate); | |
601 | ✗ | return AVERROR(EINVAL); | |
602 | } | ||
603 | |||
604 |
3/4✓ Branch 0 taken 22 times.
✓ Branch 1 taken 5501 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 22 times.
|
5523 | if (frame_rate && max_frame_rate) { |
605 | ✗ | av_log(ost, AV_LOG_ERROR, "Only one of -fpsmax and -r can be set for a stream.\n"); | |
606 | ✗ | return AVERROR(EINVAL); | |
607 | } | ||
608 | |||
609 |
2/20✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 5523 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5523 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
5523 | MATCH_PER_STREAM_OPT(frame_aspect_ratios, str, frame_aspect_ratio, oc, st); |
610 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5523 times.
|
5523 | if (frame_aspect_ratio) { |
611 | AVRational q; | ||
612 | ✗ | if (av_parse_ratio(&q, frame_aspect_ratio, 255, 0, NULL) < 0 || | |
613 | ✗ | q.num <= 0 || q.den <= 0) { | |
614 | ✗ | av_log(ost, AV_LOG_FATAL, "Invalid aspect ratio: %s\n", frame_aspect_ratio); | |
615 | ✗ | return AVERROR(EINVAL); | |
616 | } | ||
617 | ✗ | ost->frame_aspect_ratio = q; | |
618 | } | ||
619 | |||
620 |
2/2✓ Branch 0 taken 5192 times.
✓ Branch 1 taken 331 times.
|
5523 | if (ost->enc_ctx) { |
621 | 5192 | AVCodecContext *video_enc = ost->enc_ctx; | |
622 | 5192 | const char *p = NULL, *fps_mode = NULL; | |
623 | 5192 | char *frame_size = NULL; | |
624 | 5192 | char *frame_pix_fmt = NULL; | |
625 | 5192 | char *intra_matrix = NULL, *inter_matrix = NULL; | |
626 | 5192 | char *chroma_intra_matrix = NULL; | |
627 | 5192 | int do_pass = 0; | |
628 | int i; | ||
629 | |||
630 |
4/20✓ Branch 1 taken 231 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 231 times.
✓ Branch 6 taken 5192 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5192 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
5423 | MATCH_PER_STREAM_OPT(frame_sizes, str, frame_size, oc, st); |
631 |
2/2✓ Branch 0 taken 231 times.
✓ Branch 1 taken 4961 times.
|
5192 | if (frame_size) { |
632 | 231 | ret = av_parse_video_size(&video_enc->width, &video_enc->height, frame_size); | |
633 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 231 times.
|
231 | if (ret < 0) { |
634 | ✗ | av_log(ost, AV_LOG_FATAL, "Invalid frame size: %s.\n", frame_size); | |
635 | ✗ | return AVERROR(EINVAL); | |
636 | } | ||
637 | } | ||
638 | |||
639 |
4/20✓ Branch 1 taken 3733 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3733 times.
✓ Branch 6 taken 5192 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5192 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
8925 | MATCH_PER_STREAM_OPT(frame_pix_fmts, str, frame_pix_fmt, oc, st); |
640 |
3/4✓ Branch 0 taken 3733 times.
✓ Branch 1 taken 1459 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3733 times.
|
5192 | if (frame_pix_fmt && *frame_pix_fmt == '+') { |
641 | ✗ | ost->keep_pix_fmt = 1; | |
642 | ✗ | if (!*++frame_pix_fmt) | |
643 | ✗ | frame_pix_fmt = NULL; | |
644 | } | ||
645 |
2/2✓ Branch 0 taken 3733 times.
✓ Branch 1 taken 1459 times.
|
5192 | if (frame_pix_fmt) { |
646 | 3733 | video_enc->pix_fmt = pix_fmt_parse(ost, frame_pix_fmt); | |
647 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3733 times.
|
3733 | if (video_enc->pix_fmt == AV_PIX_FMT_NONE) |
648 | ✗ | return AVERROR(EINVAL); | |
649 | } | ||
650 | |||
651 |
2/20✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 5192 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5192 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
5192 | MATCH_PER_STREAM_OPT(intra_matrices, str, intra_matrix, oc, st); |
652 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5192 times.
|
5192 | if (intra_matrix) { |
653 | ✗ | if (!(video_enc->intra_matrix = av_mallocz(sizeof(*video_enc->intra_matrix) * 64))) | |
654 | ✗ | return AVERROR(ENOMEM); | |
655 | |||
656 | ✗ | ret = parse_matrix_coeffs(ost, video_enc->intra_matrix, intra_matrix); | |
657 | ✗ | if (ret < 0) | |
658 | ✗ | return ret; | |
659 | } | ||
660 |
2/20✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 5192 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5192 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
5192 | MATCH_PER_STREAM_OPT(chroma_intra_matrices, str, chroma_intra_matrix, oc, st); |
661 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5192 times.
|
5192 | if (chroma_intra_matrix) { |
662 | ✗ | uint16_t *p = av_mallocz(sizeof(*video_enc->chroma_intra_matrix) * 64); | |
663 | ✗ | if (!p) | |
664 | ✗ | return AVERROR(ENOMEM); | |
665 | ✗ | video_enc->chroma_intra_matrix = p; | |
666 | ✗ | ret = parse_matrix_coeffs(ost, p, chroma_intra_matrix); | |
667 | ✗ | if (ret < 0) | |
668 | ✗ | return ret; | |
669 | } | ||
670 |
2/20✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 5192 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5192 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
5192 | MATCH_PER_STREAM_OPT(inter_matrices, str, inter_matrix, oc, st); |
671 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5192 times.
|
5192 | if (inter_matrix) { |
672 | ✗ | if (!(video_enc->inter_matrix = av_mallocz(sizeof(*video_enc->inter_matrix) * 64))) | |
673 | ✗ | return AVERROR(ENOMEM); | |
674 | ✗ | ret = parse_matrix_coeffs(ost, video_enc->inter_matrix, inter_matrix); | |
675 | ✗ | if (ret < 0) | |
676 | ✗ | return ret; | |
677 | } | ||
678 | |||
679 |
2/20✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 5192 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5192 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
5192 | MATCH_PER_STREAM_OPT(rc_overrides, str, p, oc, st); |
680 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5192 times.
|
5192 | for (i = 0; p; i++) { |
681 | int start, end, q; | ||
682 | ✗ | int e = sscanf(p, "%d,%d,%d", &start, &end, &q); | |
683 | ✗ | if (e != 3) { | |
684 | ✗ | av_log(ost, AV_LOG_FATAL, "error parsing rc_override\n"); | |
685 | ✗ | return AVERROR(EINVAL); | |
686 | } | ||
687 | ✗ | video_enc->rc_override = | |
688 | ✗ | av_realloc_array(video_enc->rc_override, | |
689 | ✗ | i + 1, sizeof(RcOverride)); | |
690 | ✗ | if (!video_enc->rc_override) { | |
691 | ✗ | av_log(ost, AV_LOG_FATAL, "Could not (re)allocate memory for rc_override.\n"); | |
692 | ✗ | return AVERROR(ENOMEM); | |
693 | } | ||
694 | ✗ | video_enc->rc_override[i].start_frame = start; | |
695 | ✗ | video_enc->rc_override[i].end_frame = end; | |
696 | ✗ | if (q > 0) { | |
697 | ✗ | video_enc->rc_override[i].qscale = q; | |
698 | ✗ | video_enc->rc_override[i].quality_factor = 1.0; | |
699 | } | ||
700 | else { | ||
701 | ✗ | video_enc->rc_override[i].qscale = 0; | |
702 | ✗ | video_enc->rc_override[i].quality_factor = -q/100.0; | |
703 | } | ||
704 | ✗ | p = strchr(p, '/'); | |
705 | ✗ | if (p) p++; | |
706 | } | ||
707 | 5192 | video_enc->rc_override_count = i; | |
708 | |||
709 | /* two pass mode */ | ||
710 |
4/20✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 5192 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5192 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
5200 | MATCH_PER_STREAM_OPT(pass, i, do_pass, oc, st); |
711 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 5184 times.
|
5192 | if (do_pass) { |
712 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
|
8 | if (do_pass & 1) { |
713 | 4 | video_enc->flags |= AV_CODEC_FLAG_PASS1; | |
714 | 4 | av_dict_set(&ost->encoder_opts, "flags", "+pass1", AV_DICT_APPEND); | |
715 | } | ||
716 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
|
8 | if (do_pass & 2) { |
717 | 4 | video_enc->flags |= AV_CODEC_FLAG_PASS2; | |
718 | 4 | av_dict_set(&ost->encoder_opts, "flags", "+pass2", AV_DICT_APPEND); | |
719 | } | ||
720 | } | ||
721 | |||
722 |
4/20✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 5192 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5192 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
5200 | MATCH_PER_STREAM_OPT(passlogfiles, str, ost->logfile_prefix, oc, st); |
723 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 5184 times.
|
5192 | if (ost->logfile_prefix && |
724 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
|
8 | !(ost->logfile_prefix = av_strdup(ost->logfile_prefix))) |
725 | ✗ | return AVERROR(ENOMEM); | |
726 | |||
727 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 5184 times.
|
5192 | if (do_pass) { |
728 | 8 | int ost_idx = -1; | |
729 | char logfilename[1024]; | ||
730 | FILE *f; | ||
731 | |||
732 | /* compute this stream's global index */ | ||
733 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
|
16 | for (int i = 0; i <= ost->file->index; i++) |
734 | 8 | ost_idx += output_files[i]->nb_streams; | |
735 | |||
736 | 8 | snprintf(logfilename, sizeof(logfilename), "%s-%d.log", | |
737 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | ost->logfile_prefix ? ost->logfile_prefix : |
738 | DEFAULT_PASS_LOGFILENAME_PREFIX, | ||
739 | ost_idx); | ||
740 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (!strcmp(ost->enc_ctx->codec->name, "libx264")) { |
741 | ✗ | av_dict_set(&ost->encoder_opts, "stats", logfilename, AV_DICT_DONT_OVERWRITE); | |
742 | } else { | ||
743 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
|
8 | if (video_enc->flags & AV_CODEC_FLAG_PASS2) { |
744 | 4 | char *logbuffer = file_read(logfilename); | |
745 | |||
746 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (!logbuffer) { |
747 | ✗ | av_log(ost, AV_LOG_FATAL, "Error reading log file '%s' for pass-2 encoding\n", | |
748 | logfilename); | ||
749 | ✗ | return AVERROR(EIO); | |
750 | } | ||
751 | 4 | video_enc->stats_in = logbuffer; | |
752 | } | ||
753 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
|
8 | if (video_enc->flags & AV_CODEC_FLAG_PASS1) { |
754 | 4 | f = fopen_utf8(logfilename, "wb"); | |
755 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (!f) { |
756 | ✗ | av_log(ost, AV_LOG_FATAL, | |
757 | "Cannot write log file '%s' for pass-1 encoding: %s\n", | ||
758 | ✗ | logfilename, strerror(errno)); | |
759 | ✗ | return AVERROR(errno); | |
760 | } | ||
761 | 4 | ost->logfile = f; | |
762 | } | ||
763 | } | ||
764 | } | ||
765 | |||
766 |
4/20✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 5192 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5192 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
5193 | MATCH_PER_STREAM_OPT(force_fps, i, ost->force_fps, oc, st); |
767 | |||
768 | #if FFMPEG_OPT_TOP | ||
769 | 5192 | ost->top_field_first = -1; | |
770 |
2/20✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 5192 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5192 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
5192 | MATCH_PER_STREAM_OPT(top_field_first, i, ost->top_field_first, oc, st); |
771 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5192 times.
|
5192 | if (ost->top_field_first >= 0) |
772 | ✗ | av_log(ost, AV_LOG_WARNING, "-top is deprecated, use the setfield filter instead\n"); | |
773 | #endif | ||
774 | |||
775 | #if FFMPEG_OPT_VSYNC | ||
776 | 5192 | ost->vsync_method = video_sync_method; | |
777 | #else | ||
778 | ost->vsync_method = VSYNC_AUTO; | ||
779 | #endif | ||
780 |
4/20✓ Branch 1 taken 514 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 514 times.
✓ Branch 6 taken 5192 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5192 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
5706 | MATCH_PER_STREAM_OPT(fps_mode, str, fps_mode, oc, st); |
781 |
2/2✓ Branch 0 taken 514 times.
✓ Branch 1 taken 4678 times.
|
5192 | if (fps_mode) { |
782 | 514 | ret = parse_and_set_vsync(fps_mode, &ost->vsync_method, ost->file->index, ost->index, 0); | |
783 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 514 times.
|
514 | if (ret < 0) |
784 | ✗ | return ret; | |
785 | } | ||
786 | |||
787 |
3/4✓ Branch 0 taken 5171 times.
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5171 times.
|
5192 | if ((ost->frame_rate.num || ost->max_frame_rate.num) && |
788 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 20 times.
|
21 | !(ost->vsync_method == VSYNC_AUTO || |
789 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
1 | ost->vsync_method == VSYNC_CFR || ost->vsync_method == VSYNC_VSCFR)) { |
790 | ✗ | av_log(ost, AV_LOG_FATAL, "One of -r/-fpsmax was specified " | |
791 | "together a non-CFR -vsync/-fps_mode. This is contradictory.\n"); | ||
792 | ✗ | return AVERROR(EINVAL); | |
793 | } | ||
794 | |||
795 |
2/2✓ Branch 0 taken 4678 times.
✓ Branch 1 taken 514 times.
|
5192 | if (ost->vsync_method == VSYNC_AUTO) { |
796 |
3/4✓ Branch 0 taken 4658 times.
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4658 times.
|
4678 | if (ost->frame_rate.num || ost->max_frame_rate.num) { |
797 | 20 | ost->vsync_method = VSYNC_CFR; | |
798 |
2/2✓ Branch 0 taken 284 times.
✓ Branch 1 taken 4374 times.
|
4658 | } else if (!strcmp(oc->oformat->name, "avi")) { |
799 | 284 | ost->vsync_method = VSYNC_VFR; | |
800 | } else { | ||
801 | 4374 | ost->vsync_method = (oc->oformat->flags & AVFMT_VARIABLE_FPS) ? | |
802 | 3906 | ((oc->oformat->flags & AVFMT_NOTIMESTAMPS) ? | |
803 |
4/4✓ Branch 0 taken 3906 times.
✓ Branch 1 taken 468 times.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 3893 times.
|
4374 | VSYNC_PASSTHROUGH : VSYNC_VFR) : |
804 | VSYNC_CFR; | ||
805 | } | ||
806 | |||
807 |
4/4✓ Branch 0 taken 4590 times.
✓ Branch 1 taken 88 times.
✓ Branch 2 taken 488 times.
✓ Branch 3 taken 4102 times.
|
4678 | if (ost->ist && ost->vsync_method == VSYNC_CFR) { |
808 | 488 | const InputFile *ifile = ost->ist->file; | |
809 | |||
810 |
3/4✓ Branch 0 taken 442 times.
✓ Branch 1 taken 46 times.
✓ Branch 2 taken 442 times.
✗ Branch 3 not taken.
|
488 | if (ifile->nb_streams == 1 && ifile->input_ts_offset == 0) |
811 | 442 | ost->vsync_method = VSYNC_VSCFR; | |
812 | } | ||
813 | |||
814 |
3/4✓ Branch 0 taken 46 times.
✓ Branch 1 taken 4632 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 46 times.
|
4678 | if (ost->vsync_method == VSYNC_CFR && copy_ts) { |
815 | ✗ | ost->vsync_method = VSYNC_VSCFR; | |
816 | } | ||
817 | } | ||
818 |
4/4✓ Branch 0 taken 5140 times.
✓ Branch 1 taken 52 times.
✓ Branch 2 taken 442 times.
✓ Branch 3 taken 4698 times.
|
5192 | ost->is_cfr = (ost->vsync_method == VSYNC_CFR || ost->vsync_method == VSYNC_VSCFR); |
819 | } | ||
820 | |||
821 | 5523 | return 0; | |
822 | } | ||
823 | |||
824 | 1494 | static int new_stream_audio(Muxer *mux, const OptionsContext *o, | |
825 | OutputStream *ost) | ||
826 | { | ||
827 | 1494 | AVFormatContext *oc = mux->fc; | |
828 | 1494 | AVStream *st = ost->st; | |
829 | |||
830 |
2/2✓ Branch 0 taken 1241 times.
✓ Branch 1 taken 253 times.
|
1494 | if (ost->enc_ctx) { |
831 | 1241 | AVCodecContext *audio_enc = ost->enc_ctx; | |
832 | 1241 | int channels = 0; | |
833 | 1241 | char *layout = NULL; | |
834 | 1241 | char *sample_fmt = NULL; | |
835 | 1241 | const char *apad = NULL; | |
836 | |||
837 |
4/20✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 10 times.
✓ Branch 6 taken 1241 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1241 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
1251 | MATCH_PER_STREAM_OPT(audio_channels, i, channels, oc, st); |
838 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1231 times.
|
1241 | if (channels) { |
839 | 10 | audio_enc->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; | |
840 | 10 | audio_enc->ch_layout.nb_channels = channels; | |
841 | } | ||
842 | |||
843 |
4/20✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1241 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1241 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
1242 | MATCH_PER_STREAM_OPT(audio_ch_layouts, str, layout, oc, st); |
844 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1240 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
|
1241 | if (layout && av_channel_layout_from_string(&audio_enc->ch_layout, layout) < 0) { |
845 | ✗ | av_log(ost, AV_LOG_FATAL, "Unknown channel layout: %s\n", layout); | |
846 | ✗ | return AVERROR(EINVAL); | |
847 | } | ||
848 | |||
849 |
2/20✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1241 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1241 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
1241 | MATCH_PER_STREAM_OPT(sample_fmts, str, sample_fmt, oc, st); |
850 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1241 times.
|
1241 | if (sample_fmt && |
851 | ✗ | (audio_enc->sample_fmt = av_get_sample_fmt(sample_fmt)) == AV_SAMPLE_FMT_NONE) { | |
852 | ✗ | av_log(ost, AV_LOG_FATAL, "Invalid sample format '%s'\n", sample_fmt); | |
853 | ✗ | return AVERROR(EINVAL); | |
854 | } | ||
855 | |||
856 |
4/20✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 14 times.
✓ Branch 6 taken 1241 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1241 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
1255 | MATCH_PER_STREAM_OPT(audio_sample_rate, i, audio_enc->sample_rate, oc, st); |
857 | |||
858 |
2/20✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1241 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1241 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
1241 | MATCH_PER_STREAM_OPT(apad, str, apad, oc, st); |
859 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1241 times.
|
1241 | if (apad) { |
860 | ✗ | ost->apad = av_strdup(apad); | |
861 | ✗ | if (!ost->apad) | |
862 | ✗ | return AVERROR(ENOMEM); | |
863 | } | ||
864 | } | ||
865 | |||
866 | 1494 | return 0; | |
867 | } | ||
868 | |||
869 | 71 | static int new_stream_subtitle(Muxer *mux, const OptionsContext *o, | |
870 | OutputStream *ost) | ||
871 | { | ||
872 | AVStream *st; | ||
873 | |||
874 | 71 | st = ost->st; | |
875 | |||
876 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 33 times.
|
71 | if (ost->enc_ctx) { |
877 | 38 | AVCodecContext *subtitle_enc = ost->enc_ctx; | |
878 | |||
879 | AVCodecDescriptor const *input_descriptor = | ||
880 | 38 | avcodec_descriptor_get(ost->ist->par->codec_id); | |
881 | AVCodecDescriptor const *output_descriptor = | ||
882 | 38 | avcodec_descriptor_get(subtitle_enc->codec_id); | |
883 | 38 | int input_props = 0, output_props = 0; | |
884 | |||
885 | 38 | char *frame_size = NULL; | |
886 | |||
887 |
2/20✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 38 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 38 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
38 | MATCH_PER_STREAM_OPT(frame_sizes, str, frame_size, mux->fc, st); |
888 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
|
38 | if (frame_size) { |
889 | ✗ | int ret = av_parse_video_size(&subtitle_enc->width, &subtitle_enc->height, frame_size); | |
890 | ✗ | if (ret < 0) { | |
891 | ✗ | av_log(ost, AV_LOG_FATAL, "Invalid frame size: %s.\n", frame_size); | |
892 | ✗ | return ret; | |
893 | } | ||
894 | } | ||
895 |
1/2✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
|
38 | if (input_descriptor) |
896 | 38 | input_props = input_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB); | |
897 |
1/2✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
|
38 | if (output_descriptor) |
898 | 38 | output_props = output_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB); | |
899 |
3/6✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 38 times.
|
38 | if (input_props && output_props && input_props != output_props) { |
900 | ✗ | av_log(ost, AV_LOG_ERROR, | |
901 | "Subtitle encoding currently only possible from text to text " | ||
902 | "or bitmap to bitmap\n"); | ||
903 | ✗ | return AVERROR(EINVAL); | |
904 | } | ||
905 | } | ||
906 | |||
907 | 71 | return 0; | |
908 | } | ||
909 | |||
910 | 627 | static int streamcopy_init(const Muxer *mux, OutputStream *ost) | |
911 | { | ||
912 | 627 | MuxStream *ms = ms_from_ost(ost); | |
913 | |||
914 | 627 | const InputStream *ist = ost->ist; | |
915 | 627 | const InputFile *ifile = ist->file; | |
916 | |||
917 | 627 | AVCodecParameters *par = ost->par_in; | |
918 | 627 | uint32_t codec_tag = par->codec_tag; | |
919 | |||
920 | 627 | AVCodecContext *codec_ctx = NULL; | |
921 | 627 | AVDictionary *codec_opts = NULL; | |
922 | |||
923 | 627 | AVRational fr = ost->frame_rate; | |
924 | |||
925 | 627 | int ret = 0; | |
926 | |||
927 | 627 | codec_ctx = avcodec_alloc_context3(NULL); | |
928 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
|
627 | if (!codec_ctx) |
929 | ✗ | return AVERROR(ENOMEM); | |
930 | |||
931 | 627 | ret = avcodec_parameters_to_context(codec_ctx, ist->par); | |
932 |
1/2✓ Branch 0 taken 627 times.
✗ Branch 1 not taken.
|
627 | if (ret >= 0) |
933 | 627 | ret = av_opt_set_dict(codec_ctx, &ost->encoder_opts); | |
934 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
|
627 | if (ret < 0) { |
935 | ✗ | av_log(ost, AV_LOG_FATAL, | |
936 | "Error setting up codec context options.\n"); | ||
937 | ✗ | goto fail; | |
938 | } | ||
939 | |||
940 | 627 | ret = avcodec_parameters_from_context(par, codec_ctx); | |
941 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
|
627 | if (ret < 0) { |
942 | ✗ | av_log(ost, AV_LOG_FATAL, | |
943 | "Error getting reference codec parameters.\n"); | ||
944 | ✗ | goto fail; | |
945 | } | ||
946 | |||
947 |
2/2✓ Branch 0 taken 621 times.
✓ Branch 1 taken 6 times.
|
627 | if (!codec_tag) { |
948 | 621 | const struct AVCodecTag * const *ct = mux->fc->oformat->codec_tag; | |
949 | unsigned int codec_tag_tmp; | ||
950 |
6/6✓ Branch 0 taken 112 times.
✓ Branch 1 taken 509 times.
✓ Branch 3 taken 80 times.
✓ Branch 4 taken 32 times.
✓ Branch 5 taken 11 times.
✓ Branch 6 taken 69 times.
|
701 | if (!ct || av_codec_get_id (ct, par->codec_tag) == par->codec_id || |
951 | 80 | !av_codec_get_tag2(ct, par->codec_id, &codec_tag_tmp)) | |
952 | 552 | codec_tag = par->codec_tag; | |
953 | } | ||
954 | |||
955 | 627 | par->codec_tag = codec_tag; | |
956 | |||
957 |
2/2✓ Branch 0 taken 626 times.
✓ Branch 1 taken 1 times.
|
627 | if (!fr.num) |
958 | 626 | fr = ist->framerate; | |
959 | |||
960 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 625 times.
|
627 | if (fr.num) |
961 | 2 | ost->st->avg_frame_rate = fr; | |
962 | else | ||
963 | 625 | ost->st->avg_frame_rate = ist->st->avg_frame_rate; | |
964 | |||
965 | 627 | ret = avformat_transfer_internal_stream_timing_info(mux->fc->oformat, | |
966 | 627 | ost->st, ist->st, copy_tb); | |
967 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
|
627 | if (ret < 0) |
968 | ✗ | goto fail; | |
969 | |||
970 | // copy timebase while removing common factors | ||
971 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 626 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
627 | if (ost->st->time_base.num <= 0 || ost->st->time_base.den <= 0) { |
972 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 625 times.
|
626 | if (fr.num) |
973 | 1 | ost->st->time_base = av_inv_q(fr); | |
974 | else | ||
975 | 625 | ost->st->time_base = av_add_q(av_stream_get_codec_timebase(ost->st), (AVRational){0, 1}); | |
976 | } | ||
977 | |||
978 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
|
627 | if (!ms->copy_prior_start) { |
979 | ✗ | ms->ts_copy_start = (mux->of.start_time == AV_NOPTS_VALUE) ? | |
980 | ✗ | 0 : mux->of.start_time; | |
981 | ✗ | if (copy_ts && ifile->start_time != AV_NOPTS_VALUE) { | |
982 | ✗ | ms->ts_copy_start = FFMAX(ms->ts_copy_start, | |
983 | ifile->start_time + ifile->ts_offset); | ||
984 | } | ||
985 | } | ||
986 | |||
987 |
2/2✓ Branch 0 taken 69 times.
✓ Branch 1 taken 627 times.
|
696 | for (int i = 0; i < ist->st->codecpar->nb_coded_side_data; i++) { |
988 | 69 | const AVPacketSideData *sd_src = &ist->st->codecpar->coded_side_data[i]; | |
989 | AVPacketSideData *sd_dst; | ||
990 | |||
991 | 69 | sd_dst = av_packet_side_data_new(&ost->st->codecpar->coded_side_data, | |
992 | 69 | &ost->st->codecpar->nb_coded_side_data, | |
993 | 69 | sd_src->type, sd_src->size, 0); | |
994 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 69 times.
|
69 | if (!sd_dst) { |
995 | ✗ | ret = AVERROR(ENOMEM); | |
996 | ✗ | goto fail; | |
997 | } | ||
998 | 69 | memcpy(sd_dst->data, sd_src->data, sd_src->size); | |
999 | } | ||
1000 | |||
1001 |
3/3✓ Branch 0 taken 253 times.
✓ Branch 1 taken 331 times.
✓ Branch 2 taken 43 times.
|
627 | switch (par->codec_type) { |
1002 | 253 | case AVMEDIA_TYPE_AUDIO: | |
1003 |
4/6✓ Branch 0 taken 248 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 248 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 248 times.
|
253 | if ((par->block_align == 1 || par->block_align == 1152 || par->block_align == 576) && |
1004 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | par->codec_id == AV_CODEC_ID_MP3) |
1005 | ✗ | par->block_align = 0; | |
1006 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 240 times.
|
253 | if (par->codec_id == AV_CODEC_ID_AC3) |
1007 | 13 | par->block_align = 0; | |
1008 | 253 | break; | |
1009 | 331 | case AVMEDIA_TYPE_VIDEO: { | |
1010 | AVRational sar; | ||
1011 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 331 times.
|
331 | if (ost->frame_aspect_ratio.num) { // overridden by the -aspect cli option |
1012 | sar = | ||
1013 | ✗ | av_mul_q(ost->frame_aspect_ratio, | |
1014 | ✗ | (AVRational){ par->height, par->width }); | |
1015 | ✗ | av_log(ost, AV_LOG_WARNING, "Overriding aspect ratio " | |
1016 | "with stream copy may produce invalid files\n"); | ||
1017 | } | ||
1018 |
2/2✓ Branch 0 taken 90 times.
✓ Branch 1 taken 241 times.
|
331 | else if (ist->st->sample_aspect_ratio.num) |
1019 | 90 | sar = ist->st->sample_aspect_ratio; | |
1020 | else | ||
1021 | 241 | sar = par->sample_aspect_ratio; | |
1022 | 331 | ost->st->sample_aspect_ratio = par->sample_aspect_ratio = sar; | |
1023 | 331 | ost->st->avg_frame_rate = ist->st->avg_frame_rate; | |
1024 | 331 | ost->st->r_frame_rate = ist->st->r_frame_rate; | |
1025 | 331 | break; | |
1026 | } | ||
1027 | } | ||
1028 | |||
1029 | 627 | fail: | |
1030 | 627 | avcodec_free_context(&codec_ctx); | |
1031 | 627 | av_dict_free(&codec_opts); | |
1032 | 627 | return ret; | |
1033 | } | ||
1034 | |||
1035 | 7099 | static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type, | |
1036 | InputStream *ist, OutputFilter *ofilter, | ||
1037 | OutputStream **post) | ||
1038 | { | ||
1039 | 7099 | AVFormatContext *oc = mux->fc; | |
1040 | MuxStream *ms; | ||
1041 | OutputStream *ost; | ||
1042 | const AVCodec *enc; | ||
1043 | AVStream *st; | ||
1044 | 7099 | int ret = 0; | |
1045 | 7099 | const char *bsfs = NULL, *time_base = NULL; | |
1046 | 7099 | char *filters = NULL, *next, *codec_tag = NULL; | |
1047 | 7099 | double qscale = -1; | |
1048 | |||
1049 | 7099 | st = avformat_new_stream(oc, NULL); | |
1050 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7099 times.
|
7099 | if (!st) |
1051 | ✗ | return AVERROR(ENOMEM); | |
1052 | |||
1053 | 7099 | ms = mux_stream_alloc(mux, type); | |
1054 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7099 times.
|
7099 | if (!ms) |
1055 | ✗ | return AVERROR(ENOMEM); | |
1056 | |||
1057 | // only streams with sources (i.e. not attachments) | ||
1058 | // are handled by the scheduler | ||
1059 |
4/4✓ Branch 0 taken 168 times.
✓ Branch 1 taken 6931 times.
✓ Branch 2 taken 167 times.
✓ Branch 3 taken 1 times.
|
7099 | if (ist || ofilter) { |
1060 | 7098 | ret = GROW_ARRAY(mux->sch_stream_idx, mux->nb_sch_stream_idx); | |
1061 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7098 times.
|
7098 | if (ret < 0) |
1062 | ✗ | return ret; | |
1063 | |||
1064 | 7098 | ret = sch_add_mux_stream(mux->sch, mux->sch_idx); | |
1065 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7098 times.
|
7098 | if (ret < 0) |
1066 | ✗ | return ret; | |
1067 | |||
1068 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7098 times.
|
7098 | av_assert0(ret == mux->nb_sch_stream_idx - 1); |
1069 | 7098 | mux->sch_stream_idx[ret] = ms->ost.index; | |
1070 | 7098 | ms->sch_idx = ret; | |
1071 | } | ||
1072 | |||
1073 | 7099 | ost = &ms->ost; | |
1074 | |||
1075 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 7063 times.
|
7099 | if (o->streamid) { |
1076 | AVDictionaryEntry *e; | ||
1077 | char idx[16], *p; | ||
1078 | 36 | snprintf(idx, sizeof(idx), "%d", ost->index); | |
1079 | |||
1080 | 36 | e = av_dict_get(o->streamid, idx, NULL, 0); | |
1081 |
1/2✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
|
36 | if (e) { |
1082 | 36 | st->id = strtol(e->value, &p, 0); | |
1083 |
2/4✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 36 times.
|
36 | if (!e->value[0] || *p) { |
1084 | ✗ | av_log(ost, AV_LOG_FATAL, "Invalid stream id: %s\n", e->value); | |
1085 | ✗ | return AVERROR(EINVAL); | |
1086 | } | ||
1087 | } | ||
1088 | } | ||
1089 | |||
1090 | 7099 | ost->par_in = avcodec_parameters_alloc(); | |
1091 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7099 times.
|
7099 | if (!ost->par_in) |
1092 | ✗ | return AVERROR(ENOMEM); | |
1093 | |||
1094 | 7099 | ms->last_mux_dts = AV_NOPTS_VALUE; | |
1095 | |||
1096 | 7099 | ost->st = st; | |
1097 | 7099 | ost->ist = ist; | |
1098 | 7099 | ost->kf.ref_pts = AV_NOPTS_VALUE; | |
1099 | 7099 | ost->par_in->codec_type = type; | |
1100 | 7099 | st->codecpar->codec_type = type; | |
1101 | |||
1102 | 7099 | ret = choose_encoder(o, oc, ost, &enc); | |
1103 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7099 times.
|
7099 | if (ret < 0) { |
1104 | ✗ | av_log(ost, AV_LOG_FATAL, "Error selecting an encoder\n"); | |
1105 | ✗ | return ret; | |
1106 | } | ||
1107 | |||
1108 |
2/2✓ Branch 0 taken 6471 times.
✓ Branch 1 taken 628 times.
|
7099 | if (enc) { |
1109 | 6471 | ost->enc_ctx = avcodec_alloc_context3(enc); | |
1110 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6471 times.
|
6471 | if (!ost->enc_ctx) |
1111 | ✗ | return AVERROR(ENOMEM); | |
1112 | |||
1113 | 6471 | ret = sch_add_enc(mux->sch, encoder_thread, ost, | |
1114 |
2/2✓ Branch 0 taken 6433 times.
✓ Branch 1 taken 38 times.
|
6471 | ost->type == AVMEDIA_TYPE_SUBTITLE ? NULL : enc_open); |
1115 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6471 times.
|
6471 | if (ret < 0) |
1116 | ✗ | return ret; | |
1117 | 6471 | ms->sch_idx_enc = ret; | |
1118 | |||
1119 | 6471 | ret = enc_alloc(&ost->enc, enc, mux->sch, ms->sch_idx_enc); | |
1120 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6471 times.
|
6471 | if (ret < 0) |
1121 | ✗ | return ret; | |
1122 | |||
1123 | 6471 | av_strlcat(ms->log_name, "/", sizeof(ms->log_name)); | |
1124 | 6471 | av_strlcat(ms->log_name, enc->name, sizeof(ms->log_name)); | |
1125 | } else { | ||
1126 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 628 times.
|
628 | if (ofilter) { |
1127 | ✗ | av_log(ost, AV_LOG_ERROR, | |
1128 | "Streamcopy requested for output stream fed " | ||
1129 | "from a complex filtergraph. Filtering and streamcopy " | ||
1130 | "cannot be used together.\n"); | ||
1131 | ✗ | return AVERROR(EINVAL); | |
1132 | } | ||
1133 | |||
1134 | 628 | av_strlcat(ms->log_name, "/copy", sizeof(ms->log_name)); | |
1135 | } | ||
1136 | |||
1137 | 7099 | av_log(ost, AV_LOG_VERBOSE, "Created %s stream from ", | |
1138 | av_get_media_type_string(type)); | ||
1139 |
2/2✓ Branch 0 taken 6931 times.
✓ Branch 1 taken 168 times.
|
7099 | if (ist) |
1140 | 6931 | av_log(ost, AV_LOG_VERBOSE, "input stream %d:%d", | |
1141 | 6931 | ist->file->index, ist->index); | |
1142 |
2/2✓ Branch 0 taken 167 times.
✓ Branch 1 taken 1 times.
|
168 | else if (ofilter) |
1143 | 167 | av_log(ost, AV_LOG_VERBOSE, "complex filtergraph %d:[%s]\n", | |
1144 | 167 | ofilter->graph->index, ofilter->name); | |
1145 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | else if (type == AVMEDIA_TYPE_ATTACHMENT) |
1146 | 1 | av_log(ost, AV_LOG_VERBOSE, "attached file"); | |
1147 | ✗ | else av_assert0(0); | |
1148 | 7099 | av_log(ost, AV_LOG_VERBOSE, "\n"); | |
1149 | |||
1150 | 7099 | ms->pkt = av_packet_alloc(); | |
1151 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7099 times.
|
7099 | if (!ms->pkt) |
1152 | ✗ | return AVERROR(ENOMEM); | |
1153 | |||
1154 |
2/2✓ Branch 0 taken 6471 times.
✓ Branch 1 taken 628 times.
|
7099 | if (ost->enc_ctx) { |
1155 | 6471 | AVCodecContext *enc = ost->enc_ctx; | |
1156 | 6471 | AVIOContext *s = NULL; | |
1157 | 6471 | char *buf = NULL, *arg = NULL, *preset = NULL; | |
1158 | 6471 | const char *enc_stats_pre = NULL, *enc_stats_post = NULL, *mux_stats = NULL; | |
1159 | 6471 | const char *enc_time_base = NULL; | |
1160 | |||
1161 | 6471 | ret = filter_codec_opts(o->g->codec_opts, enc->codec_id, | |
1162 | 6471 | oc, st, enc->codec, &ost->encoder_opts); | |
1163 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6471 times.
|
6471 | if (ret < 0) |
1164 | ✗ | return ret; | |
1165 | |||
1166 |
2/20✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 6471 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6471 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
6471 | MATCH_PER_STREAM_OPT(presets, str, preset, oc, st); |
1167 | 6471 | ost->autoscale = 1; | |
1168 |
2/20✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 6471 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6471 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
6471 | MATCH_PER_STREAM_OPT(autoscale, i, ost->autoscale, oc, st); |
1169 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 6471 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
6471 | if (preset && (!(ret = get_preset_file_2(preset, enc->codec->name, &s)))) { |
1170 | AVBPrint bprint; | ||
1171 | ✗ | av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED); | |
1172 | do { | ||
1173 | ✗ | av_bprint_clear(&bprint); | |
1174 | ✗ | buf = get_line(s, &bprint); | |
1175 | ✗ | if (!buf) { | |
1176 | ✗ | ret = AVERROR(ENOMEM); | |
1177 | ✗ | break; | |
1178 | } | ||
1179 | |||
1180 | ✗ | if (!buf[0] || buf[0] == '#') | |
1181 | ✗ | continue; | |
1182 | ✗ | if (!(arg = strchr(buf, '='))) { | |
1183 | ✗ | av_log(ost, AV_LOG_FATAL, "Invalid line found in the preset file.\n"); | |
1184 | ✗ | ret = AVERROR(EINVAL); | |
1185 | ✗ | break; | |
1186 | } | ||
1187 | ✗ | *arg++ = 0; | |
1188 | ✗ | av_dict_set(&ost->encoder_opts, buf, arg, AV_DICT_DONT_OVERWRITE); | |
1189 | ✗ | } while (!s->eof_reached); | |
1190 | ✗ | av_bprint_finalize(&bprint, NULL); | |
1191 | ✗ | avio_closep(&s); | |
1192 | } | ||
1193 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6471 times.
|
6471 | if (ret) { |
1194 | ✗ | av_log(ost, AV_LOG_FATAL, | |
1195 | "Preset %s specified, but could not be opened.\n", preset); | ||
1196 | ✗ | return ret; | |
1197 | } | ||
1198 | |||
1199 |
2/20✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 6471 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6471 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
6471 | MATCH_PER_STREAM_OPT(enc_stats_pre, str, enc_stats_pre, oc, st); |
1200 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 6471 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
6471 | if (enc_stats_pre && |
1201 | ✗ | (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) { | |
1202 | ✗ | const char *format = "{fidx} {sidx} {n} {t}"; | |
1203 | |||
1204 | ✗ | MATCH_PER_STREAM_OPT(enc_stats_pre_fmt, str, format, oc, st); | |
1205 | |||
1206 | ✗ | ret = enc_stats_init(ost, &ost->enc_stats_pre, 1, enc_stats_pre, format); | |
1207 | ✗ | if (ret < 0) | |
1208 | ✗ | return ret; | |
1209 | } | ||
1210 | |||
1211 |
2/20✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 6471 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6471 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
6471 | MATCH_PER_STREAM_OPT(enc_stats_post, str, enc_stats_post, oc, st); |
1212 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 6471 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
6471 | if (enc_stats_post && |
1213 | ✗ | (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) { | |
1214 | ✗ | const char *format = "{fidx} {sidx} {n} {t}"; | |
1215 | |||
1216 | ✗ | MATCH_PER_STREAM_OPT(enc_stats_post_fmt, str, format, oc, st); | |
1217 | |||
1218 | ✗ | ret = enc_stats_init(ost, &ost->enc_stats_post, 0, enc_stats_post, format); | |
1219 | ✗ | if (ret < 0) | |
1220 | ✗ | return ret; | |
1221 | } | ||
1222 | |||
1223 |
2/20✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 6471 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6471 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
6471 | MATCH_PER_STREAM_OPT(mux_stats, str, mux_stats, oc, st); |
1224 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 6471 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
6471 | if (mux_stats && |
1225 | ✗ | (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) { | |
1226 | ✗ | const char *format = "{fidx} {sidx} {n} {t}"; | |
1227 | |||
1228 | ✗ | MATCH_PER_STREAM_OPT(mux_stats_fmt, str, format, oc, st); | |
1229 | |||
1230 | ✗ | ret = enc_stats_init(ost, &ms->stats, 0, mux_stats, format); | |
1231 | ✗ | if (ret < 0) | |
1232 | ✗ | return ret; | |
1233 | } | ||
1234 | |||
1235 |
4/20✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 6471 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6471 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
6472 | MATCH_PER_STREAM_OPT(enc_time_bases, str, enc_time_base, oc, st); |
1236 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6470 times.
|
6471 | if (enc_time_base) { |
1237 | AVRational q; | ||
1238 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (!strcmp(enc_time_base, "demux")) { |
1239 | 1 | q = (AVRational){ ENC_TIME_BASE_DEMUX, 0 }; | |
1240 | ✗ | } else if (!strcmp(enc_time_base, "filter")) { | |
1241 | ✗ | q = (AVRational){ ENC_TIME_BASE_FILTER, 0 }; | |
1242 | } else { | ||
1243 | ✗ | ret = av_parse_ratio(&q, enc_time_base, INT_MAX, 0, NULL); | |
1244 | ✗ | if (ret < 0 || q.den <= 0 | |
1245 | #if !FFMPEG_OPT_ENC_TIME_BASE_NUM | ||
1246 | || q.num < 0 | ||
1247 | #endif | ||
1248 | ) { | ||
1249 | ✗ | av_log(ost, AV_LOG_FATAL, "Invalid time base: %s\n", enc_time_base); | |
1250 | ✗ | return ret < 0 ? ret : AVERROR(EINVAL); | |
1251 | } | ||
1252 | #if FFMPEG_OPT_ENC_TIME_BASE_NUM | ||
1253 | ✗ | if (q.num < 0) | |
1254 | ✗ | av_log(ost, AV_LOG_WARNING, "-enc_time_base -1 is deprecated," | |
1255 | " use -enc_timebase demux\n"); | ||
1256 | #endif | ||
1257 | } | ||
1258 | |||
1259 | 1 | ost->enc_timebase = q; | |
1260 | } | ||
1261 | } else { | ||
1262 | 628 | ret = filter_codec_opts(o->g->codec_opts, AV_CODEC_ID_NONE, oc, st, | |
1263 | NULL, &ost->encoder_opts); | ||
1264 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 628 times.
|
628 | if (ret < 0) |
1265 | ✗ | return ret; | |
1266 | } | ||
1267 | |||
1268 | |||
1269 |
2/2✓ Branch 0 taken 1857 times.
✓ Branch 1 taken 5242 times.
|
7099 | if (o->bitexact) { |
1270 | 1857 | ost->bitexact = 1; | |
1271 |
2/2✓ Branch 0 taken 4722 times.
✓ Branch 1 taken 520 times.
|
5242 | } else if (ost->enc_ctx) { |
1272 | 4722 | ost->bitexact = check_opt_bitexact(ost->enc_ctx, ost->encoder_opts, "flags", | |
1273 | AV_CODEC_FLAG_BITEXACT); | ||
1274 | } | ||
1275 | |||
1276 |
4/20✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 7099 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7099 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
7102 | MATCH_PER_STREAM_OPT(time_bases, str, time_base, oc, st); |
1277 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 7096 times.
|
7099 | if (time_base) { |
1278 | AVRational q; | ||
1279 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | if (av_parse_ratio(&q, time_base, INT_MAX, 0, NULL) < 0 || |
1280 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
|
3 | q.num <= 0 || q.den <= 0) { |
1281 | ✗ | av_log(ost, AV_LOG_FATAL, "Invalid time base: %s\n", time_base); | |
1282 | ✗ | return AVERROR(EINVAL); | |
1283 | } | ||
1284 | 3 | st->time_base = q; | |
1285 | } | ||
1286 | |||
1287 | 7099 | ms->max_frames = INT64_MAX; | |
1288 |
14/20✓ Branch 1 taken 4811 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 4815 times.
✓ Branch 6 taken 7099 times.
✓ Branch 7 taken 2141 times.
✓ Branch 8 taken 4958 times.
✓ Branch 9 taken 2141 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 2141 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 2141 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 2141 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 6423 times.
✓ Branch 19 taken 2141 times.
✓ Branch 20 taken 2141 times.
✗ Branch 21 not taken.
|
18337 | MATCH_PER_STREAM_OPT(max_frames, i64, ms->max_frames, oc, st); |
1289 |
2/2✓ Branch 0 taken 4815 times.
✓ Branch 1 taken 7093 times.
|
11908 | for (int i = 0; i < o->max_frames.nb_opt; i++) { |
1290 | 4815 | char *p = o->max_frames.opt[i].specifier; | |
1291 |
4/4✓ Branch 0 taken 169 times.
✓ Branch 1 taken 4646 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 163 times.
|
4815 | if (!*p && type != AVMEDIA_TYPE_VIDEO) { |
1292 | 6 | av_log(ost, AV_LOG_WARNING, "Applying unspecific -frames to non video streams, maybe you meant -vframes ?\n"); | |
1293 | 6 | break; | |
1294 | } | ||
1295 | } | ||
1296 | |||
1297 | 7099 | ms->copy_prior_start = -1; | |
1298 |
2/20✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 7099 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7099 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
7099 | MATCH_PER_STREAM_OPT(copy_prior_start, i, ms->copy_prior_start, oc ,st); |
1299 | |||
1300 |
6/20✓ Branch 1 taken 132 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 142 times.
✓ Branch 6 taken 7099 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7099 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
7241 | MATCH_PER_STREAM_OPT(bitstream_filters, str, bsfs, oc, st); |
1301 |
3/4✓ Branch 0 taken 132 times.
✓ Branch 1 taken 6967 times.
✓ Branch 2 taken 132 times.
✗ Branch 3 not taken.
|
7099 | if (bsfs && *bsfs) { |
1302 | 132 | ret = av_bsf_list_parse_str(bsfs, &ms->bsf_ctx); | |
1303 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 132 times.
|
132 | if (ret < 0) { |
1304 | ✗ | av_log(ost, AV_LOG_ERROR, "Error parsing bitstream filter sequence '%s': %s\n", bsfs, av_err2str(ret)); | |
1305 | ✗ | return ret; | |
1306 | } | ||
1307 | } | ||
1308 | |||
1309 |
4/20✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 7 times.
✓ Branch 6 taken 7099 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7099 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
7106 | MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, oc, st); |
1310 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7092 times.
|
7099 | if (codec_tag) { |
1311 | 7 | uint32_t tag = strtol(codec_tag, &next, 0); | |
1312 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | if (*next) { |
1313 | 7 | uint8_t buf[4] = { 0 }; | |
1314 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | memcpy(buf, codec_tag, FFMIN(sizeof(buf), strlen(codec_tag))); |
1315 | 7 | tag = AV_RL32(buf); | |
1316 | } | ||
1317 | 7 | ost->st->codecpar->codec_tag = tag; | |
1318 | 7 | ost->par_in->codec_tag = tag; | |
1319 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
|
7 | if (ost->enc_ctx) |
1320 | 1 | ost->enc_ctx->codec_tag = tag; | |
1321 | } | ||
1322 | |||
1323 |
14/20✓ Branch 1 taken 266 times.
✓ Branch 2 taken 55 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 55 times.
✓ Branch 5 taken 321 times.
✓ Branch 6 taken 7099 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 7098 times.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✓ Branch 19 taken 1 times.
✓ Branch 20 taken 1 times.
✗ Branch 21 not taken.
|
7421 | MATCH_PER_STREAM_OPT(qscale, dbl, qscale, oc, st); |
1324 |
4/4✓ Branch 0 taken 6471 times.
✓ Branch 1 taken 628 times.
✓ Branch 2 taken 265 times.
✓ Branch 3 taken 6206 times.
|
7099 | if (ost->enc_ctx && qscale >= 0) { |
1325 | 265 | ost->enc_ctx->flags |= AV_CODEC_FLAG_QSCALE; | |
1326 | 265 | ost->enc_ctx->global_quality = FF_QP2LAMBDA * qscale; | |
1327 | } | ||
1328 | |||
1329 |
2/2✓ Branch 0 taken 7098 times.
✓ Branch 1 taken 1 times.
|
7099 | if (ms->sch_idx >= 0) { |
1330 | 7098 | int max_muxing_queue_size = 128; | |
1331 | 7098 | int muxing_queue_data_threshold = 50 * 1024 * 1024; | |
1332 | |||
1333 |
4/20✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 7098 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7098 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
7100 | MATCH_PER_STREAM_OPT(max_muxing_queue_size, i, max_muxing_queue_size, oc, st); |
1334 |
2/20✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 7098 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7098 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
7098 | MATCH_PER_STREAM_OPT(muxing_queue_data_threshold, i, muxing_queue_data_threshold, oc, st); |
1335 | |||
1336 | 7098 | sch_mux_stream_buffering(mux->sch, mux->sch_idx, ms->sch_idx, | |
1337 | max_muxing_queue_size, muxing_queue_data_threshold); | ||
1338 | } | ||
1339 | |||
1340 |
4/20✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 7099 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7099 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
7100 | MATCH_PER_STREAM_OPT(bits_per_raw_sample, i, ost->bits_per_raw_sample, |
1341 | oc, st); | ||
1342 | |||
1343 |
6/20✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 7099 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7099 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
7101 | MATCH_PER_STREAM_OPT(fix_sub_duration_heartbeat, i, ost->fix_sub_duration_heartbeat, |
1344 | oc, st); | ||
1345 | |||
1346 |
4/4✓ Branch 0 taken 2747 times.
✓ Branch 1 taken 4352 times.
✓ Branch 2 taken 2651 times.
✓ Branch 3 taken 96 times.
|
7099 | if (oc->oformat->flags & AVFMT_GLOBALHEADER && ost->enc_ctx) |
1347 | 2651 | ost->enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; | |
1348 | |||
1349 | 7099 | av_dict_copy(&ost->sws_dict, o->g->sws_dict, 0); | |
1350 | |||
1351 | 7099 | av_dict_copy(&ost->swr_opts, o->g->swr_opts, 0); | |
1352 |
4/4✓ Branch 0 taken 6471 times.
✓ Branch 1 taken 628 times.
✓ Branch 3 taken 59 times.
✓ Branch 4 taken 6412 times.
|
7099 | if (ost->enc_ctx && av_get_exact_bits_per_sample(ost->enc_ctx->codec_id) == 24) |
1353 | 59 | av_dict_set(&ost->swr_opts, "output_sample_bits", "24", 0); | |
1354 | |||
1355 |
2/20✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 7099 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7099 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
7099 | MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, |
1356 | ms->copy_initial_nonkeyframes, oc, st); | ||
1357 | |||
1358 |
4/4✓ Branch 0 taken 5523 times.
✓ Branch 1 taken 1494 times.
✓ Branch 2 taken 71 times.
✓ Branch 3 taken 11 times.
|
7099 | switch (type) { |
1359 | 5523 | case AVMEDIA_TYPE_VIDEO: ret = new_stream_video (mux, o, ost); break; | |
1360 | 1494 | case AVMEDIA_TYPE_AUDIO: ret = new_stream_audio (mux, o, ost); break; | |
1361 | 71 | case AVMEDIA_TYPE_SUBTITLE: ret = new_stream_subtitle (mux, o, ost); break; | |
1362 | } | ||
1363 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7099 times.
|
7099 | if (ret < 0) |
1364 | ✗ | return ret; | |
1365 | |||
1366 |
4/4✓ Branch 0 taken 1576 times.
✓ Branch 1 taken 5523 times.
✓ Branch 2 taken 1494 times.
✓ Branch 3 taken 82 times.
|
7099 | if (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO) { |
1367 | 7017 | ret = ost_get_filters(o, oc, ost, &filters); | |
1368 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7017 times.
|
7017 | if (ret < 0) |
1369 | ✗ | return ret; | |
1370 | } | ||
1371 | |||
1372 |
4/4✓ Branch 0 taken 6471 times.
✓ Branch 1 taken 628 times.
✓ Branch 2 taken 1279 times.
✓ Branch 3 taken 5192 times.
|
7099 | if (ost->enc && |
1373 |
2/2✓ Branch 0 taken 1241 times.
✓ Branch 1 taken 38 times.
|
7712 | (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) { |
1374 |
2/2✓ Branch 0 taken 167 times.
✓ Branch 1 taken 6266 times.
|
6433 | if (ofilter) { |
1375 | 167 | ost->filter = ofilter; | |
1376 | 167 | ret = ofilter_bind_ost(ofilter, ost, ms->sch_idx_enc); | |
1377 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 167 times.
|
167 | if (ret < 0) |
1378 | ✗ | return ret; | |
1379 | } else { | ||
1380 | 6266 | ret = init_simple_filtergraph(ost->ist, ost, filters, | |
1381 | 6266 | mux->sch, ms->sch_idx_enc); | |
1382 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6266 times.
|
6266 | if (ret < 0) { |
1383 | ✗ | av_log(ost, AV_LOG_ERROR, | |
1384 | "Error initializing a simple filtergraph\n"); | ||
1385 | ✗ | return ret; | |
1386 | } | ||
1387 | } | ||
1388 | |||
1389 | 6433 | ret = sch_connect(mux->sch, SCH_ENC(ms->sch_idx_enc), | |
1390 | 6433 | SCH_MSTREAM(mux->sch_idx, ms->sch_idx)); | |
1391 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6433 times.
|
6433 | if (ret < 0) |
1392 | ✗ | return ret; | |
1393 |
2/2✓ Branch 0 taken 665 times.
✓ Branch 1 taken 1 times.
|
666 | } else if (ost->ist) { |
1394 | 665 | int sched_idx = ist_output_add(ost->ist, ost); | |
1395 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
|
665 | if (sched_idx < 0) { |
1396 | ✗ | av_log(ost, AV_LOG_ERROR, | |
1397 | "Error binding an input stream\n"); | ||
1398 | ✗ | return sched_idx; | |
1399 | } | ||
1400 | 665 | ms->sch_idx_src = sched_idx; | |
1401 | |||
1402 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 627 times.
|
665 | if (ost->enc) { |
1403 | 38 | ret = sch_connect(mux->sch, SCH_DEC(sched_idx), | |
1404 | 38 | SCH_ENC(ms->sch_idx_enc)); | |
1405 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
|
38 | if (ret < 0) |
1406 | ✗ | return ret; | |
1407 | |||
1408 | 38 | ret = sch_connect(mux->sch, SCH_ENC(ms->sch_idx_enc), | |
1409 | 38 | SCH_MSTREAM(mux->sch_idx, ms->sch_idx)); | |
1410 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
|
38 | if (ret < 0) |
1411 | ✗ | return ret; | |
1412 | } else { | ||
1413 | 627 | ret = sch_connect(mux->sch, SCH_DSTREAM(ost->ist->file->index, sched_idx), | |
1414 | 627 | SCH_MSTREAM(ost->file->index, ms->sch_idx)); | |
1415 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
|
627 | if (ret < 0) |
1416 | ✗ | return ret; | |
1417 | } | ||
1418 | } | ||
1419 | |||
1420 |
4/4✓ Branch 0 taken 6931 times.
✓ Branch 1 taken 168 times.
✓ Branch 2 taken 627 times.
✓ Branch 3 taken 6304 times.
|
7099 | if (ost->ist && !ost->enc) { |
1421 | 627 | ret = streamcopy_init(mux, ost); | |
1422 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 627 times.
|
627 | if (ret < 0) |
1423 | ✗ | return ret; | |
1424 | } | ||
1425 | |||
1426 | // copy estimated duration as a hint to the muxer | ||
1427 |
4/4✓ Branch 0 taken 6931 times.
✓ Branch 1 taken 168 times.
✓ Branch 2 taken 5431 times.
✓ Branch 3 taken 1500 times.
|
7099 | if (ost->ist && ost->ist->st->duration > 0) { |
1428 | 5431 | ms->stream_duration = ist->st->duration; | |
1429 | 5431 | ms->stream_duration_tb = ist->st->time_base; | |
1430 | } | ||
1431 | |||
1432 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7098 times.
|
7099 | if (post) |
1433 | 1 | *post = ost; | |
1434 | |||
1435 | 7099 | return 0; | |
1436 | } | ||
1437 | |||
1438 | 6364 | static int map_auto_video(Muxer *mux, const OptionsContext *o) | |
1439 | { | ||
1440 | 6364 | AVFormatContext *oc = mux->fc; | |
1441 | 6364 | InputStream *best_ist = NULL; | |
1442 | 6364 | int best_score = 0; | |
1443 | int qcr; | ||
1444 | |||
1445 | /* video: highest resolution */ | ||
1446 |
2/2✓ Branch 1 taken 731 times.
✓ Branch 2 taken 5633 times.
|
6364 | if (av_guess_codec(oc->oformat, NULL, oc->url, NULL, AVMEDIA_TYPE_VIDEO) == AV_CODEC_ID_NONE) |
1447 | 731 | return 0; | |
1448 | |||
1449 | 5633 | qcr = avformat_query_codec(oc->oformat, oc->oformat->video_codec, 0); | |
1450 |
2/2✓ Branch 0 taken 5673 times.
✓ Branch 1 taken 5633 times.
|
11306 | for (int j = 0; j < nb_input_files; j++) { |
1451 | 5673 | InputFile *ifile = input_files[j]; | |
1452 | 5673 | InputStream *file_best_ist = NULL; | |
1453 | 5673 | int file_best_score = 0; | |
1454 |
2/2✓ Branch 0 taken 5950 times.
✓ Branch 1 taken 5673 times.
|
11623 | for (int i = 0; i < ifile->nb_streams; i++) { |
1455 | 5950 | InputStream *ist = ifile->streams[i]; | |
1456 | int score; | ||
1457 | |||
1458 |
2/2✓ Branch 0 taken 5949 times.
✓ Branch 1 taken 1 times.
|
5950 | if (ist->user_set_discard == AVDISCARD_ALL || |
1459 |
2/2✓ Branch 0 taken 630 times.
✓ Branch 1 taken 5319 times.
|
5949 | ist->st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO) |
1460 | 631 | continue; | |
1461 | |||
1462 | 10638 | score = ist->st->codecpar->width * ist->st->codecpar->height | |
1463 |
2/2✓ Branch 0 taken 5317 times.
✓ Branch 1 taken 2 times.
|
5319 | + 100000000 * !!(ist->st->event_flags & AVSTREAM_EVENT_FLAG_NEW_PACKETS) |
1464 |
2/2✓ Branch 0 taken 509 times.
✓ Branch 1 taken 4810 times.
|
5319 | + 5000000*!!(ist->st->disposition & AV_DISPOSITION_DEFAULT); |
1465 |
3/4✓ Branch 0 taken 5319 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 5310 times.
|
5319 | if((qcr!=MKTAG('A', 'P', 'I', 'C')) && (ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC)) |
1466 | 9 | score = 1; | |
1467 | |||
1468 |
2/2✓ Branch 0 taken 5318 times.
✓ Branch 1 taken 1 times.
|
5319 | if (score > file_best_score) { |
1469 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 5318 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
5318 | if((qcr==MKTAG('A', 'P', 'I', 'C')) && !(ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC)) |
1470 | ✗ | continue; | |
1471 | 5318 | file_best_score = score; | |
1472 | 5318 | file_best_ist = ist; | |
1473 | } | ||
1474 | } | ||
1475 |
2/2✓ Branch 0 taken 5318 times.
✓ Branch 1 taken 355 times.
|
5673 | if (file_best_ist) { |
1476 |
1/2✓ Branch 0 taken 5318 times.
✗ Branch 1 not taken.
|
5318 | if((qcr == MKTAG('A', 'P', 'I', 'C')) || |
1477 |
2/2✓ Branch 0 taken 5310 times.
✓ Branch 1 taken 8 times.
|
5318 | !(file_best_ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC)) |
1478 |
2/2✓ Branch 0 taken 509 times.
✓ Branch 1 taken 4801 times.
|
5310 | file_best_score -= 5000000*!!(file_best_ist->st->disposition & AV_DISPOSITION_DEFAULT); |
1479 |
1/2✓ Branch 0 taken 5318 times.
✗ Branch 1 not taken.
|
5318 | if (file_best_score > best_score) { |
1480 | 5318 | best_score = file_best_score; | |
1481 | 5318 | best_ist = file_best_ist; | |
1482 | } | ||
1483 | } | ||
1484 | } | ||
1485 |
2/2✓ Branch 0 taken 5318 times.
✓ Branch 1 taken 315 times.
|
5633 | if (best_ist) |
1486 | 5318 | return ost_add(mux, o, AVMEDIA_TYPE_VIDEO, best_ist, NULL, NULL); | |
1487 | |||
1488 | 315 | return 0; | |
1489 | } | ||
1490 | |||
1491 | 6453 | static int map_auto_audio(Muxer *mux, const OptionsContext *o) | |
1492 | { | ||
1493 | 6453 | AVFormatContext *oc = mux->fc; | |
1494 | 6453 | InputStream *best_ist = NULL; | |
1495 | 6453 | int best_score = 0; | |
1496 | |||
1497 | /* audio: most channels */ | ||
1498 |
2/2✓ Branch 1 taken 842 times.
✓ Branch 2 taken 5611 times.
|
6453 | if (av_guess_codec(oc->oformat, NULL, oc->url, NULL, AVMEDIA_TYPE_AUDIO) == AV_CODEC_ID_NONE) |
1499 | 842 | return 0; | |
1500 | |||
1501 |
2/2✓ Branch 0 taken 5610 times.
✓ Branch 1 taken 5611 times.
|
11221 | for (int j = 0; j < nb_input_files; j++) { |
1502 | 5610 | InputFile *ifile = input_files[j]; | |
1503 | 5610 | InputStream *file_best_ist = NULL; | |
1504 | 5610 | int file_best_score = 0; | |
1505 |
2/2✓ Branch 0 taken 5813 times.
✓ Branch 1 taken 5610 times.
|
11423 | for (int i = 0; i < ifile->nb_streams; i++) { |
1506 | 5813 | InputStream *ist = ifile->streams[i]; | |
1507 | int score; | ||
1508 | |||
1509 |
2/2✓ Branch 0 taken 5812 times.
✓ Branch 1 taken 1 times.
|
5813 | if (ist->user_set_discard == AVDISCARD_ALL || |
1510 |
2/2✓ Branch 0 taken 4522 times.
✓ Branch 1 taken 1290 times.
|
5812 | ist->st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) |
1511 | 4523 | continue; | |
1512 | |||
1513 | 2580 | score = ist->st->codecpar->ch_layout.nb_channels | |
1514 |
2/2✓ Branch 0 taken 1289 times.
✓ Branch 1 taken 1 times.
|
1290 | + 100000000 * !!(ist->st->event_flags & AVSTREAM_EVENT_FLAG_NEW_PACKETS) |
1515 |
2/2✓ Branch 0 taken 171 times.
✓ Branch 1 taken 1119 times.
|
1290 | + 5000000*!!(ist->st->disposition & AV_DISPOSITION_DEFAULT); |
1516 |
2/2✓ Branch 0 taken 1280 times.
✓ Branch 1 taken 10 times.
|
1290 | if (score > file_best_score) { |
1517 | 1280 | file_best_score = score; | |
1518 | 1280 | file_best_ist = ist; | |
1519 | } | ||
1520 | } | ||
1521 |
2/2✓ Branch 0 taken 1280 times.
✓ Branch 1 taken 4330 times.
|
5610 | if (file_best_ist) { |
1522 |
2/2✓ Branch 0 taken 171 times.
✓ Branch 1 taken 1109 times.
|
1280 | file_best_score -= 5000000*!!(file_best_ist->st->disposition & AV_DISPOSITION_DEFAULT); |
1523 |
1/2✓ Branch 0 taken 1280 times.
✗ Branch 1 not taken.
|
1280 | if (file_best_score > best_score) { |
1524 | 1280 | best_score = file_best_score; | |
1525 | 1280 | best_ist = file_best_ist; | |
1526 | } | ||
1527 | } | ||
1528 | } | ||
1529 |
2/2✓ Branch 0 taken 1280 times.
✓ Branch 1 taken 4331 times.
|
5611 | if (best_ist) |
1530 | 1280 | return ost_add(mux, o, AVMEDIA_TYPE_AUDIO, best_ist, NULL, NULL); | |
1531 | |||
1532 | 4331 | return 0; | |
1533 | } | ||
1534 | |||
1535 | 6610 | static int map_auto_subtitle(Muxer *mux, const OptionsContext *o) | |
1536 | { | ||
1537 | 6610 | AVFormatContext *oc = mux->fc; | |
1538 | 6610 | const char *subtitle_codec_name = NULL; | |
1539 | |||
1540 | /* subtitles: pick first */ | ||
1541 | 6610 | subtitle_codec_name = opt_match_per_type_str(&o->codec_names, 's'); | |
1542 |
4/4✓ Branch 1 taken 6550 times.
✓ Branch 2 taken 60 times.
✓ Branch 3 taken 6543 times.
✓ Branch 4 taken 7 times.
|
6610 | if (!avcodec_find_encoder(oc->oformat->subtitle_codec) && !subtitle_codec_name) |
1543 | 6543 | return 0; | |
1544 | |||
1545 |
2/2✓ Branch 2 taken 81 times.
✓ Branch 3 taken 19 times.
|
100 | for (InputStream *ist = ist_iter(NULL); ist; ist = ist_iter(ist)) |
1546 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 33 times.
|
81 | if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) { |
1547 | AVCodecDescriptor const *input_descriptor = | ||
1548 | 48 | avcodec_descriptor_get(ist->st->codecpar->codec_id); | |
1549 | 48 | AVCodecDescriptor const *output_descriptor = NULL; | |
1550 | AVCodec const *output_codec = | ||
1551 | 48 | avcodec_find_encoder(oc->oformat->subtitle_codec); | |
1552 | 48 | int input_props = 0, output_props = 0; | |
1553 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
|
48 | if (ist->user_set_discard == AVDISCARD_ALL) |
1554 | ✗ | continue; | |
1555 |
2/2✓ Branch 0 taken 41 times.
✓ Branch 1 taken 7 times.
|
48 | if (output_codec) |
1556 | 41 | output_descriptor = avcodec_descriptor_get(output_codec->id); | |
1557 |
1/2✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
|
48 | if (input_descriptor) |
1558 | 48 | input_props = input_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB); | |
1559 |
2/2✓ Branch 0 taken 41 times.
✓ Branch 1 taken 7 times.
|
48 | if (output_descriptor) |
1560 | 41 | output_props = output_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB); | |
1561 |
2/2✓ Branch 0 taken 32 times.
✓ Branch 1 taken 16 times.
|
48 | if (subtitle_codec_name || |
1562 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
32 | input_props & output_props || |
1563 | // Map dvb teletext which has neither property to any output subtitle encoder | ||
1564 | ✗ | input_descriptor && output_descriptor && | |
1565 | ✗ | (!input_descriptor->props || | |
1566 | ✗ | !output_descriptor->props)) { | |
1567 | 48 | return ost_add(mux, o, AVMEDIA_TYPE_SUBTITLE, ist, NULL, NULL); | |
1568 | } | ||
1569 | } | ||
1570 | |||
1571 | 19 | return 0; | |
1572 | } | ||
1573 | |||
1574 | 6611 | static int map_auto_data(Muxer *mux, const OptionsContext *o) | |
1575 | { | ||
1576 | 6611 | AVFormatContext *oc = mux->fc; | |
1577 | /* Data only if codec id match */ | ||
1578 | 6611 | enum AVCodecID codec_id = av_guess_codec(oc->oformat, NULL, oc->url, NULL, AVMEDIA_TYPE_DATA); | |
1579 | |||
1580 |
1/2✓ Branch 0 taken 6611 times.
✗ Branch 1 not taken.
|
6611 | if (codec_id == AV_CODEC_ID_NONE) |
1581 | 6611 | return 0; | |
1582 | |||
1583 | ✗ | for (InputStream *ist = ist_iter(NULL); ist; ist = ist_iter(ist)) { | |
1584 | ✗ | if (ist->user_set_discard == AVDISCARD_ALL) | |
1585 | ✗ | continue; | |
1586 | ✗ | if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_DATA && | |
1587 | ✗ | ist->st->codecpar->codec_id == codec_id) { | |
1588 | ✗ | int ret = ost_add(mux, o, AVMEDIA_TYPE_DATA, ist, NULL, NULL); | |
1589 | ✗ | if (ret < 0) | |
1590 | ✗ | return ret; | |
1591 | } | ||
1592 | } | ||
1593 | |||
1594 | ✗ | return 0; | |
1595 | } | ||
1596 | |||
1597 | 339 | static int map_manual(Muxer *mux, const OptionsContext *o, const StreamMap *map) | |
1598 | { | ||
1599 | InputStream *ist; | ||
1600 | int ret; | ||
1601 | |||
1602 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 339 times.
|
339 | if (map->disabled) |
1603 | ✗ | return 0; | |
1604 | |||
1605 |
2/2✓ Branch 0 taken 54 times.
✓ Branch 1 taken 285 times.
|
339 | if (map->linklabel) { |
1606 | FilterGraph *fg; | ||
1607 | 54 | OutputFilter *ofilter = NULL; | |
1608 | int j, k; | ||
1609 | |||
1610 |
1/2✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
|
54 | for (j = 0; j < nb_filtergraphs; j++) { |
1611 | 54 | fg = filtergraphs[j]; | |
1612 |
1/2✓ Branch 0 taken 176 times.
✗ Branch 1 not taken.
|
176 | for (k = 0; k < fg->nb_outputs; k++) { |
1613 | 176 | const char *linklabel = fg->outputs[k]->linklabel; | |
1614 |
3/4✓ Branch 0 taken 54 times.
✓ Branch 1 taken 122 times.
✓ Branch 2 taken 54 times.
✗ Branch 3 not taken.
|
176 | if (linklabel && !strcmp(linklabel, map->linklabel)) { |
1615 | 54 | ofilter = fg->outputs[k]; | |
1616 | 54 | goto loop_end; | |
1617 | } | ||
1618 | } | ||
1619 | } | ||
1620 | ✗ | loop_end: | |
1621 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
|
54 | if (!ofilter) { |
1622 | ✗ | av_log(mux, AV_LOG_FATAL, "Output with label '%s' does not exist " | |
1623 | ✗ | "in any defined filter graph, or was already used elsewhere.\n", map->linklabel); | |
1624 | ✗ | return AVERROR(EINVAL); | |
1625 | } | ||
1626 | |||
1627 | 54 | av_log(mux, AV_LOG_VERBOSE, "Creating output stream from an explicitly " | |
1628 | 54 | "mapped complex filtergraph %d, output [%s]\n", fg->index, map->linklabel); | |
1629 | |||
1630 | 54 | ret = ost_add(mux, o, ofilter->type, NULL, ofilter, NULL); | |
1631 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
|
54 | if (ret < 0) |
1632 | ✗ | return ret; | |
1633 | } else { | ||
1634 | 285 | ist = input_files[map->file_index]->streams[map->stream_index]; | |
1635 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 285 times.
|
285 | if (ist->user_set_discard == AVDISCARD_ALL) { |
1636 | ✗ | av_log(mux, AV_LOG_FATAL, "Stream #%d:%d is disabled and cannot be mapped.\n", | |
1637 | ✗ | map->file_index, map->stream_index); | |
1638 | ✗ | return AVERROR(EINVAL); | |
1639 | } | ||
1640 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 285 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
285 | if(o->subtitle_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) |
1641 | ✗ | return 0; | |
1642 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 285 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
285 | if(o-> audio_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) |
1643 | ✗ | return 0; | |
1644 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 284 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
285 | if(o-> video_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) |
1645 | ✗ | return 0; | |
1646 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 285 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
285 | if(o-> data_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_DATA) |
1647 | ✗ | return 0; | |
1648 | |||
1649 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 285 times.
|
285 | if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_UNKNOWN && |
1650 | ✗ | !copy_unknown_streams) { | |
1651 | ✗ | av_log(mux, ignore_unknown_streams ? AV_LOG_WARNING : AV_LOG_FATAL, | |
1652 | "Cannot map stream #%d:%d - unsupported type.\n", | ||
1653 | ✗ | map->file_index, map->stream_index); | |
1654 | ✗ | if (!ignore_unknown_streams) { | |
1655 | ✗ | av_log(mux, AV_LOG_FATAL, | |
1656 | "If you want unsupported types ignored instead " | ||
1657 | "of failing, please use the -ignore_unknown option\n" | ||
1658 | "If you want them copied, please use -copy_unknown\n"); | ||
1659 | ✗ | return AVERROR(EINVAL); | |
1660 | } | ||
1661 | ✗ | return 0; | |
1662 | } | ||
1663 | |||
1664 | 285 | ret = ost_add(mux, o, ist->st->codecpar->codec_type, ist, NULL, NULL); | |
1665 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 285 times.
|
285 | if (ret < 0) |
1666 | ✗ | return ret; | |
1667 | } | ||
1668 | |||
1669 | 339 | return 0; | |
1670 | } | ||
1671 | |||
1672 | 6757 | static int of_add_attachments(Muxer *mux, const OptionsContext *o) | |
1673 | { | ||
1674 | OutputStream *ost; | ||
1675 | int err; | ||
1676 | |||
1677 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6757 times.
|
6758 | for (int i = 0; i < o->nb_attachments; i++) { |
1678 | AVIOContext *pb; | ||
1679 | uint8_t *attachment; | ||
1680 | char *attachment_filename; | ||
1681 | const char *p; | ||
1682 | int64_t len; | ||
1683 | |||
1684 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if ((err = avio_open2(&pb, o->attachments[i], AVIO_FLAG_READ, &int_cb, NULL)) < 0) { |
1685 | ✗ | av_log(mux, AV_LOG_FATAL, "Could not open attachment file %s.\n", | |
1686 | ✗ | o->attachments[i]); | |
1687 | ✗ | return err; | |
1688 | } | ||
1689 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if ((len = avio_size(pb)) <= 0) { |
1690 | ✗ | av_log(mux, AV_LOG_FATAL, "Could not get size of the attachment %s.\n", | |
1691 | ✗ | o->attachments[i]); | |
1692 | ✗ | err = len ? len : AVERROR_INVALIDDATA; | |
1693 | ✗ | goto read_fail; | |
1694 | } | ||
1695 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (len > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) { |
1696 | ✗ | av_log(mux, AV_LOG_FATAL, "Attachment %s too large.\n", | |
1697 | ✗ | o->attachments[i]); | |
1698 | ✗ | err = AVERROR(ERANGE); | |
1699 | ✗ | goto read_fail; | |
1700 | } | ||
1701 | |||
1702 | 1 | attachment = av_malloc(len + AV_INPUT_BUFFER_PADDING_SIZE); | |
1703 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!attachment) { |
1704 | ✗ | err = AVERROR(ENOMEM); | |
1705 | ✗ | goto read_fail; | |
1706 | } | ||
1707 | |||
1708 | 1 | err = avio_read(pb, attachment, len); | |
1709 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (err < 0) |
1710 | ✗ | av_log(mux, AV_LOG_FATAL, "Error reading attachment file %s: %s\n", | |
1711 | ✗ | o->attachments[i], av_err2str(err)); | |
1712 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | else if (err != len) { |
1713 | ✗ | av_log(mux, AV_LOG_FATAL, "Could not read all %"PRId64" bytes for " | |
1714 | ✗ | "attachment file %s\n", len, o->attachments[i]); | |
1715 | ✗ | err = AVERROR(EIO); | |
1716 | } | ||
1717 | |||
1718 | 1 | read_fail: | |
1719 | 1 | avio_closep(&pb); | |
1720 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (err < 0) |
1721 | ✗ | return err; | |
1722 | |||
1723 | 1 | memset(attachment + len, 0, AV_INPUT_BUFFER_PADDING_SIZE); | |
1724 | |||
1725 | 1 | av_log(mux, AV_LOG_VERBOSE, "Creating attachment stream from file %s\n", | |
1726 | 1 | o->attachments[i]); | |
1727 | |||
1728 | 1 | attachment_filename = av_strdup(o->attachments[i]); | |
1729 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!attachment_filename) { |
1730 | ✗ | av_free(attachment); | |
1731 | ✗ | return AVERROR(ENOMEM); | |
1732 | } | ||
1733 | |||
1734 | 1 | err = ost_add(mux, o, AVMEDIA_TYPE_ATTACHMENT, NULL, NULL, &ost); | |
1735 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (err < 0) { |
1736 | ✗ | av_free(attachment_filename); | |
1737 | ✗ | av_freep(&attachment); | |
1738 | ✗ | return err; | |
1739 | } | ||
1740 | |||
1741 | 1 | ost->attachment_filename = attachment_filename; | |
1742 | 1 | ost->par_in->extradata = attachment; | |
1743 | 1 | ost->par_in->extradata_size = len; | |
1744 | |||
1745 | 1 | p = strrchr(o->attachments[i], '/'); | |
1746 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | av_dict_set(&ost->st->metadata, "filename", (p && *p) ? p + 1 : o->attachments[i], AV_DICT_DONT_OVERWRITE); |
1747 | } | ||
1748 | |||
1749 | 6757 | return 0; | |
1750 | } | ||
1751 | |||
1752 | 6757 | static int create_streams(Muxer *mux, const OptionsContext *o) | |
1753 | { | ||
1754 | static int (* const map_func[])(Muxer *mux, const OptionsContext *o) = { | ||
1755 | [AVMEDIA_TYPE_VIDEO] = map_auto_video, | ||
1756 | [AVMEDIA_TYPE_AUDIO] = map_auto_audio, | ||
1757 | [AVMEDIA_TYPE_SUBTITLE] = map_auto_subtitle, | ||
1758 | [AVMEDIA_TYPE_DATA] = map_auto_data, | ||
1759 | }; | ||
1760 | |||
1761 | 6757 | AVFormatContext *oc = mux->fc; | |
1762 | |||
1763 | 6757 | int auto_disable = | |
1764 | 6757 | o->video_disable * (1 << AVMEDIA_TYPE_VIDEO) | | |
1765 | 6757 | o->audio_disable * (1 << AVMEDIA_TYPE_AUDIO) | | |
1766 | 6757 | o->subtitle_disable * (1 << AVMEDIA_TYPE_SUBTITLE) | | |
1767 | 6757 | o->data_disable * (1 << AVMEDIA_TYPE_DATA); | |
1768 | |||
1769 | int ret; | ||
1770 | |||
1771 | /* create streams for all unlabeled output pads */ | ||
1772 |
2/2✓ Branch 0 taken 120 times.
✓ Branch 1 taken 6757 times.
|
6877 | for (int i = 0; i < nb_filtergraphs; i++) { |
1773 | 120 | FilterGraph *fg = filtergraphs[i]; | |
1774 |
2/2✓ Branch 0 taken 170 times.
✓ Branch 1 taken 120 times.
|
290 | for (int j = 0; j < fg->nb_outputs; j++) { |
1775 | 170 | OutputFilter *ofilter = fg->outputs[j]; | |
1776 | |||
1777 |
4/4✓ Branch 0 taken 115 times.
✓ Branch 1 taken 55 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 113 times.
|
170 | if (ofilter->linklabel || ofilter->ost) |
1778 | 57 | continue; | |
1779 | |||
1780 | 113 | auto_disable |= 1 << ofilter->type; | |
1781 | |||
1782 | 113 | av_log(mux, AV_LOG_VERBOSE, "Creating output stream from unlabeled " | |
1783 | "output of complex filtergraph %d.", fg->index); | ||
1784 |
1/2✓ Branch 0 taken 113 times.
✗ Branch 1 not taken.
|
113 | if (!o->nb_stream_maps) |
1785 | 113 | av_log(mux, AV_LOG_VERBOSE, " This overrides automatic %s mapping.", | |
1786 | av_get_media_type_string(ofilter->type)); | ||
1787 | 113 | av_log(mux, AV_LOG_VERBOSE, "\n"); | |
1788 | |||
1789 | 113 | ret = ost_add(mux, o, ofilter->type, NULL, ofilter, NULL); | |
1790 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 113 times.
|
113 | if (ret < 0) |
1791 | ✗ | return ret; | |
1792 | } | ||
1793 | } | ||
1794 | |||
1795 |
2/2✓ Branch 0 taken 6611 times.
✓ Branch 1 taken 146 times.
|
6757 | if (!o->nb_stream_maps) { |
1796 | 6611 | av_log(mux, AV_LOG_VERBOSE, "No explicit maps, mapping streams automatically...\n"); | |
1797 | |||
1798 | /* pick the "best" stream of each type */ | ||
1799 |
2/2✓ Branch 0 taken 26444 times.
✓ Branch 1 taken 6611 times.
|
33055 | for (int i = 0; i < FF_ARRAY_ELEMS(map_func); i++) { |
1800 |
3/4✓ Branch 0 taken 26444 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 406 times.
✓ Branch 3 taken 26038 times.
|
26444 | if (!map_func[i] || auto_disable & (1 << i)) |
1801 | 406 | continue; | |
1802 | 26038 | ret = map_func[i](mux, o); | |
1803 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 26038 times.
|
26038 | if (ret < 0) |
1804 | ✗ | return ret; | |
1805 | } | ||
1806 | } else { | ||
1807 | 146 | av_log(mux, AV_LOG_VERBOSE, "Adding streams from explicit maps...\n"); | |
1808 | |||
1809 |
2/2✓ Branch 0 taken 339 times.
✓ Branch 1 taken 146 times.
|
485 | for (int i = 0; i < o->nb_stream_maps; i++) { |
1810 | 339 | ret = map_manual(mux, o, &o->stream_maps[i]); | |
1811 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 339 times.
|
339 | if (ret < 0) |
1812 | ✗ | return ret; | |
1813 | } | ||
1814 | } | ||
1815 | |||
1816 | 6757 | ret = of_add_attachments(mux, o); | |
1817 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6757 times.
|
6757 | if (ret < 0) |
1818 | ✗ | return ret; | |
1819 | |||
1820 | // setup fix_sub_duration_heartbeat mappings | ||
1821 |
2/2✓ Branch 0 taken 7099 times.
✓ Branch 1 taken 6757 times.
|
13856 | for (unsigned i = 0; i < oc->nb_streams; i++) { |
1822 | 7099 | MuxStream *src = ms_from_ost(mux->of.streams[i]); | |
1823 | |||
1824 |
2/2✓ Branch 0 taken 7098 times.
✓ Branch 1 taken 1 times.
|
7099 | if (!src->ost.fix_sub_duration_heartbeat) |
1825 | 7098 | continue; | |
1826 | |||
1827 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
3 | for (unsigned j = 0; j < oc->nb_streams; j++) { |
1828 | 2 | MuxStream *dst = ms_from_ost(mux->of.streams[j]); | |
1829 | |||
1830 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
2 | if (src == dst || dst->ost.type != AVMEDIA_TYPE_SUBTITLE || |
1831 |
3/6✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
|
1 | !dst->ost.enc || !dst->ost.ist || !dst->ost.ist->fix_sub_duration) |
1832 | 1 | continue; | |
1833 | |||
1834 | 1 | ret = sch_mux_sub_heartbeat_add(mux->sch, mux->sch_idx, src->sch_idx, | |
1835 | 1 | dst->sch_idx_src); | |
1836 | |||
1837 | } | ||
1838 | } | ||
1839 | |||
1840 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 6757 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
6757 | if (!oc->nb_streams && !(oc->oformat->flags & AVFMT_NOSTREAMS)) { |
1841 | ✗ | av_dump_format(oc, nb_output_files - 1, oc->url, 1); | |
1842 | ✗ | av_log(mux, AV_LOG_ERROR, "Output file does not contain any stream\n"); | |
1843 | ✗ | return AVERROR(EINVAL); | |
1844 | } | ||
1845 | |||
1846 | 6757 | return 0; | |
1847 | } | ||
1848 | |||
1849 | 6757 | static int setup_sync_queues(Muxer *mux, AVFormatContext *oc, int64_t buf_size_us) | |
1850 | { | ||
1851 | 6757 | OutputFile *of = &mux->of; | |
1852 | 6757 | int nb_av_enc = 0, nb_audio_fs = 0, nb_interleaved = 0; | |
1853 | 6757 | int limit_frames = 0, limit_frames_av_enc = 0; | |
1854 | |||
1855 | #define IS_AV_ENC(ost, type) \ | ||
1856 | (ost->enc_ctx && (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) | ||
1857 | #define IS_INTERLEAVED(type) (type != AVMEDIA_TYPE_ATTACHMENT) | ||
1858 | |||
1859 |
2/2✓ Branch 0 taken 7099 times.
✓ Branch 1 taken 6757 times.
|
13856 | for (int i = 0; i < oc->nb_streams; i++) { |
1860 | 7099 | OutputStream *ost = of->streams[i]; | |
1861 | 7099 | MuxStream *ms = ms_from_ost(ost); | |
1862 | 7099 | enum AVMediaType type = ost->type; | |
1863 | |||
1864 | 7099 | ms->sq_idx_mux = -1; | |
1865 | |||
1866 | 7099 | nb_interleaved += IS_INTERLEAVED(type); | |
1867 |
6/6✓ Branch 0 taken 6471 times.
✓ Branch 1 taken 628 times.
✓ Branch 2 taken 1279 times.
✓ Branch 3 taken 5192 times.
✓ Branch 4 taken 1241 times.
✓ Branch 5 taken 38 times.
|
7099 | nb_av_enc += IS_AV_ENC(ost, type); |
1868 |
4/4✓ Branch 0 taken 6471 times.
✓ Branch 1 taken 628 times.
✓ Branch 2 taken 1241 times.
✓ Branch 3 taken 5230 times.
|
8340 | nb_audio_fs += (ost->enc_ctx && type == AVMEDIA_TYPE_AUDIO && |
1869 |
2/2✓ Branch 0 taken 156 times.
✓ Branch 1 taken 1085 times.
|
1241 | !(ost->enc_ctx->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)); |
1870 | |||
1871 | 7099 | limit_frames |= ms->max_frames < INT64_MAX; | |
1872 |
7/8✓ Branch 0 taken 2670 times.
✓ Branch 1 taken 4429 times.
✓ Branch 2 taken 2651 times.
✓ Branch 3 taken 19 times.
✓ Branch 4 taken 28 times.
✓ Branch 5 taken 2623 times.
✓ Branch 6 taken 28 times.
✗ Branch 7 not taken.
|
7099 | limit_frames_av_enc |= (ms->max_frames < INT64_MAX) && IS_AV_ENC(ost, type); |
1873 | } | ||
1874 | |||
1875 |
7/8✓ Branch 0 taken 223 times.
✓ Branch 1 taken 6534 times.
✓ Branch 2 taken 219 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 6753 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3972 times.
✓ Branch 7 taken 122 times.
|
10851 | if (!((nb_interleaved > 1 && of->shortest) || |
1876 |
2/2✓ Branch 0 taken 4094 times.
✓ Branch 1 taken 2659 times.
|
6753 | (nb_interleaved > 0 && limit_frames) || |
1877 | nb_audio_fs)) | ||
1878 | 3972 | return 0; | |
1879 | |||
1880 | /* we use a sync queue before encoding when: | ||
1881 | * - 'shortest' is in effect and we have two or more encoded audio/video | ||
1882 | * streams | ||
1883 | * - at least one encoded audio/video stream is frame-limited, since | ||
1884 | * that has similar semantics to 'shortest' | ||
1885 | * - at least one audio encoder requires constant frame sizes | ||
1886 | * | ||
1887 | * Note that encoding sync queues are handled in the scheduler, because | ||
1888 | * different encoders run in different threads and need external | ||
1889 | * synchronization, while muxer sync queues can be handled inside the muxer | ||
1890 | */ | ||
1891 |
8/8✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2781 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 133 times.
✓ Branch 5 taken 2651 times.
✓ Branch 6 taken 124 times.
✓ Branch 7 taken 9 times.
|
2785 | if ((of->shortest && nb_av_enc > 1) || limit_frames_av_enc || nb_audio_fs) { |
1892 | int sq_idx, ret; | ||
1893 | |||
1894 | 2776 | sq_idx = sch_add_sq_enc(mux->sch, buf_size_us, mux); | |
1895 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2776 times.
|
2776 | if (sq_idx < 0) |
1896 | ✗ | return sq_idx; | |
1897 | |||
1898 |
2/2✓ Branch 0 taken 2828 times.
✓ Branch 1 taken 2776 times.
|
5604 | for (int i = 0; i < oc->nb_streams; i++) { |
1899 | 2828 | OutputStream *ost = of->streams[i]; | |
1900 | 2828 | MuxStream *ms = ms_from_ost(ost); | |
1901 | 2828 | enum AVMediaType type = ost->type; | |
1902 | |||
1903 |
5/6✓ Branch 0 taken 2821 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 183 times.
✓ Branch 3 taken 2638 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 183 times.
|
2828 | if (!IS_AV_ENC(ost, type)) |
1904 | 7 | continue; | |
1905 | |||
1906 | 2821 | ret = sch_sq_add_enc(mux->sch, sq_idx, ms->sch_idx_enc, | |
1907 |
2/2✓ Branch 0 taken 2651 times.
✓ Branch 1 taken 166 times.
|
2817 | of->shortest || ms->max_frames < INT64_MAX, |
1908 |
2/2✓ Branch 0 taken 2817 times.
✓ Branch 1 taken 4 times.
|
2821 | ms->max_frames); |
1909 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2821 times.
|
2821 | if (ret < 0) |
1910 | ✗ | return ret; | |
1911 | } | ||
1912 | } | ||
1913 | |||
1914 | /* if there are any additional interleaved streams, then ALL the streams | ||
1915 | * are also synchronized before sending them to the muxer */ | ||
1916 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 2772 times.
|
2785 | if (nb_interleaved > nb_av_enc) { |
1917 | 13 | mux->sq_mux = sq_alloc(SYNC_QUEUE_PACKETS, buf_size_us, mux); | |
1918 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | if (!mux->sq_mux) |
1919 | ✗ | return AVERROR(ENOMEM); | |
1920 | |||
1921 | 13 | mux->sq_pkt = av_packet_alloc(); | |
1922 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | if (!mux->sq_pkt) |
1923 | ✗ | return AVERROR(ENOMEM); | |
1924 | |||
1925 |
2/2✓ Branch 0 taken 35 times.
✓ Branch 1 taken 13 times.
|
48 | for (int i = 0; i < oc->nb_streams; i++) { |
1926 | 35 | OutputStream *ost = of->streams[i]; | |
1927 | 35 | MuxStream *ms = ms_from_ost(ost); | |
1928 | 35 | enum AVMediaType type = ost->type; | |
1929 | |||
1930 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
|
35 | if (!IS_INTERLEAVED(type)) |
1931 | ✗ | continue; | |
1932 | |||
1933 | 35 | ms->sq_idx_mux = sq_add_stream(mux->sq_mux, | |
1934 |
4/4✓ Branch 0 taken 29 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 10 times.
|
35 | of->shortest || ms->max_frames < INT64_MAX); |
1935 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
|
35 | if (ms->sq_idx_mux < 0) |
1936 | ✗ | return ms->sq_idx_mux; | |
1937 | |||
1938 |
2/2✓ Branch 0 taken 19 times.
✓ Branch 1 taken 16 times.
|
35 | if (ms->max_frames != INT64_MAX) |
1939 | 19 | sq_limit_frames(mux->sq_mux, ms->sq_idx_mux, ms->max_frames); | |
1940 | } | ||
1941 | } | ||
1942 | |||
1943 | #undef IS_AV_ENC | ||
1944 | #undef IS_INTERLEAVED | ||
1945 | |||
1946 | 2785 | return 0; | |
1947 | } | ||
1948 | |||
1949 | 8 | static int of_parse_iamf_audio_element_layers(Muxer *mux, AVStreamGroup *stg, char *ptr) | |
1950 | { | ||
1951 | 8 | AVIAMFAudioElement *audio_element = stg->params.iamf_audio_element; | |
1952 | 8 | AVDictionary *dict = NULL; | |
1953 | const char *token; | ||
1954 | 8 | int ret = 0; | |
1955 | |||
1956 | 8 | audio_element->demixing_info = | |
1957 | 8 | av_iamf_param_definition_alloc(AV_IAMF_PARAMETER_DEFINITION_DEMIXING, 1, NULL); | |
1958 | 8 | audio_element->recon_gain_info = | |
1959 | 8 | av_iamf_param_definition_alloc(AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN, 1, NULL); | |
1960 | |||
1961 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | if (!audio_element->demixing_info || |
1962 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | !audio_element->recon_gain_info) |
1963 | ✗ | return AVERROR(ENOMEM); | |
1964 | |||
1965 | /* process manually set layers and parameters */ | ||
1966 | 8 | token = av_strtok(NULL, ",", &ptr); | |
1967 |
2/2✓ Branch 0 taken 32 times.
✓ Branch 1 taken 8 times.
|
40 | while (token) { |
1968 | const AVDictionaryEntry *e; | ||
1969 | 32 | int demixing = 0, recon_gain = 0; | |
1970 | 32 | int layer = 0; | |
1971 | |||
1972 |
1/2✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
|
32 | if (ptr) |
1973 | 32 | ptr += strspn(ptr, " \n\t\r"); | |
1974 |
2/2✓ Branch 1 taken 20 times.
✓ Branch 2 taken 12 times.
|
32 | if (av_strstart(token, "layer=", &token)) |
1975 | 20 | layer = 1; | |
1976 |
2/2✓ Branch 1 taken 6 times.
✓ Branch 2 taken 6 times.
|
12 | else if (av_strstart(token, "demixing=", &token)) |
1977 | 6 | demixing = 1; | |
1978 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | else if (av_strstart(token, "recon_gain=", &token)) |
1979 | 6 | recon_gain = 1; | |
1980 | |||
1981 | 32 | av_dict_free(&dict); | |
1982 | 32 | ret = av_dict_parse_string(&dict, token, "=", ":", 0); | |
1983 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
|
32 | if (ret < 0) { |
1984 | ✗ | av_log(mux, AV_LOG_ERROR, "Error parsing audio element specification %s\n", token); | |
1985 | ✗ | goto fail; | |
1986 | } | ||
1987 | |||
1988 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 12 times.
|
32 | if (layer) { |
1989 | 20 | AVIAMFLayer *audio_layer = av_iamf_audio_element_add_layer(audio_element); | |
1990 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
|
20 | if (!audio_layer) { |
1991 | ✗ | av_log(mux, AV_LOG_ERROR, "Error adding layer to stream group %d\n", stg->index); | |
1992 | ✗ | ret = AVERROR(ENOMEM); | |
1993 | ✗ | goto fail; | |
1994 | } | ||
1995 | 20 | av_opt_set_dict(audio_layer, &dict); | |
1996 |
3/4✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
12 | } else if (demixing || recon_gain) { |
1997 | 12 | AVIAMFParamDefinition *param = demixing ? audio_element->demixing_info | |
1998 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
|
12 | : audio_element->recon_gain_info; |
1999 | 12 | void *subblock = av_iamf_param_definition_get_subblock(param, 0); | |
2000 | |||
2001 | 12 | av_opt_set_dict(param, &dict); | |
2002 | 12 | av_opt_set_dict(subblock, &dict); | |
2003 | } | ||
2004 | |||
2005 | // make sure that no entries are left in the dict | ||
2006 | 32 | e = NULL; | |
2007 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
|
32 | if (e = av_dict_iterate(dict, e)) { |
2008 | ✗ | av_log(mux, AV_LOG_FATAL, "Unknown layer key %s.\n", e->key); | |
2009 | ✗ | ret = AVERROR(EINVAL); | |
2010 | ✗ | goto fail; | |
2011 | } | ||
2012 | 32 | token = av_strtok(NULL, ",", &ptr); | |
2013 | } | ||
2014 | |||
2015 | 8 | fail: | |
2016 | 8 | av_dict_free(&dict); | |
2017 |
2/4✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
|
8 | if (!ret && !audio_element->nb_layers) { |
2018 | ✗ | av_log(mux, AV_LOG_ERROR, "No layer in audio element specification\n"); | |
2019 | ✗ | ret = AVERROR(EINVAL); | |
2020 | } | ||
2021 | |||
2022 | 8 | return ret; | |
2023 | } | ||
2024 | |||
2025 | 8 | static int of_parse_iamf_submixes(Muxer *mux, AVStreamGroup *stg, char *ptr) | |
2026 | { | ||
2027 | 8 | AVFormatContext *oc = mux->fc; | |
2028 | 8 | AVIAMFMixPresentation *mix = stg->params.iamf_mix_presentation; | |
2029 | 8 | AVDictionary *dict = NULL; | |
2030 | const char *token; | ||
2031 | 8 | char *submix_str = NULL; | |
2032 | 8 | int ret = 0; | |
2033 | |||
2034 | /* process manually set submixes */ | ||
2035 | 8 | token = av_strtok(NULL, ",", &ptr); | |
2036 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 8 times.
|
18 | while (token) { |
2037 | 10 | AVIAMFSubmix *submix = NULL; | |
2038 | const char *subtoken; | ||
2039 | 10 | char *subptr = NULL; | |
2040 | |||
2041 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | if (ptr) |
2042 | 10 | ptr += strspn(ptr, " \n\t\r"); | |
2043 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
|
10 | if (!av_strstart(token, "submix=", &token)) { |
2044 | ✗ | av_log(mux, AV_LOG_ERROR, "No submix in mix presentation specification \"%s\"\n", token); | |
2045 | ✗ | goto fail; | |
2046 | } | ||
2047 | |||
2048 | 10 | submix_str = av_strdup(token); | |
2049 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (!submix_str) |
2050 | ✗ | goto fail; | |
2051 | |||
2052 | 10 | submix = av_iamf_mix_presentation_add_submix(mix); | |
2053 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (!submix) { |
2054 | ✗ | av_log(mux, AV_LOG_ERROR, "Error adding submix to stream group %d\n", stg->index); | |
2055 | ✗ | ret = AVERROR(ENOMEM); | |
2056 | ✗ | goto fail; | |
2057 | } | ||
2058 | 10 | submix->output_mix_config = | |
2059 | 10 | av_iamf_param_definition_alloc(AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN, 0, NULL); | |
2060 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (!submix->output_mix_config) { |
2061 | ✗ | ret = AVERROR(ENOMEM); | |
2062 | ✗ | goto fail; | |
2063 | } | ||
2064 | |||
2065 | 10 | subptr = NULL; | |
2066 | 10 | subtoken = av_strtok(submix_str, "|", &subptr); | |
2067 |
2/2✓ Branch 0 taken 42 times.
✓ Branch 1 taken 10 times.
|
52 | while (subtoken) { |
2068 | const AVDictionaryEntry *e; | ||
2069 | 42 | int element = 0, layout = 0; | |
2070 | |||
2071 |
2/2✓ Branch 0 taken 32 times.
✓ Branch 1 taken 10 times.
|
42 | if (subptr) |
2072 | 32 | subptr += strspn(subptr, " \n\t\r"); | |
2073 |
2/2✓ Branch 1 taken 10 times.
✓ Branch 2 taken 32 times.
|
42 | if (av_strstart(subtoken, "element=", &subtoken)) |
2074 | 10 | element = 1; | |
2075 |
2/2✓ Branch 1 taken 22 times.
✓ Branch 2 taken 10 times.
|
32 | else if (av_strstart(subtoken, "layout=", &subtoken)) |
2076 | 22 | layout = 1; | |
2077 | |||
2078 | 42 | av_dict_free(&dict); | |
2079 | 42 | ret = av_dict_parse_string(&dict, subtoken, "=", ":", 0); | |
2080 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
|
42 | if (ret < 0) { |
2081 | ✗ | av_log(mux, AV_LOG_ERROR, "Error parsing submix specification \"%s\"\n", subtoken); | |
2082 | ✗ | goto fail; | |
2083 | } | ||
2084 | |||
2085 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 32 times.
|
42 | if (element) { |
2086 | AVIAMFSubmixElement *submix_element; | ||
2087 | 10 | char *endptr = NULL; | |
2088 | 10 | int64_t idx = -1; | |
2089 | |||
2090 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | if (e = av_dict_get(dict, "stg", NULL, 0)) |
2091 | 10 | idx = strtoll(e->value, &endptr, 0); | |
2092 |
4/8✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 10 times.
✗ Branch 7 not taken.
|
10 | if (!endptr || *endptr || idx < 0 || idx >= oc->nb_stream_groups - 1 || |
2093 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | oc->stream_groups[idx]->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT) { |
2094 | ✗ | av_log(mux, AV_LOG_ERROR, "Invalid or missing stream group index in " | |
2095 | "submix element specification \"%s\"\n", subtoken); | ||
2096 | ✗ | ret = AVERROR(EINVAL); | |
2097 | ✗ | goto fail; | |
2098 | } | ||
2099 | 10 | submix_element = av_iamf_submix_add_element(submix); | |
2100 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (!submix_element) { |
2101 | ✗ | av_log(mux, AV_LOG_ERROR, "Error adding element to submix\n"); | |
2102 | ✗ | ret = AVERROR(ENOMEM); | |
2103 | ✗ | goto fail; | |
2104 | } | ||
2105 | |||
2106 | 10 | submix_element->audio_element_id = oc->stream_groups[idx]->id; | |
2107 | |||
2108 | 10 | submix_element->element_mix_config = | |
2109 | 10 | av_iamf_param_definition_alloc(AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN, 0, NULL); | |
2110 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (!submix_element->element_mix_config) |
2111 | ✗ | ret = AVERROR(ENOMEM); | |
2112 | 10 | av_dict_set(&dict, "stg", NULL, 0); | |
2113 | 10 | av_opt_set_dict2(submix_element, &dict, AV_OPT_SEARCH_CHILDREN); | |
2114 |
2/2✓ Branch 0 taken 22 times.
✓ Branch 1 taken 10 times.
|
32 | } else if (layout) { |
2115 | 22 | AVIAMFSubmixLayout *submix_layout = av_iamf_submix_add_layout(submix); | |
2116 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
|
22 | if (!submix_layout) { |
2117 | ✗ | av_log(mux, AV_LOG_ERROR, "Error adding layout to submix\n"); | |
2118 | ✗ | ret = AVERROR(ENOMEM); | |
2119 | ✗ | goto fail; | |
2120 | } | ||
2121 | 22 | av_opt_set_dict(submix_layout, &dict); | |
2122 | } else | ||
2123 | 10 | av_opt_set_dict2(submix, &dict, AV_OPT_SEARCH_CHILDREN); | |
2124 | |||
2125 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
|
42 | if (ret < 0) { |
2126 | ✗ | goto fail; | |
2127 | } | ||
2128 | |||
2129 | // make sure that no entries are left in the dict | ||
2130 | 42 | e = NULL; | |
2131 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
|
42 | while (e = av_dict_iterate(dict, e)) { |
2132 | ✗ | av_log(mux, AV_LOG_FATAL, "Unknown submix key %s.\n", e->key); | |
2133 | ✗ | ret = AVERROR(EINVAL); | |
2134 | ✗ | goto fail; | |
2135 | } | ||
2136 | 42 | subtoken = av_strtok(NULL, "|", &subptr); | |
2137 | } | ||
2138 | 10 | av_freep(&submix_str); | |
2139 | |||
2140 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (!submix->nb_elements) { |
2141 | ✗ | av_log(mux, AV_LOG_ERROR, "No audio elements in submix specification \"%s\"\n", token); | |
2142 | ✗ | ret = AVERROR(EINVAL); | |
2143 | } | ||
2144 | 10 | token = av_strtok(NULL, ",", &ptr); | |
2145 | } | ||
2146 | |||
2147 | 8 | fail: | |
2148 | 8 | av_dict_free(&dict); | |
2149 | 8 | av_free(submix_str); | |
2150 | |||
2151 | 8 | return ret; | |
2152 | } | ||
2153 | |||
2154 | 16 | static int of_parse_group_token(Muxer *mux, const char *token, char *ptr) | |
2155 | { | ||
2156 | 16 | AVFormatContext *oc = mux->fc; | |
2157 | AVStreamGroup *stg; | ||
2158 | 16 | AVDictionary *dict = NULL, *tmp = NULL; | |
2159 | const AVDictionaryEntry *e; | ||
2160 | 16 | const AVOption opts[] = { | |
2161 | { "type", "Set group type", offsetof(AVStreamGroup, type), AV_OPT_TYPE_INT, | ||
2162 | { .i64 = 0 }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, .unit = "type" }, | ||
2163 | { "iamf_audio_element", NULL, 0, AV_OPT_TYPE_CONST, | ||
2164 | { .i64 = AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT }, .unit = "type" }, | ||
2165 | { "iamf_mix_presentation", NULL, 0, AV_OPT_TYPE_CONST, | ||
2166 | { .i64 = AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION }, .unit = "type" }, | ||
2167 | { NULL }, | ||
2168 | }; | ||
2169 | 16 | const AVClass class = { | |
2170 | .class_name = "StreamGroupType", | ||
2171 | .item_name = av_default_item_name, | ||
2172 | .option = opts, | ||
2173 | .version = LIBAVUTIL_VERSION_INT, | ||
2174 | }; | ||
2175 | 16 | const AVClass *pclass = &class; | |
2176 | int type, ret; | ||
2177 | |||
2178 | 16 | ret = av_dict_parse_string(&dict, token, "=", ":", AV_DICT_MULTIKEY); | |
2179 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
|
16 | if (ret < 0) { |
2180 | ✗ | av_log(mux, AV_LOG_ERROR, "Error parsing group specification %s\n", token); | |
2181 | ✗ | return ret; | |
2182 | } | ||
2183 | |||
2184 | // "type" is not a user settable AVOption in AVStreamGroup, so handle it here | ||
2185 | 16 | e = av_dict_get(dict, "type", NULL, 0); | |
2186 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
|
16 | if (!e) { |
2187 | ✗ | av_log(mux, AV_LOG_ERROR, "No type specified for Stream Group in \"%s\"\n", token); | |
2188 | ✗ | ret = AVERROR(EINVAL); | |
2189 | ✗ | goto end; | |
2190 | } | ||
2191 | |||
2192 | 16 | ret = av_opt_eval_int(&pclass, opts, e->value, &type); | |
2193 |
2/4✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
|
16 | if (!ret && type == AV_STREAM_GROUP_PARAMS_NONE) |
2194 | ✗ | ret = AVERROR(EINVAL); | |
2195 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
|
16 | if (ret < 0) { |
2196 | ✗ | av_log(mux, AV_LOG_ERROR, "Invalid group type \"%s\"\n", e->value); | |
2197 | ✗ | goto end; | |
2198 | } | ||
2199 | |||
2200 | 16 | av_dict_copy(&tmp, dict, 0); | |
2201 | 16 | stg = avformat_stream_group_create(oc, type, &tmp); | |
2202 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
|
16 | if (!stg) { |
2203 | ✗ | ret = AVERROR(ENOMEM); | |
2204 | ✗ | goto end; | |
2205 | } | ||
2206 | |||
2207 | 16 | e = NULL; | |
2208 |
2/2✓ Branch 1 taken 36 times.
✓ Branch 2 taken 16 times.
|
52 | while (e = av_dict_get(dict, "st", e, 0)) { |
2209 | char *endptr; | ||
2210 | 36 | int64_t idx = strtoll(e->value, &endptr, 0); | |
2211 |
3/6✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 36 times.
|
36 | if (*endptr || idx < 0 || idx >= oc->nb_streams) { |
2212 | ✗ | av_log(mux, AV_LOG_ERROR, "Invalid stream index %"PRId64"\n", idx); | |
2213 | ✗ | ret = AVERROR(EINVAL); | |
2214 | ✗ | goto end; | |
2215 | } | ||
2216 | 36 | ret = avformat_stream_group_add_stream(stg, oc->streams[idx]); | |
2217 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
|
36 | if (ret < 0) |
2218 | ✗ | goto end; | |
2219 | } | ||
2220 |
2/2✓ Branch 1 taken 8 times.
✓ Branch 2 taken 16 times.
|
24 | while (e = av_dict_get(dict, "stg", e, 0)) { |
2221 | char *endptr; | ||
2222 | 8 | int64_t idx = strtoll(e->value, &endptr, 0); | |
2223 |
3/6✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
|
8 | if (*endptr || idx < 0 || idx >= oc->nb_stream_groups - 1) { |
2224 | ✗ | av_log(mux, AV_LOG_ERROR, "Invalid stream group index %"PRId64"\n", idx); | |
2225 | ✗ | ret = AVERROR(EINVAL); | |
2226 | ✗ | goto end; | |
2227 | } | ||
2228 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 8 times.
|
44 | for (unsigned i = 0; i < oc->stream_groups[idx]->nb_streams; i++) { |
2229 | 36 | ret = avformat_stream_group_add_stream(stg, oc->stream_groups[idx]->streams[i]); | |
2230 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
|
36 | if (ret < 0) |
2231 | ✗ | goto end; | |
2232 | } | ||
2233 | } | ||
2234 | |||
2235 |
2/3✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
16 | switch(type) { |
2236 | 8 | case AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT: | |
2237 | 8 | ret = of_parse_iamf_audio_element_layers(mux, stg, ptr); | |
2238 | 8 | break; | |
2239 | 8 | case AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION: | |
2240 | 8 | ret = of_parse_iamf_submixes(mux, stg, ptr); | |
2241 | 8 | break; | |
2242 | ✗ | default: | |
2243 | ✗ | av_log(mux, AV_LOG_FATAL, "Unknown group type %d.\n", type); | |
2244 | ✗ | ret = AVERROR(EINVAL); | |
2245 | ✗ | break; | |
2246 | } | ||
2247 | |||
2248 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
|
16 | if (ret < 0) |
2249 | ✗ | goto end; | |
2250 | |||
2251 | // make sure that nothing but "st" and "stg" entries are left in the dict | ||
2252 | 16 | e = NULL; | |
2253 | 16 | av_dict_set(&tmp, "type", NULL, 0); | |
2254 |
2/2✓ Branch 1 taken 16 times.
✓ Branch 2 taken 16 times.
|
32 | while (e = av_dict_iterate(tmp, e)) { |
2255 |
3/4✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
|
16 | if (!strcmp(e->key, "st") || !strcmp(e->key, "stg")) |
2256 | 16 | continue; | |
2257 | |||
2258 | ✗ | av_log(mux, AV_LOG_FATAL, "Unknown group key %s.\n", e->key); | |
2259 | ✗ | ret = AVERROR(EINVAL); | |
2260 | ✗ | goto end; | |
2261 | } | ||
2262 | |||
2263 | 16 | ret = 0; | |
2264 | 16 | end: | |
2265 | 16 | av_dict_free(&dict); | |
2266 | 16 | av_dict_free(&tmp); | |
2267 | |||
2268 | 16 | return ret; | |
2269 | } | ||
2270 | |||
2271 | 6757 | static int of_add_groups(Muxer *mux, const OptionsContext *o) | |
2272 | { | ||
2273 | /* process manually set groups */ | ||
2274 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 6757 times.
|
6773 | for (int i = 0; i < o->stream_groups.nb_opt; i++) { |
2275 | const char *token; | ||
2276 | 16 | char *str, *ptr = NULL; | |
2277 | 16 | int ret = 0; | |
2278 | |||
2279 | 16 | str = av_strdup(o->stream_groups.opt[i].u.str); | |
2280 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
|
16 | if (!str) |
2281 | ✗ | return ret; | |
2282 | |||
2283 | 16 | token = av_strtok(str, ",", &ptr); | |
2284 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | if (token) { |
2285 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | if (ptr) |
2286 | 16 | ptr += strspn(ptr, " \n\t\r"); | |
2287 | 16 | ret = of_parse_group_token(mux, token, ptr); | |
2288 | } | ||
2289 | |||
2290 | 16 | av_free(str); | |
2291 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
|
16 | if (ret < 0) |
2292 | ✗ | return ret; | |
2293 | } | ||
2294 | |||
2295 | 6757 | return 0; | |
2296 | } | ||
2297 | |||
2298 | 6757 | static int of_add_programs(Muxer *mux, const OptionsContext *o) | |
2299 | { | ||
2300 | 6757 | AVFormatContext *oc = mux->fc; | |
2301 | /* process manually set programs */ | ||
2302 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6757 times.
|
6757 | for (int i = 0; i < o->program.nb_opt; i++) { |
2303 | ✗ | AVDictionary *dict = NULL; | |
2304 | const AVDictionaryEntry *e; | ||
2305 | AVProgram *program; | ||
2306 | ✗ | int ret, progid = i + 1; | |
2307 | |||
2308 | ✗ | ret = av_dict_parse_string(&dict, o->program.opt[i].u.str, "=", ":", | |
2309 | AV_DICT_MULTIKEY); | ||
2310 | ✗ | if (ret < 0) { | |
2311 | ✗ | av_log(mux, AV_LOG_ERROR, "Error parsing program specification %s\n", | |
2312 | ✗ | o->program.opt[i].u.str); | |
2313 | ✗ | return ret; | |
2314 | } | ||
2315 | |||
2316 | ✗ | e = av_dict_get(dict, "program_num", NULL, 0); | |
2317 | ✗ | if (e) { | |
2318 | ✗ | progid = strtol(e->value, NULL, 0); | |
2319 | ✗ | av_dict_set(&dict, e->key, NULL, 0); | |
2320 | } | ||
2321 | |||
2322 | ✗ | program = av_new_program(oc, progid); | |
2323 | ✗ | if (!program) { | |
2324 | ✗ | ret = AVERROR(ENOMEM); | |
2325 | ✗ | goto fail; | |
2326 | } | ||
2327 | |||
2328 | ✗ | e = av_dict_get(dict, "title", NULL, 0); | |
2329 | ✗ | if (e) { | |
2330 | ✗ | av_dict_set(&program->metadata, e->key, e->value, 0); | |
2331 | ✗ | av_dict_set(&dict, e->key, NULL, 0); | |
2332 | } | ||
2333 | |||
2334 | ✗ | e = NULL; | |
2335 | ✗ | while (e = av_dict_get(dict, "st", e, 0)) { | |
2336 | ✗ | int st_num = strtol(e->value, NULL, 0); | |
2337 | ✗ | av_program_add_stream_index(oc, progid, st_num); | |
2338 | } | ||
2339 | |||
2340 | // make sure that nothing but "st" entries are left in the dict | ||
2341 | ✗ | e = NULL; | |
2342 | ✗ | while (e = av_dict_iterate(dict, e)) { | |
2343 | ✗ | if (!strcmp(e->key, "st")) | |
2344 | ✗ | continue; | |
2345 | |||
2346 | ✗ | av_log(mux, AV_LOG_FATAL, "Unknown program key %s.\n", e->key); | |
2347 | ✗ | ret = AVERROR(EINVAL); | |
2348 | ✗ | goto fail; | |
2349 | } | ||
2350 | |||
2351 | ✗ | fail: | |
2352 | ✗ | av_dict_free(&dict); | |
2353 | ✗ | if (ret < 0) | |
2354 | ✗ | return ret; | |
2355 | } | ||
2356 | |||
2357 | 6757 | return 0; | |
2358 | } | ||
2359 | |||
2360 | /** | ||
2361 | * Parse a metadata specifier passed as 'arg' parameter. | ||
2362 | * @param arg metadata string to parse | ||
2363 | * @param type metadata type is written here -- g(lobal)/s(tream)/c(hapter)/p(rogram) | ||
2364 | * @param index for type c/p, chapter/program index is written here | ||
2365 | * @param stream_spec for type s, the stream specifier is written here | ||
2366 | */ | ||
2367 | 230 | static int parse_meta_type(void *logctx, const char *arg, | |
2368 | char *type, int *index, const char **stream_spec) | ||
2369 | { | ||
2370 |
2/2✓ Branch 0 taken 71 times.
✓ Branch 1 taken 159 times.
|
230 | if (*arg) { |
2371 | 71 | *type = *arg; | |
2372 |
3/4✓ Branch 0 taken 21 times.
✓ Branch 1 taken 46 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
71 | switch (*arg) { |
2373 | 21 | case 'g': | |
2374 | 21 | break; | |
2375 | 46 | case 's': | |
2376 |
2/4✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 46 times.
|
46 | if (*(++arg) && *arg != ':') { |
2377 | ✗ | av_log(logctx, AV_LOG_FATAL, "Invalid metadata specifier %s.\n", arg); | |
2378 | ✗ | return AVERROR(EINVAL); | |
2379 | } | ||
2380 |
1/2✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
|
46 | *stream_spec = *arg == ':' ? arg + 1 : ""; |
2381 | 46 | break; | |
2382 | 4 | case 'c': | |
2383 | case 'p': | ||
2384 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
|
4 | if (*(++arg) == ':') |
2385 | 3 | *index = strtol(++arg, NULL, 0); | |
2386 | 4 | break; | |
2387 | ✗ | default: | |
2388 | ✗ | av_log(logctx, AV_LOG_FATAL, "Invalid metadata type %c.\n", *arg); | |
2389 | ✗ | return AVERROR(EINVAL); | |
2390 | } | ||
2391 | } else | ||
2392 | 159 | *type = 'g'; | |
2393 | |||
2394 | 230 | return 0; | |
2395 | } | ||
2396 | |||
2397 | 6757 | static int of_add_metadata(OutputFile *of, AVFormatContext *oc, | |
2398 | const OptionsContext *o) | ||
2399 | { | ||
2400 |
2/2✓ Branch 0 taken 216 times.
✓ Branch 1 taken 6757 times.
|
6973 | for (int i = 0; i < o->metadata.nb_opt; i++) { |
2401 | AVDictionary **m; | ||
2402 | char type, *val; | ||
2403 | const char *stream_spec; | ||
2404 | 216 | int index = 0, ret = 0; | |
2405 | |||
2406 | 216 | val = strchr(o->metadata.opt[i].u.str, '='); | |
2407 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 216 times.
|
216 | if (!val) { |
2408 | ✗ | av_log(of, AV_LOG_FATAL, "No '=' character in metadata string %s.\n", | |
2409 | ✗ | o->metadata.opt[i].u.str); | |
2410 | ✗ | return AVERROR(EINVAL); | |
2411 | } | ||
2412 | 216 | *val++ = 0; | |
2413 | |||
2414 | 216 | ret = parse_meta_type(of, o->metadata.opt[i].specifier, &type, &index, &stream_spec); | |
2415 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 216 times.
|
216 | if (ret < 0) |
2416 | ✗ | return ret; | |
2417 | |||
2418 |
2/2✓ Branch 0 taken 41 times.
✓ Branch 1 taken 175 times.
|
216 | if (type == 's') { |
2419 |
2/2✓ Branch 0 taken 219 times.
✓ Branch 1 taken 41 times.
|
260 | for (int j = 0; j < oc->nb_streams; j++) { |
2420 |
2/2✓ Branch 1 taken 41 times.
✓ Branch 2 taken 178 times.
|
219 | if ((ret = check_stream_specifier(oc, oc->streams[j], stream_spec)) > 0) { |
2421 |
1/2✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
|
41 | av_dict_set(&oc->streams[j]->metadata, o->metadata.opt[i].u.str, *val ? val : NULL, 0); |
2422 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 178 times.
|
178 | } else if (ret < 0) |
2423 | ✗ | return ret; | |
2424 | } | ||
2425 | } else { | ||
2426 |
2/4✓ Branch 0 taken 171 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
175 | switch (type) { |
2427 | 171 | case 'g': | |
2428 | 171 | m = &oc->metadata; | |
2429 | 171 | break; | |
2430 | 4 | case 'c': | |
2431 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
|
4 | if (index < 0 || index >= oc->nb_chapters) { |
2432 | ✗ | av_log(of, AV_LOG_FATAL, "Invalid chapter index %d in metadata specifier.\n", index); | |
2433 | ✗ | return AVERROR(EINVAL); | |
2434 | } | ||
2435 | 4 | m = &oc->chapters[index]->metadata; | |
2436 | 4 | break; | |
2437 | ✗ | case 'p': | |
2438 | ✗ | if (index < 0 || index >= oc->nb_programs) { | |
2439 | ✗ | av_log(of, AV_LOG_FATAL, "Invalid program index %d in metadata specifier.\n", index); | |
2440 | ✗ | return AVERROR(EINVAL); | |
2441 | } | ||
2442 | ✗ | m = &oc->programs[index]->metadata; | |
2443 | ✗ | break; | |
2444 | ✗ | default: | |
2445 | ✗ | av_log(of, AV_LOG_FATAL, "Invalid metadata specifier %s.\n", o->metadata.opt[i].specifier); | |
2446 | ✗ | return AVERROR(EINVAL); | |
2447 | } | ||
2448 |
2/2✓ Branch 0 taken 174 times.
✓ Branch 1 taken 1 times.
|
175 | av_dict_set(m, o->metadata.opt[i].u.str, *val ? val : NULL, 0); |
2449 | } | ||
2450 | } | ||
2451 | |||
2452 | 6757 | return 0; | |
2453 | } | ||
2454 | |||
2455 | 19 | static int copy_chapters(InputFile *ifile, OutputFile *ofile, AVFormatContext *os, | |
2456 | int copy_metadata) | ||
2457 | { | ||
2458 | 19 | AVFormatContext *is = ifile->ctx; | |
2459 | AVChapter **tmp; | ||
2460 | |||
2461 | 19 | tmp = av_realloc_f(os->chapters, is->nb_chapters + os->nb_chapters, sizeof(*os->chapters)); | |
2462 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
|
19 | if (!tmp) |
2463 | ✗ | return AVERROR(ENOMEM); | |
2464 | 19 | os->chapters = tmp; | |
2465 | |||
2466 |
2/2✓ Branch 0 taken 37 times.
✓ Branch 1 taken 16 times.
|
53 | for (int i = 0; i < is->nb_chapters; i++) { |
2467 | 37 | AVChapter *in_ch = is->chapters[i], *out_ch; | |
2468 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
|
37 | int64_t start_time = (ofile->start_time == AV_NOPTS_VALUE) ? 0 : ofile->start_time; |
2469 | 37 | int64_t ts_off = av_rescale_q(start_time - ifile->ts_offset, | |
2470 | 37 | AV_TIME_BASE_Q, in_ch->time_base); | |
2471 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 32 times.
|
37 | int64_t rt = (ofile->recording_time == INT64_MAX) ? INT64_MAX : |
2472 | 5 | av_rescale_q(ofile->recording_time, AV_TIME_BASE_Q, in_ch->time_base); | |
2473 | |||
2474 | |||
2475 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
|
37 | if (in_ch->end < ts_off) |
2476 | ✗ | continue; | |
2477 |
4/4✓ Branch 0 taken 5 times.
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 2 times.
|
37 | if (rt != INT64_MAX && in_ch->start > rt + ts_off) |
2478 | 3 | break; | |
2479 | |||
2480 | 34 | out_ch = av_mallocz(sizeof(AVChapter)); | |
2481 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
|
34 | if (!out_ch) |
2482 | ✗ | return AVERROR(ENOMEM); | |
2483 | |||
2484 | 34 | out_ch->id = in_ch->id; | |
2485 | 34 | out_ch->time_base = in_ch->time_base; | |
2486 | 34 | out_ch->start = FFMAX(0, in_ch->start - ts_off); | |
2487 | 34 | out_ch->end = FFMIN(rt, in_ch->end - ts_off); | |
2488 | |||
2489 |
1/2✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
|
34 | if (copy_metadata) |
2490 | 34 | av_dict_copy(&out_ch->metadata, in_ch->metadata, 0); | |
2491 | |||
2492 | 34 | os->chapters[os->nb_chapters++] = out_ch; | |
2493 | } | ||
2494 | 19 | return 0; | |
2495 | } | ||
2496 | |||
2497 | 7 | static int copy_metadata(Muxer *mux, AVFormatContext *ic, | |
2498 | const char *outspec, const char *inspec, | ||
2499 | int *metadata_global_manual, int *metadata_streams_manual, | ||
2500 | int *metadata_chapters_manual) | ||
2501 | { | ||
2502 | 7 | AVFormatContext *oc = mux->fc; | |
2503 | 7 | AVDictionary **meta_in = NULL; | |
2504 | 7 | AVDictionary **meta_out = NULL; | |
2505 | 7 | int i, ret = 0; | |
2506 | char type_in, type_out; | ||
2507 | 7 | const char *istream_spec = NULL, *ostream_spec = NULL; | |
2508 | 7 | int idx_in = 0, idx_out = 0; | |
2509 | |||
2510 | 7 | ret = parse_meta_type(mux, inspec, &type_in, &idx_in, &istream_spec); | |
2511 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | if (ret >= 0) |
2512 | 7 | ret = parse_meta_type(mux, outspec, &type_out, &idx_out, &ostream_spec); | |
2513 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (ret < 0) |
2514 | ✗ | return ret; | |
2515 | |||
2516 |
4/8✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
7 | if (type_in == 'g' || type_out == 'g' || (!*outspec && !ic)) |
2517 | 5 | *metadata_global_manual = 1; | |
2518 |
7/8✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
|
7 | if (type_in == 's' || type_out == 's' || (!*outspec && !ic)) |
2519 | 3 | *metadata_streams_manual = 1; | |
2520 |
5/8✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
|
7 | if (type_in == 'c' || type_out == 'c' || (!*outspec && !ic)) |
2521 | ✗ | *metadata_chapters_manual = 1; | |
2522 | |||
2523 | /* ic is NULL when just disabling automatic mappings */ | ||
2524 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5 times.
|
7 | if (!ic) |
2525 | 2 | return 0; | |
2526 | |||
2527 | #define METADATA_CHECK_INDEX(index, nb_elems, desc)\ | ||
2528 | if ((index) < 0 || (index) >= (nb_elems)) {\ | ||
2529 | av_log(mux, AV_LOG_FATAL, "Invalid %s index %d while processing metadata maps.\n",\ | ||
2530 | (desc), (index));\ | ||
2531 | return AVERROR(EINVAL);\ | ||
2532 | } | ||
2533 | |||
2534 | #define SET_DICT(type, meta, context, index)\ | ||
2535 | switch (type) {\ | ||
2536 | case 'g':\ | ||
2537 | meta = &context->metadata;\ | ||
2538 | break;\ | ||
2539 | case 'c':\ | ||
2540 | METADATA_CHECK_INDEX(index, context->nb_chapters, "chapter")\ | ||
2541 | meta = &context->chapters[index]->metadata;\ | ||
2542 | break;\ | ||
2543 | case 'p':\ | ||
2544 | METADATA_CHECK_INDEX(index, context->nb_programs, "program")\ | ||
2545 | meta = &context->programs[index]->metadata;\ | ||
2546 | break;\ | ||
2547 | case 's':\ | ||
2548 | break; /* handled separately below */ \ | ||
2549 | default: av_assert0(0);\ | ||
2550 | }\ | ||
2551 | |||
2552 |
2/13✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
|
5 | SET_DICT(type_in, meta_in, ic, idx_in); |
2553 |
2/13✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
|
5 | SET_DICT(type_out, meta_out, oc, idx_out); |
2554 | |||
2555 | /* for input streams choose first matching stream */ | ||
2556 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
|
5 | if (type_in == 's') { |
2557 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | for (i = 0; i < ic->nb_streams; i++) { |
2558 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
|
3 | if ((ret = check_stream_specifier(ic, ic->streams[i], istream_spec)) > 0) { |
2559 | 2 | meta_in = &ic->streams[i]->metadata; | |
2560 | 2 | break; | |
2561 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | } else if (ret < 0) |
2562 | ✗ | return ret; | |
2563 | } | ||
2564 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (!meta_in) { |
2565 | ✗ | av_log(mux, AV_LOG_FATAL, "Stream specifier %s does not match any streams.\n", istream_spec); | |
2566 | ✗ | return AVERROR(EINVAL); | |
2567 | } | ||
2568 | } | ||
2569 | |||
2570 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
|
5 | if (type_out == 's') { |
2571 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3 times.
|
11 | for (i = 0; i < oc->nb_streams; i++) { |
2572 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 5 times.
|
8 | if ((ret = check_stream_specifier(oc, oc->streams[i], ostream_spec)) > 0) { |
2573 | 3 | meta_out = &oc->streams[i]->metadata; | |
2574 | 3 | av_dict_copy(meta_out, *meta_in, AV_DICT_DONT_OVERWRITE); | |
2575 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | } else if (ret < 0) |
2576 | ✗ | return ret; | |
2577 | } | ||
2578 | } else | ||
2579 | 2 | av_dict_copy(meta_out, *meta_in, AV_DICT_DONT_OVERWRITE); | |
2580 | |||
2581 | 5 | return 0; | |
2582 | } | ||
2583 | |||
2584 | 6757 | static int copy_meta(Muxer *mux, const OptionsContext *o) | |
2585 | { | ||
2586 | 6757 | OutputFile *of = &mux->of; | |
2587 | 6757 | AVFormatContext *oc = mux->fc; | |
2588 | 6757 | int chapters_input_file = o->chapters_input_file; | |
2589 | 6757 | int metadata_global_manual = 0; | |
2590 | 6757 | int metadata_streams_manual = 0; | |
2591 | 6757 | int metadata_chapters_manual = 0; | |
2592 | int ret; | ||
2593 | |||
2594 | /* copy metadata */ | ||
2595 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 6757 times.
|
6764 | for (int i = 0; i < o->metadata_map.nb_opt; i++) { |
2596 | char *p; | ||
2597 | 7 | int in_file_index = strtol(o->metadata_map.opt[i].u.str, &p, 0); | |
2598 | |||
2599 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (in_file_index >= nb_input_files) { |
2600 | ✗ | av_log(mux, AV_LOG_FATAL, "Invalid input file index %d while " | |
2601 | "processing metadata maps\n", in_file_index); | ||
2602 | ✗ | return AVERROR(EINVAL); | |
2603 | } | ||
2604 | 10 | ret = copy_metadata(mux, | |
2605 | 5 | in_file_index >= 0 ? input_files[in_file_index]->ctx : NULL, | |
2606 |
4/4✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 2 times.
|
10 | o->metadata_map.opt[i].specifier, *p ? p + 1 : p, |
2607 | &metadata_global_manual, &metadata_streams_manual, | ||
2608 | &metadata_chapters_manual); | ||
2609 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (ret < 0) |
2610 | ✗ | return ret; | |
2611 | } | ||
2612 | |||
2613 | /* copy chapters */ | ||
2614 |
1/2✓ Branch 0 taken 6757 times.
✗ Branch 1 not taken.
|
6757 | if (chapters_input_file >= nb_input_files) { |
2615 |
1/2✓ Branch 0 taken 6757 times.
✗ Branch 1 not taken.
|
6757 | if (chapters_input_file == INT_MAX) { |
2616 | /* copy chapters from the first input file that has them*/ | ||
2617 | 6757 | chapters_input_file = -1; | |
2618 |
2/2✓ Branch 0 taken 6788 times.
✓ Branch 1 taken 6738 times.
|
13526 | for (int i = 0; i < nb_input_files; i++) |
2619 |
2/2✓ Branch 0 taken 19 times.
✓ Branch 1 taken 6769 times.
|
6788 | if (input_files[i]->ctx->nb_chapters) { |
2620 | 19 | chapters_input_file = i; | |
2621 | 19 | break; | |
2622 | } | ||
2623 | } else { | ||
2624 | ✗ | av_log(mux, AV_LOG_FATAL, "Invalid input file index %d in chapter mapping.\n", | |
2625 | chapters_input_file); | ||
2626 | ✗ | return AVERROR(EINVAL); | |
2627 | } | ||
2628 | } | ||
2629 |
2/2✓ Branch 0 taken 19 times.
✓ Branch 1 taken 6738 times.
|
6757 | if (chapters_input_file >= 0) |
2630 | 19 | copy_chapters(input_files[chapters_input_file], of, oc, | |
2631 | !metadata_chapters_manual); | ||
2632 | |||
2633 | /* copy global metadata by default */ | ||
2634 |
4/4✓ Branch 0 taken 6753 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 6699 times.
✓ Branch 3 taken 54 times.
|
6757 | if (!metadata_global_manual && nb_input_files){ |
2635 | 6699 | av_dict_copy(&oc->metadata, input_files[0]->ctx->metadata, | |
2636 | AV_DICT_DONT_OVERWRITE); | ||
2637 |
2/2✓ Branch 0 taken 179 times.
✓ Branch 1 taken 6520 times.
|
6699 | if (of->recording_time != INT64_MAX) |
2638 | 179 | av_dict_set(&oc->metadata, "duration", NULL, 0); | |
2639 | 6699 | av_dict_set(&oc->metadata, "creation_time", NULL, 0); | |
2640 | 6699 | av_dict_set(&oc->metadata, "company_name", NULL, 0); | |
2641 | 6699 | av_dict_set(&oc->metadata, "product_name", NULL, 0); | |
2642 | 6699 | av_dict_set(&oc->metadata, "product_version", NULL, 0); | |
2643 | } | ||
2644 |
2/2✓ Branch 0 taken 6755 times.
✓ Branch 1 taken 2 times.
|
6757 | if (!metadata_streams_manual) |
2645 |
2/2✓ Branch 0 taken 7094 times.
✓ Branch 1 taken 6755 times.
|
13849 | for (int i = 0; i < of->nb_streams; i++) { |
2646 | 7094 | OutputStream *ost = of->streams[i]; | |
2647 | |||
2648 |
2/2✓ Branch 0 taken 168 times.
✓ Branch 1 taken 6926 times.
|
7094 | if (!ost->ist) /* this is true e.g. for attached files */ |
2649 | 168 | continue; | |
2650 | 6926 | av_dict_copy(&ost->st->metadata, ost->ist->st->metadata, AV_DICT_DONT_OVERWRITE); | |
2651 |
2/2✓ Branch 0 taken 6300 times.
✓ Branch 1 taken 626 times.
|
6926 | if (ost->enc_ctx) { |
2652 | 6300 | av_dict_set(&ost->st->metadata, "encoder", NULL, 0); | |
2653 | } | ||
2654 | } | ||
2655 | |||
2656 | 6757 | return 0; | |
2657 | } | ||
2658 | |||
2659 | 6757 | static int set_dispositions(Muxer *mux, const OptionsContext *o) | |
2660 | { | ||
2661 | 6757 | OutputFile *of = &mux->of; | |
2662 | 6757 | AVFormatContext *ctx = mux->fc; | |
2663 | |||
2664 | // indexed by type+1, because AVMEDIA_TYPE_UNKNOWN=-1 | ||
2665 | 6757 | int nb_streams[AVMEDIA_TYPE_NB + 1] = { 0 }; | |
2666 | 6757 | int have_default[AVMEDIA_TYPE_NB + 1] = { 0 }; | |
2667 | 6757 | int have_manual = 0; | |
2668 | 6757 | int ret = 0; | |
2669 | |||
2670 | const char **dispositions; | ||
2671 | |||
2672 | 6757 | dispositions = av_calloc(ctx->nb_streams, sizeof(*dispositions)); | |
2673 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6757 times.
|
6757 | if (!dispositions) |
2674 | ✗ | return AVERROR(ENOMEM); | |
2675 | |||
2676 | // first, copy the input dispositions | ||
2677 |
2/2✓ Branch 0 taken 7099 times.
✓ Branch 1 taken 6757 times.
|
13856 | for (int i = 0; i < ctx->nb_streams; i++) { |
2678 | 7099 | OutputStream *ost = of->streams[i]; | |
2679 | |||
2680 | 7099 | nb_streams[ost->type + 1]++; | |
2681 | |||
2682 |
6/20✓ Branch 1 taken 16 times.
✓ Branch 2 taken 43 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 43 times.
✓ Branch 5 taken 59 times.
✓ Branch 6 taken 7099 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7099 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
7158 | MATCH_PER_STREAM_OPT(disposition, str, dispositions[i], ctx, ost->st); |
2683 | |||
2684 | 7099 | have_manual |= !!dispositions[i]; | |
2685 | |||
2686 |
2/2✓ Branch 0 taken 6931 times.
✓ Branch 1 taken 168 times.
|
7099 | if (ost->ist) { |
2687 | 6931 | ost->st->disposition = ost->ist->st->disposition; | |
2688 | |||
2689 |
2/2✓ Branch 0 taken 766 times.
✓ Branch 1 taken 6165 times.
|
6931 | if (ost->st->disposition & AV_DISPOSITION_DEFAULT) |
2690 | 766 | have_default[ost->type + 1] = 1; | |
2691 | } | ||
2692 | } | ||
2693 | |||
2694 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 6749 times.
|
6757 | if (have_manual) { |
2695 | // process manually set dispositions - they override the above copy | ||
2696 |
2/2✓ Branch 0 taken 23 times.
✓ Branch 1 taken 8 times.
|
31 | for (int i = 0; i < ctx->nb_streams; i++) { |
2697 | 23 | OutputStream *ost = of->streams[i]; | |
2698 | 23 | const char *disp = dispositions[i]; | |
2699 | |||
2700 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 16 times.
|
23 | if (!disp) |
2701 | 7 | continue; | |
2702 | |||
2703 | 16 | ret = av_opt_set(ost->st, "disposition", disp, 0); | |
2704 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
|
16 | if (ret < 0) |
2705 | ✗ | goto finish; | |
2706 | } | ||
2707 | } else { | ||
2708 | // For each media type with more than one stream, find a suitable stream to | ||
2709 | // mark as default, unless one is already marked default. | ||
2710 | // "Suitable" means the first of that type, skipping attached pictures. | ||
2711 |
2/2✓ Branch 0 taken 7076 times.
✓ Branch 1 taken 6749 times.
|
13825 | for (int i = 0; i < ctx->nb_streams; i++) { |
2712 | 7076 | OutputStream *ost = of->streams[i]; | |
2713 | 7076 | enum AVMediaType type = ost->type; | |
2714 | |||
2715 |
4/4✓ Branch 0 taken 226 times.
✓ Branch 1 taken 6850 times.
✓ Branch 2 taken 62 times.
✓ Branch 3 taken 164 times.
|
7076 | if (nb_streams[type + 1] < 2 || have_default[type + 1] || |
2716 |
2/2✓ Branch 0 taken 32 times.
✓ Branch 1 taken 30 times.
|
62 | ost->st->disposition & AV_DISPOSITION_ATTACHED_PIC) |
2717 | 7046 | continue; | |
2718 | |||
2719 | 30 | ost->st->disposition |= AV_DISPOSITION_DEFAULT; | |
2720 | 30 | have_default[type + 1] = 1; | |
2721 | } | ||
2722 | } | ||
2723 | |||
2724 | 6749 | finish: | |
2725 | 6757 | av_freep(&dispositions); | |
2726 | |||
2727 | 6757 | return ret; | |
2728 | } | ||
2729 | |||
2730 | const char *const forced_keyframes_const_names[] = { | ||
2731 | "n", | ||
2732 | "n_forced", | ||
2733 | "prev_forced_n", | ||
2734 | "prev_forced_t", | ||
2735 | "t", | ||
2736 | NULL | ||
2737 | }; | ||
2738 | |||
2739 | 1 | static int compare_int64(const void *a, const void *b) | |
2740 | { | ||
2741 | 1 | return FFDIFFSIGN(*(const int64_t *)a, *(const int64_t *)b); | |
2742 | } | ||
2743 | |||
2744 | 1 | static int parse_forced_key_frames(void *log, KeyframeForceCtx *kf, | |
2745 | const Muxer *mux, const char *spec) | ||
2746 | { | ||
2747 | const char *p; | ||
2748 | 1 | int n = 1, i, ret, size, index = 0; | |
2749 | int64_t t, *pts; | ||
2750 | |||
2751 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1 times.
|
14 | for (p = spec; *p; p++) |
2752 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12 times.
|
13 | if (*p == ',') |
2753 | 1 | n++; | |
2754 | 1 | size = n; | |
2755 | 1 | pts = av_malloc_array(size, sizeof(*pts)); | |
2756 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!pts) |
2757 | ✗ | return AVERROR(ENOMEM); | |
2758 | |||
2759 | 1 | p = spec; | |
2760 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
3 | for (i = 0; i < n; i++) { |
2761 | 2 | char *next = strchr(p, ','); | |
2762 | |||
2763 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | if (next) |
2764 | 1 | *next++ = 0; | |
2765 | |||
2766 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (strstr(p, "chapters") == p) { |
2767 | ✗ | AVChapter * const *ch = mux->fc->chapters; | |
2768 | ✗ | unsigned int nb_ch = mux->fc->nb_chapters; | |
2769 | int j; | ||
2770 | |||
2771 | ✗ | if (nb_ch > INT_MAX - size || | |
2772 | ✗ | !(pts = av_realloc_f(pts, size += nb_ch - 1, | |
2773 | sizeof(*pts)))) | ||
2774 | ✗ | return AVERROR(ENOMEM); | |
2775 | |||
2776 | ✗ | if (p[8]) { | |
2777 | ✗ | ret = av_parse_time(&t, p + 8, 1); | |
2778 | ✗ | if (ret < 0) { | |
2779 | ✗ | av_log(log, AV_LOG_ERROR, | |
2780 | "Invalid chapter time offset: %s\n", p + 8); | ||
2781 | ✗ | goto fail; | |
2782 | } | ||
2783 | } else | ||
2784 | ✗ | t = 0; | |
2785 | |||
2786 | ✗ | for (j = 0; j < nb_ch; j++) { | |
2787 | ✗ | const AVChapter *c = ch[j]; | |
2788 | av_assert1(index < size); | ||
2789 | ✗ | pts[index++] = av_rescale_q(c->start, c->time_base, | |
2790 | ✗ | AV_TIME_BASE_Q) + t; | |
2791 | } | ||
2792 | |||
2793 | } else { | ||
2794 | av_assert1(index < size); | ||
2795 | 2 | ret = av_parse_time(&t, p, 1); | |
2796 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (ret < 0) { |
2797 | ✗ | av_log(log, AV_LOG_ERROR, "Invalid keyframe time: %s\n", p); | |
2798 | ✗ | goto fail; | |
2799 | } | ||
2800 | |||
2801 | 2 | pts[index++] = t; | |
2802 | } | ||
2803 | |||
2804 | 2 | p = next; | |
2805 | } | ||
2806 | |||
2807 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | av_assert0(index == size); |
2808 | 1 | qsort(pts, size, sizeof(*pts), compare_int64); | |
2809 | 1 | kf->nb_pts = size; | |
2810 | 1 | kf->pts = pts; | |
2811 | |||
2812 | 1 | return 0; | |
2813 | ✗ | fail: | |
2814 | ✗ | av_freep(&pts); | |
2815 | ✗ | return ret; | |
2816 | } | ||
2817 | |||
2818 | 6757 | static int process_forced_keyframes(Muxer *mux, const OptionsContext *o) | |
2819 | { | ||
2820 |
2/2✓ Branch 0 taken 7099 times.
✓ Branch 1 taken 6757 times.
|
13856 | for (int i = 0; i < mux->of.nb_streams; i++) { |
2821 | 7099 | OutputStream *ost = mux->of.streams[i]; | |
2822 | 7099 | const char *forced_keyframes = NULL; | |
2823 | |||
2824 |
4/20✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 7099 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7099 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
7103 | MATCH_PER_STREAM_OPT(forced_key_frames, str, forced_keyframes, mux->fc, ost->st); |
2825 | |||
2826 |
4/4✓ Branch 0 taken 5523 times.
✓ Branch 1 taken 1576 times.
✓ Branch 2 taken 5188 times.
✓ Branch 3 taken 4 times.
|
12291 | if (!(ost->type == AVMEDIA_TYPE_VIDEO && |
2827 |
2/2✓ Branch 0 taken 5192 times.
✓ Branch 1 taken 331 times.
|
5523 | ost->enc_ctx && forced_keyframes)) |
2828 | 7095 | continue; | |
2829 | |||
2830 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (!strncmp(forced_keyframes, "expr:", 5)) { |
2831 | ✗ | int ret = av_expr_parse(&ost->kf.pexpr, forced_keyframes + 5, | |
2832 | forced_keyframes_const_names, NULL, NULL, NULL, NULL, 0, NULL); | ||
2833 | ✗ | if (ret < 0) { | |
2834 | ✗ | av_log(ost, AV_LOG_ERROR, | |
2835 | "Invalid force_key_frames expression '%s'\n", forced_keyframes + 5); | ||
2836 | ✗ | return ret; | |
2837 | } | ||
2838 | ✗ | ost->kf.expr_const_values[FKF_N] = 0; | |
2839 | ✗ | ost->kf.expr_const_values[FKF_N_FORCED] = 0; | |
2840 | ✗ | ost->kf.expr_const_values[FKF_PREV_FORCED_N] = NAN; | |
2841 | ✗ | ost->kf.expr_const_values[FKF_PREV_FORCED_T] = NAN; | |
2842 | |||
2843 | // Don't parse the 'forced_keyframes' in case of 'keep-source-keyframes', | ||
2844 | // parse it only for static kf timings | ||
2845 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
|
4 | } else if (!strcmp(forced_keyframes, "source")) { |
2846 | 3 | ost->kf.type = KF_FORCE_SOURCE; | |
2847 | #if FFMPEG_OPT_FORCE_KF_SOURCE_NO_DROP | ||
2848 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | } else if (!strcmp(forced_keyframes, "source_no_drop")) { |
2849 | ✗ | av_log(ost, AV_LOG_WARNING, "The 'source_no_drop' value for " | |
2850 | "-force_key_frames is deprecated, use just 'source'\n"); | ||
2851 | ✗ | ost->kf.type = KF_FORCE_SOURCE; | |
2852 | #endif | ||
2853 | } else { | ||
2854 | 1 | int ret = parse_forced_key_frames(ost, &ost->kf, mux, forced_keyframes); | |
2855 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (ret < 0) |
2856 | ✗ | return ret; | |
2857 | } | ||
2858 | } | ||
2859 | |||
2860 | 6757 | return 0; | |
2861 | } | ||
2862 | |||
2863 | 6757 | static int validate_enc_avopt(Muxer *mux, const AVDictionary *codec_avopt) | |
2864 | { | ||
2865 | 6757 | const AVClass *class = avcodec_get_class(); | |
2866 | 6757 | const AVClass *fclass = avformat_get_class(); | |
2867 | 6757 | const OutputFile *of = &mux->of; | |
2868 | |||
2869 | AVDictionary *unused_opts; | ||
2870 | const AVDictionaryEntry *e; | ||
2871 | |||
2872 | 6757 | unused_opts = strip_specifiers(codec_avopt); | |
2873 |
2/2✓ Branch 0 taken 7099 times.
✓ Branch 1 taken 6757 times.
|
13856 | for (int i = 0; i < of->nb_streams; i++) { |
2874 | 7099 | e = NULL; | |
2875 |
2/2✓ Branch 1 taken 15711 times.
✓ Branch 2 taken 7099 times.
|
22810 | while ((e = av_dict_iterate(of->streams[i]->encoder_opts, e))) |
2876 | 15711 | av_dict_set(&unused_opts, e->key, NULL, 0); | |
2877 | } | ||
2878 | |||
2879 | 6757 | e = NULL; | |
2880 |
2/2✓ Branch 1 taken 1094 times.
✓ Branch 2 taken 6757 times.
|
7851 | while ((e = av_dict_iterate(unused_opts, e))) { |
2881 | 1094 | const AVOption *option = av_opt_find(&class, e->key, NULL, 0, | |
2882 | AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ); | ||
2883 | 1094 | const AVOption *foption = av_opt_find(&fclass, e->key, NULL, 0, | |
2884 | AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ); | ||
2885 |
4/4✓ Branch 0 taken 1093 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 1089 times.
|
1094 | if (!option || foption) |
2886 | 5 | continue; | |
2887 | |||
2888 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1089 times.
|
1089 | if (!(option->flags & AV_OPT_FLAG_ENCODING_PARAM)) { |
2889 | ✗ | av_log(mux, AV_LOG_ERROR, "Codec AVOption %s (%s) is not an " | |
2890 | ✗ | "encoding option.\n", e->key, option->help ? option->help : ""); | |
2891 | ✗ | return AVERROR(EINVAL); | |
2892 | } | ||
2893 | |||
2894 | // gop_timecode is injected by generic code but not always used | ||
2895 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1081 times.
|
1089 | if (!strcmp(e->key, "gop_timecode")) |
2896 | 8 | continue; | |
2897 | |||
2898 | 1081 | av_log(mux, AV_LOG_WARNING, "Codec AVOption %s (%s) has not been used " | |
2899 | "for any stream. The most likely reason is either wrong type " | ||
2900 | "(e.g. a video option with no video streams) or that it is a " | ||
2901 | "private option of some encoder which was not actually used for " | ||
2902 |
2/2✓ Branch 0 taken 890 times.
✓ Branch 1 taken 191 times.
|
2162 | "any stream.\n", e->key, option->help ? option->help : ""); |
2903 | } | ||
2904 | 6757 | av_dict_free(&unused_opts); | |
2905 | |||
2906 | 6757 | return 0; | |
2907 | } | ||
2908 | |||
2909 | 7862 | static const char *output_file_item_name(void *obj) | |
2910 | { | ||
2911 | 7862 | const Muxer *mux = obj; | |
2912 | |||
2913 | 7862 | return mux->log_name; | |
2914 | } | ||
2915 | |||
2916 | static const AVClass output_file_class = { | ||
2917 | .class_name = "OutputFile", | ||
2918 | .version = LIBAVUTIL_VERSION_INT, | ||
2919 | .item_name = output_file_item_name, | ||
2920 | .category = AV_CLASS_CATEGORY_MUXER, | ||
2921 | }; | ||
2922 | |||
2923 | 6757 | static Muxer *mux_alloc(void) | |
2924 | { | ||
2925 | 6757 | Muxer *mux = allocate_array_elem(&output_files, sizeof(*mux), &nb_output_files); | |
2926 | |||
2927 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6757 times.
|
6757 | if (!mux) |
2928 | ✗ | return NULL; | |
2929 | |||
2930 | 6757 | mux->of.class = &output_file_class; | |
2931 | 6757 | mux->of.index = nb_output_files - 1; | |
2932 | |||
2933 | 6757 | snprintf(mux->log_name, sizeof(mux->log_name), "out#%d", mux->of.index); | |
2934 | |||
2935 | 6757 | return mux; | |
2936 | } | ||
2937 | |||
2938 | 6757 | int of_open(const OptionsContext *o, const char *filename, Scheduler *sch) | |
2939 | { | ||
2940 | Muxer *mux; | ||
2941 | AVFormatContext *oc; | ||
2942 | int err; | ||
2943 | OutputFile *of; | ||
2944 | |||
2945 | 6757 | int64_t recording_time = o->recording_time; | |
2946 | 6757 | int64_t stop_time = o->stop_time; | |
2947 | |||
2948 | 6757 | mux = mux_alloc(); | |
2949 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6757 times.
|
6757 | if (!mux) |
2950 | ✗ | return AVERROR(ENOMEM); | |
2951 | |||
2952 | 6757 | of = &mux->of; | |
2953 | |||
2954 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 6757 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
6757 | if (stop_time != INT64_MAX && recording_time != INT64_MAX) { |
2955 | ✗ | stop_time = INT64_MAX; | |
2956 | ✗ | av_log(mux, AV_LOG_WARNING, "-t and -to cannot be used together; using -t.\n"); | |
2957 | } | ||
2958 | |||
2959 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 6757 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
6757 | if (stop_time != INT64_MAX && recording_time == INT64_MAX) { |
2960 | ✗ | int64_t start_time = o->start_time == AV_NOPTS_VALUE ? 0 : o->start_time; | |
2961 | ✗ | if (stop_time <= start_time) { | |
2962 | ✗ | av_log(mux, AV_LOG_ERROR, "-to value smaller than -ss; aborting.\n"); | |
2963 | ✗ | return AVERROR(EINVAL); | |
2964 | } else { | ||
2965 | ✗ | recording_time = stop_time - start_time; | |
2966 | } | ||
2967 | } | ||
2968 | |||
2969 | 6757 | of->recording_time = recording_time; | |
2970 | 6757 | of->start_time = o->start_time; | |
2971 | 6757 | of->shortest = o->shortest; | |
2972 | |||
2973 | 6757 | mux->limit_filesize = o->limit_filesize; | |
2974 | 6757 | av_dict_copy(&mux->opts, o->g->format_opts, 0); | |
2975 | |||
2976 |
2/2✓ Branch 0 taken 2590 times.
✓ Branch 1 taken 4167 times.
|
6757 | if (!strcmp(filename, "-")) |
2977 | 2590 | filename = "pipe:"; | |
2978 | |||
2979 | 6757 | err = avformat_alloc_output_context2(&oc, NULL, o->format, filename); | |
2980 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6757 times.
|
6757 | if (!oc) { |
2981 | ✗ | av_log(mux, AV_LOG_FATAL, "Error initializing the muxer for %s: %s\n", | |
2982 | ✗ | filename, av_err2str(err)); | |
2983 | ✗ | return err; | |
2984 | } | ||
2985 | 6757 | mux->fc = oc; | |
2986 | |||
2987 | 6757 | av_strlcat(mux->log_name, "/", sizeof(mux->log_name)); | |
2988 | 6757 | av_strlcat(mux->log_name, oc->oformat->name, sizeof(mux->log_name)); | |
2989 | |||
2990 | |||
2991 | 6757 | of->format = oc->oformat; | |
2992 |
2/2✓ Branch 0 taken 185 times.
✓ Branch 1 taken 6572 times.
|
6757 | if (recording_time != INT64_MAX) |
2993 | 185 | oc->duration = recording_time; | |
2994 | |||
2995 | 6757 | oc->interrupt_callback = int_cb; | |
2996 | |||
2997 |
2/2✓ Branch 0 taken 1793 times.
✓ Branch 1 taken 4964 times.
|
6757 | if (o->bitexact) { |
2998 | 1793 | oc->flags |= AVFMT_FLAG_BITEXACT; | |
2999 | 1793 | of->bitexact = 1; | |
3000 | } else { | ||
3001 | 4964 | of->bitexact = check_opt_bitexact(oc, mux->opts, "fflags", | |
3002 | AVFMT_FLAG_BITEXACT); | ||
3003 | } | ||
3004 | |||
3005 | 6757 | err = sch_add_mux(sch, muxer_thread, mux_check_init, mux, | |
3006 | 6757 | !strcmp(oc->oformat->name, "rtp"), o->thread_queue_size); | |
3007 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6757 times.
|
6757 | if (err < 0) |
3008 | ✗ | return err; | |
3009 | 6757 | mux->sch = sch; | |
3010 | 6757 | mux->sch_idx = err; | |
3011 | |||
3012 | /* create all output streams for this file */ | ||
3013 | 6757 | err = create_streams(mux, o); | |
3014 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6757 times.
|
6757 | if (err < 0) |
3015 | ✗ | return err; | |
3016 | |||
3017 | /* check if all codec options have been used */ | ||
3018 | 6757 | err = validate_enc_avopt(mux, o->g->codec_opts); | |
3019 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6757 times.
|
6757 | if (err < 0) |
3020 | ✗ | return err; | |
3021 | |||
3022 | /* check filename in case of an image number is expected */ | ||
3023 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 6757 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
6757 | if (oc->oformat->flags & AVFMT_NEEDNUMBER && !av_filename_number_test(oc->url)) { |
3024 | ✗ | av_log(mux, AV_LOG_FATAL, | |
3025 | "Output filename '%s' does not contain a numeric pattern like " | ||
3026 | "'%%d', which is required by output format '%s'.\n", | ||
3027 | ✗ | oc->url, oc->oformat->name); | |
3028 | ✗ | return AVERROR(EINVAL); | |
3029 | } | ||
3030 | |||
3031 |
2/2✓ Branch 0 taken 6666 times.
✓ Branch 1 taken 91 times.
|
6757 | if (!(oc->oformat->flags & AVFMT_NOFILE)) { |
3032 | /* test if it already exists to avoid losing precious files */ | ||
3033 | 6666 | err = assert_file_overwrite(filename); | |
3034 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6666 times.
|
6666 | if (err < 0) |
3035 | ✗ | return err; | |
3036 | |||
3037 | /* open the file */ | ||
3038 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6666 times.
|
6666 | if ((err = avio_open2(&oc->pb, filename, AVIO_FLAG_WRITE, |
3039 | 6666 | &oc->interrupt_callback, | |
3040 | &mux->opts)) < 0) { | ||
3041 | ✗ | av_log(mux, AV_LOG_FATAL, "Error opening output %s: %s\n", | |
3042 | ✗ | filename, av_err2str(err)); | |
3043 | ✗ | return err; | |
3044 | } | ||
3045 |
4/4✓ Branch 0 taken 58 times.
✓ Branch 1 taken 33 times.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 51 times.
|
91 | } else if (strcmp(oc->oformat->name, "image2")==0 && !av_filename_number_test(filename)) { |
3046 | 7 | err = assert_file_overwrite(filename); | |
3047 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (err < 0) |
3048 | ✗ | return err; | |
3049 | } | ||
3050 | |||
3051 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6757 times.
|
6757 | if (o->mux_preload) { |
3052 | ✗ | av_dict_set_int(&mux->opts, "preload", o->mux_preload*AV_TIME_BASE, 0); | |
3053 | } | ||
3054 | 6757 | oc->max_delay = (int)(o->mux_max_delay * AV_TIME_BASE); | |
3055 | |||
3056 | /* copy metadata and chapters from input files */ | ||
3057 | 6757 | err = copy_meta(mux, o); | |
3058 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6757 times.
|
6757 | if (err < 0) |
3059 | ✗ | return err; | |
3060 | |||
3061 | 6757 | err = of_add_groups(mux, o); | |
3062 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6757 times.
|
6757 | if (err < 0) |
3063 | ✗ | return err; | |
3064 | |||
3065 | 6757 | err = of_add_programs(mux, o); | |
3066 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6757 times.
|
6757 | if (err < 0) |
3067 | ✗ | return err; | |
3068 | |||
3069 | 6757 | err = of_add_metadata(of, oc, o); | |
3070 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6757 times.
|
6757 | if (err < 0) |
3071 | ✗ | return err; | |
3072 | |||
3073 | 6757 | err = set_dispositions(mux, o); | |
3074 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6757 times.
|
6757 | if (err < 0) { |
3075 | ✗ | av_log(mux, AV_LOG_FATAL, "Error setting output stream dispositions\n"); | |
3076 | ✗ | return err; | |
3077 | } | ||
3078 | |||
3079 | // parse forced keyframe specifications; | ||
3080 | // must be done after chapters are created | ||
3081 | 6757 | err = process_forced_keyframes(mux, o); | |
3082 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6757 times.
|
6757 | if (err < 0) { |
3083 | ✗ | av_log(mux, AV_LOG_FATAL, "Error processing forced keyframes\n"); | |
3084 | ✗ | return err; | |
3085 | } | ||
3086 | |||
3087 | 6757 | err = setup_sync_queues(mux, oc, o->shortest_buf_duration * AV_TIME_BASE); | |
3088 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6757 times.
|
6757 | if (err < 0) { |
3089 | ✗ | av_log(mux, AV_LOG_FATAL, "Error setting up output sync queues\n"); | |
3090 | ✗ | return err; | |
3091 | } | ||
3092 | |||
3093 | 6757 | of->url = filename; | |
3094 | |||
3095 | /* initialize streamcopy streams. */ | ||
3096 |
2/2✓ Branch 0 taken 7099 times.
✓ Branch 1 taken 6757 times.
|
13856 | for (int i = 0; i < of->nb_streams; i++) { |
3097 | 7099 | OutputStream *ost = of->streams[i]; | |
3098 | |||
3099 |
2/2✓ Branch 0 taken 628 times.
✓ Branch 1 taken 6471 times.
|
7099 | if (!ost->enc) { |
3100 | 628 | err = of_stream_init(of, ost); | |
3101 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 628 times.
|
628 | if (err < 0) |
3102 | ✗ | return err; | |
3103 | } | ||
3104 | } | ||
3105 | |||
3106 | 6757 | return 0; | |
3107 | } | ||
3108 |