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 | 4982 | static int check_opt_bitexact(void *ctx, const AVDictionary *opts, | |
54 | const char *opt_name, int flag) | ||
55 | { | ||
56 | 4982 | const AVDictionaryEntry *e = av_dict_get(opts, opt_name, NULL, 0); | |
57 | |||
58 |
2/2✓ Branch 0 taken 4009 times.
✓ Branch 1 taken 973 times.
|
4982 | if (e) { |
59 | 4009 | const AVOption *o = av_opt_find(ctx, opt_name, NULL, 0, 0); | |
60 | 4009 | int val = 0; | |
61 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4009 times.
|
4009 | if (!o) |
62 | ✗ | return 0; | |
63 | 4009 | av_opt_eval_flags(ctx, o, e->value, &val); | |
64 | 4009 | return !!(val & flag); | |
65 | } | ||
66 | 973 | return 0; | |
67 | } | ||
68 | |||
69 | 7133 | static int choose_encoder(const OptionsContext *o, AVFormatContext *s, | |
70 | OutputStream *ost, const AVCodec **enc) | ||
71 | { | ||
72 | 7133 | enum AVMediaType type = ost->type; | |
73 | 7133 | char *codec_name = NULL; | |
74 | |||
75 | 7133 | *enc = NULL; | |
76 | |||
77 |
16/20✓ Branch 1 taken 4305 times.
✓ Branch 2 taken 199 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 199 times.
✓ Branch 5 taken 4504 times.
✓ Branch 6 taken 7133 times.
✓ Branch 7 taken 62 times.
✓ Branch 8 taken 7071 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.
|
11947 | MATCH_PER_STREAM_OPT(codec_names, str, codec_name, s, ost->st); |
78 | |||
79 |
4/4✓ Branch 0 taken 1594 times.
✓ Branch 1 taken 5539 times.
✓ Branch 2 taken 82 times.
✓ Branch 3 taken 1512 times.
|
7133 | 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 2883 times.
✓ Branch 1 taken 4239 times.
|
7122 | if (!codec_name) { |
93 | 2883 | ost->par_in->codec_id = av_guess_codec(s->oformat, NULL, s->url, NULL, ost->type); | |
94 | 2883 | *enc = avcodec_find_encoder(ost->par_in->codec_id); | |
95 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2883 times.
|
2883 | 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 3604 times.
✓ Branch 1 taken 635 times.
|
4239 | } else if (strcmp(codec_name, "copy")) { |
103 | 3604 | int ret = find_codec(ost, codec_name, ost->type, 1, enc); | |
104 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3604 times.
|
3604 | if (ret < 0) |
105 | ✗ | return ret; | |
106 | 3604 | ost->par_in->codec_id = (*enc)->id; | |
107 | } | ||
108 | |||
109 | 7122 | 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 | 6779 | void of_enc_stats_close(void) | |
197 | { | ||
198 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6779 times.
|
6779 | 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 | 6779 | av_freep(&enc_stats_files); | |
203 | 6779 | nb_enc_stats_files = 0; | |
204 | 6779 | } | |
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 | 28 | static const char *output_stream_item_name(void *obj) | |
378 | { | ||
379 | 28 | const MuxStream *ms = obj; | |
380 | |||
381 | 28 | 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 | 7133 | static MuxStream *mux_stream_alloc(Muxer *mux, enum AVMediaType type) | |
392 | { | ||
393 | 7133 | const char *type_str = av_get_media_type_string(type); | |
394 | MuxStream *ms; | ||
395 | |||
396 | 7133 | ms = allocate_array_elem(&mux->of.streams, sizeof(*ms), &mux->of.nb_streams); | |
397 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7133 times.
|
7133 | if (!ms) |
398 | ✗ | return NULL; | |
399 | |||
400 | 7133 | ms->ost.file = &mux->of; | |
401 | 7133 | ms->ost.index = mux->of.nb_streams - 1; | |
402 | 7133 | ms->ost.type = type; | |
403 | |||
404 | 7133 | ms->ost.class = &output_stream_class; | |
405 | |||
406 | 7133 | ms->sch_idx = -1; | |
407 | 7133 | ms->sch_idx_enc = -1; | |
408 | |||
409 |
1/2✓ Branch 0 taken 7133 times.
✗ Branch 1 not taken.
|
7133 | snprintf(ms->log_name, sizeof(ms->log_name), "%cost#%d:%d", |
410 | 7133 | type_str ? *type_str : '?', mux->of.index, ms->ost.index); | |
411 | |||
412 | 7133 | return ms; | |
413 | } | ||
414 | |||
415 | 7051 | static int ost_get_filters(const OptionsContext *o, AVFormatContext *oc, | |
416 | OutputStream *ost, char **dst) | ||
417 | { | ||
418 | 7051 | const char *filters = NULL; | |
419 | #if FFMPEG_OPT_FILTER_SCRIPT | ||
420 | 7051 | 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 7051 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7051 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.
|
7051 | MATCH_PER_STREAM_OPT(filter_scripts, str, filters_script, oc, ost->st); |
423 | #endif | ||
424 |
6/20✓ Branch 1 taken 3488 times.
✓ Branch 2 taken 91 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 91 times.
✓ Branch 5 taken 3579 times.
✓ Branch 6 taken 7051 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7051 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.
|
10630 | MATCH_PER_STREAM_OPT(filters, str, filters, oc, ost->st); |
425 | |||
426 |
2/2✓ Branch 0 taken 602 times.
✓ Branch 1 taken 6449 times.
|
7051 | if (!ost->enc) { |
427 |
1/2✓ Branch 0 taken 602 times.
✗ Branch 1 not taken.
|
602 | if ( |
428 | #if FFMPEG_OPT_FILTER_SCRIPT | ||
429 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 602 times.
|
602 | 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 | 602 | return 0; | |
445 | } | ||
446 | |||
447 |
2/2✓ Branch 0 taken 168 times.
✓ Branch 1 taken 6281 times.
|
6449 | if (!ost->ist) { |
448 |
1/2✓ Branch 0 taken 168 times.
✗ Branch 1 not taken.
|
168 | if ( |
449 | #if FFMPEG_OPT_FILTER_SCRIPT | ||
450 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 168 times.
|
168 | 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 | 168 | return 0; | |
467 | } | ||
468 | |||
469 | #if FFMPEG_OPT_FILTER_SCRIPT | ||
470 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 6281 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
6281 | 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 6281 times.
|
6281 | if (filters_script) |
476 | ✗ | *dst = file_read(filters_script); | |
477 | else | ||
478 | #endif | ||
479 |
2/2✓ Branch 0 taken 3488 times.
✓ Branch 1 taken 2793 times.
|
6281 | if (filters) |
480 | 3488 | *dst = av_strdup(filters); | |
481 | else | ||
482 |
2/2✓ Branch 0 taken 2209 times.
✓ Branch 1 taken 584 times.
|
2793 | *dst = av_strdup(ost->type == AVMEDIA_TYPE_VIDEO ? "null" : "anull"); |
483 |
1/2✓ Branch 0 taken 6281 times.
✗ Branch 1 not taken.
|
6281 | 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 | 624 | static int fmt_in_list(const int *formats, int format) | |
506 | { | ||
507 |
1/2✓ Branch 0 taken 3376 times.
✗ Branch 1 not taken.
|
3376 | for (; *formats != -1; formats++) |
508 |
2/2✓ Branch 0 taken 624 times.
✓ Branch 1 taken 2752 times.
|
3376 | if (*formats == format) |
509 | 624 | 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 | 3741 | static enum AVPixelFormat pix_fmt_parse(OutputStream *ost, const char *name) | |
540 | { | ||
541 | 3741 | const enum AVPixelFormat *fmts = ost->enc_ctx->codec->pix_fmts; | |
542 | enum AVPixelFormat fmt; | ||
543 | |||
544 | 3741 | fmt = av_get_pix_fmt(name); | |
545 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3741 times.
|
3741 | 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 312 times.
✓ Branch 1 taken 3429 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 312 times.
|
3741 | 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 312 times.
✓ Branch 1 taken 3429 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 312 times.
|
3741 | if (fmts && !fmt_in_list(fmts, fmt)) |
577 | ✗ | fmt = choose_pixel_fmt(ost->enc_ctx->codec, fmt); | |
578 | |||
579 | 3741 | return fmt; | |
580 | } | ||
581 | |||
582 | 5539 | static int new_stream_video(Muxer *mux, const OptionsContext *o, | |
583 | OutputStream *ost, int *keep_pix_fmt, | ||
584 | enum VideoSyncMethod *vsync_method) | ||
585 | { | ||
586 | 5539 | MuxStream *ms = ms_from_ost(ost); | |
587 | 5539 | AVFormatContext *oc = mux->fc; | |
588 | AVStream *st; | ||
589 | 5539 | char *frame_rate = NULL, *max_frame_rate = NULL, *frame_aspect_ratio = NULL; | |
590 | 5539 | int ret = 0; | |
591 | |||
592 | 5539 | st = ost->st; | |
593 | |||
594 |
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 5539 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5539 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.
|
5561 | MATCH_PER_STREAM_OPT(frame_rates, str, frame_rate, oc, st); |
595 |
3/4✓ Branch 0 taken 22 times.
✓ Branch 1 taken 5517 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 22 times.
|
5539 | if (frame_rate && av_parse_video_rate(&ost->frame_rate, frame_rate) < 0) { |
596 | ✗ | av_log(ost, AV_LOG_FATAL, "Invalid framerate value: %s\n", frame_rate); | |
597 | ✗ | return AVERROR(EINVAL); | |
598 | } | ||
599 | |||
600 |
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 5539 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5539 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.
|
5539 | MATCH_PER_STREAM_OPT(max_frame_rates, str, max_frame_rate, oc, st); |
601 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 5539 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
5539 | if (max_frame_rate && av_parse_video_rate(&ost->max_frame_rate, max_frame_rate) < 0) { |
602 | ✗ | av_log(ost, AV_LOG_FATAL, "Invalid maximum framerate value: %s\n", max_frame_rate); | |
603 | ✗ | return AVERROR(EINVAL); | |
604 | } | ||
605 | |||
606 |
3/4✓ Branch 0 taken 22 times.
✓ Branch 1 taken 5517 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 22 times.
|
5539 | if (frame_rate && max_frame_rate) { |
607 | ✗ | av_log(ost, AV_LOG_ERROR, "Only one of -fpsmax and -r can be set for a stream.\n"); | |
608 | ✗ | return AVERROR(EINVAL); | |
609 | } | ||
610 | |||
611 |
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 5539 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5539 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.
|
5539 | MATCH_PER_STREAM_OPT(frame_aspect_ratios, str, frame_aspect_ratio, oc, st); |
612 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5539 times.
|
5539 | if (frame_aspect_ratio) { |
613 | AVRational q; | ||
614 | ✗ | if (av_parse_ratio(&q, frame_aspect_ratio, 255, 0, NULL) < 0 || | |
615 | ✗ | q.num <= 0 || q.den <= 0) { | |
616 | ✗ | av_log(ost, AV_LOG_FATAL, "Invalid aspect ratio: %s\n", frame_aspect_ratio); | |
617 | ✗ | return AVERROR(EINVAL); | |
618 | } | ||
619 | ✗ | ost->frame_aspect_ratio = q; | |
620 | } | ||
621 | |||
622 |
2/2✓ Branch 0 taken 5202 times.
✓ Branch 1 taken 337 times.
|
5539 | if (ost->enc_ctx) { |
623 | 5202 | AVCodecContext *video_enc = ost->enc_ctx; | |
624 | 5202 | const char *p = NULL, *fps_mode = NULL; | |
625 | 5202 | char *frame_size = NULL; | |
626 | 5202 | char *frame_pix_fmt = NULL; | |
627 | 5202 | char *intra_matrix = NULL, *inter_matrix = NULL; | |
628 | 5202 | char *chroma_intra_matrix = NULL; | |
629 | 5202 | int do_pass = 0; | |
630 | int i; | ||
631 | |||
632 |
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 5202 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5202 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.
|
5433 | MATCH_PER_STREAM_OPT(frame_sizes, str, frame_size, oc, st); |
633 |
2/2✓ Branch 0 taken 231 times.
✓ Branch 1 taken 4971 times.
|
5202 | if (frame_size) { |
634 | 231 | ret = av_parse_video_size(&video_enc->width, &video_enc->height, frame_size); | |
635 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 231 times.
|
231 | if (ret < 0) { |
636 | ✗ | av_log(ost, AV_LOG_FATAL, "Invalid frame size: %s.\n", frame_size); | |
637 | ✗ | return AVERROR(EINVAL); | |
638 | } | ||
639 | } | ||
640 | |||
641 |
4/20✓ Branch 1 taken 3741 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3741 times.
✓ Branch 6 taken 5202 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5202 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.
|
8943 | MATCH_PER_STREAM_OPT(frame_pix_fmts, str, frame_pix_fmt, oc, st); |
642 |
3/4✓ Branch 0 taken 3741 times.
✓ Branch 1 taken 1461 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3741 times.
|
5202 | if (frame_pix_fmt && *frame_pix_fmt == '+') { |
643 | ✗ | *keep_pix_fmt = 1; | |
644 | ✗ | if (!*++frame_pix_fmt) | |
645 | ✗ | frame_pix_fmt = NULL; | |
646 | } | ||
647 |
2/2✓ Branch 0 taken 3741 times.
✓ Branch 1 taken 1461 times.
|
5202 | if (frame_pix_fmt) { |
648 | 3741 | video_enc->pix_fmt = pix_fmt_parse(ost, frame_pix_fmt); | |
649 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3741 times.
|
3741 | if (video_enc->pix_fmt == AV_PIX_FMT_NONE) |
650 | ✗ | return AVERROR(EINVAL); | |
651 | } | ||
652 | |||
653 |
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 5202 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5202 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.
|
5202 | MATCH_PER_STREAM_OPT(intra_matrices, str, intra_matrix, oc, st); |
654 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5202 times.
|
5202 | if (intra_matrix) { |
655 | ✗ | if (!(video_enc->intra_matrix = av_mallocz(sizeof(*video_enc->intra_matrix) * 64))) | |
656 | ✗ | return AVERROR(ENOMEM); | |
657 | |||
658 | ✗ | ret = parse_matrix_coeffs(ost, video_enc->intra_matrix, intra_matrix); | |
659 | ✗ | if (ret < 0) | |
660 | ✗ | return ret; | |
661 | } | ||
662 |
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 5202 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5202 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.
|
5202 | MATCH_PER_STREAM_OPT(chroma_intra_matrices, str, chroma_intra_matrix, oc, st); |
663 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5202 times.
|
5202 | if (chroma_intra_matrix) { |
664 | ✗ | uint16_t *p = av_mallocz(sizeof(*video_enc->chroma_intra_matrix) * 64); | |
665 | ✗ | if (!p) | |
666 | ✗ | return AVERROR(ENOMEM); | |
667 | ✗ | video_enc->chroma_intra_matrix = p; | |
668 | ✗ | ret = parse_matrix_coeffs(ost, p, chroma_intra_matrix); | |
669 | ✗ | if (ret < 0) | |
670 | ✗ | return ret; | |
671 | } | ||
672 |
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 5202 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5202 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.
|
5202 | MATCH_PER_STREAM_OPT(inter_matrices, str, inter_matrix, oc, st); |
673 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5202 times.
|
5202 | if (inter_matrix) { |
674 | ✗ | if (!(video_enc->inter_matrix = av_mallocz(sizeof(*video_enc->inter_matrix) * 64))) | |
675 | ✗ | return AVERROR(ENOMEM); | |
676 | ✗ | ret = parse_matrix_coeffs(ost, video_enc->inter_matrix, inter_matrix); | |
677 | ✗ | if (ret < 0) | |
678 | ✗ | return ret; | |
679 | } | ||
680 | |||
681 |
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 5202 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5202 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.
|
5202 | MATCH_PER_STREAM_OPT(rc_overrides, str, p, oc, st); |
682 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5202 times.
|
5202 | for (i = 0; p; i++) { |
683 | int start, end, q; | ||
684 | ✗ | int e = sscanf(p, "%d,%d,%d", &start, &end, &q); | |
685 | ✗ | if (e != 3) { | |
686 | ✗ | av_log(ost, AV_LOG_FATAL, "error parsing rc_override\n"); | |
687 | ✗ | return AVERROR(EINVAL); | |
688 | } | ||
689 | ✗ | video_enc->rc_override = | |
690 | ✗ | av_realloc_array(video_enc->rc_override, | |
691 | ✗ | i + 1, sizeof(RcOverride)); | |
692 | ✗ | if (!video_enc->rc_override) { | |
693 | ✗ | av_log(ost, AV_LOG_FATAL, "Could not (re)allocate memory for rc_override.\n"); | |
694 | ✗ | return AVERROR(ENOMEM); | |
695 | } | ||
696 | ✗ | video_enc->rc_override[i].start_frame = start; | |
697 | ✗ | video_enc->rc_override[i].end_frame = end; | |
698 | ✗ | if (q > 0) { | |
699 | ✗ | video_enc->rc_override[i].qscale = q; | |
700 | ✗ | video_enc->rc_override[i].quality_factor = 1.0; | |
701 | } | ||
702 | else { | ||
703 | ✗ | video_enc->rc_override[i].qscale = 0; | |
704 | ✗ | video_enc->rc_override[i].quality_factor = -q/100.0; | |
705 | } | ||
706 | ✗ | p = strchr(p, '/'); | |
707 | ✗ | if (p) p++; | |
708 | } | ||
709 | 5202 | video_enc->rc_override_count = i; | |
710 | |||
711 | /* two pass mode */ | ||
712 |
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 5202 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5202 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.
|
5210 | MATCH_PER_STREAM_OPT(pass, i, do_pass, oc, st); |
713 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 5194 times.
|
5202 | if (do_pass) { |
714 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
|
8 | if (do_pass & 1) |
715 | 4 | video_enc->flags |= AV_CODEC_FLAG_PASS1; | |
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 | } | ||
719 | |||
720 |
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 5202 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5202 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.
|
5210 | MATCH_PER_STREAM_OPT(passlogfiles, str, ost->logfile_prefix, oc, st); |
721 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 5194 times.
|
5202 | if (ost->logfile_prefix && |
722 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
|
8 | !(ost->logfile_prefix = av_strdup(ost->logfile_prefix))) |
723 | ✗ | return AVERROR(ENOMEM); | |
724 | |||
725 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 5194 times.
|
5202 | if (do_pass) { |
726 | 8 | int ost_idx = -1; | |
727 | char logfilename[1024]; | ||
728 | FILE *f; | ||
729 | |||
730 | /* compute this stream's global index */ | ||
731 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
|
16 | for (int i = 0; i <= ost->file->index; i++) |
732 | 8 | ost_idx += output_files[i]->nb_streams; | |
733 | |||
734 | 8 | snprintf(logfilename, sizeof(logfilename), "%s-%d.log", | |
735 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | ost->logfile_prefix ? ost->logfile_prefix : |
736 | DEFAULT_PASS_LOGFILENAME_PREFIX, | ||
737 | ost_idx); | ||
738 |
2/4✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
|
8 | if (!strcmp(ost->enc_ctx->codec->name, "libx264") || !strcmp(ost->enc_ctx->codec->name, "libvvenc")) { |
739 | ✗ | if (av_opt_is_set_to_default_by_name(ost->enc_ctx, "stats", | |
740 | AV_OPT_SEARCH_CHILDREN) > 0) | ||
741 | ✗ | av_opt_set(ost->enc_ctx, "stats", logfilename, | |
742 | AV_OPT_SEARCH_CHILDREN); | ||
743 | } else { | ||
744 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
|
8 | if (video_enc->flags & AV_CODEC_FLAG_PASS2) { |
745 | 4 | char *logbuffer = file_read(logfilename); | |
746 | |||
747 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (!logbuffer) { |
748 | ✗ | av_log(ost, AV_LOG_FATAL, "Error reading log file '%s' for pass-2 encoding\n", | |
749 | logfilename); | ||
750 | ✗ | return AVERROR(EIO); | |
751 | } | ||
752 | 4 | video_enc->stats_in = logbuffer; | |
753 | } | ||
754 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
|
8 | if (video_enc->flags & AV_CODEC_FLAG_PASS1) { |
755 | 4 | f = fopen_utf8(logfilename, "wb"); | |
756 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (!f) { |
757 | ✗ | av_log(ost, AV_LOG_FATAL, | |
758 | "Cannot write log file '%s' for pass-1 encoding: %s\n", | ||
759 | ✗ | logfilename, strerror(errno)); | |
760 | ✗ | return AVERROR(errno); | |
761 | } | ||
762 | 4 | ost->logfile = f; | |
763 | } | ||
764 | } | ||
765 | } | ||
766 | |||
767 |
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 5202 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5202 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.
|
5203 | MATCH_PER_STREAM_OPT(force_fps, i, ost->force_fps, oc, st); |
768 | |||
769 | #if FFMPEG_OPT_TOP | ||
770 | 5202 | ost->top_field_first = -1; | |
771 |
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 5202 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5202 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.
|
5202 | MATCH_PER_STREAM_OPT(top_field_first, i, ost->top_field_first, oc, st); |
772 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5202 times.
|
5202 | if (ost->top_field_first >= 0) |
773 | ✗ | av_log(ost, AV_LOG_WARNING, "-top is deprecated, use the setfield filter instead\n"); | |
774 | #endif | ||
775 | |||
776 | #if FFMPEG_OPT_VSYNC | ||
777 | 5202 | *vsync_method = video_sync_method; | |
778 | #else | ||
779 | *vsync_method = VSYNC_AUTO; | ||
780 | #endif | ||
781 |
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 5202 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5202 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.
|
5716 | MATCH_PER_STREAM_OPT(fps_mode, str, fps_mode, oc, st); |
782 |
2/2✓ Branch 0 taken 514 times.
✓ Branch 1 taken 4688 times.
|
5202 | if (fps_mode) { |
783 | 514 | ret = parse_and_set_vsync(fps_mode, vsync_method, ost->file->index, ost->index, 0); | |
784 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 514 times.
|
514 | if (ret < 0) |
785 | ✗ | return ret; | |
786 | } | ||
787 | |||
788 |
3/4✓ Branch 0 taken 5181 times.
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5181 times.
|
5202 | if ((ost->frame_rate.num || ost->max_frame_rate.num) && |
789 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 20 times.
|
21 | !(*vsync_method == VSYNC_AUTO || |
790 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
1 | *vsync_method == VSYNC_CFR || *vsync_method == VSYNC_VSCFR)) { |
791 | ✗ | av_log(ost, AV_LOG_FATAL, "One of -r/-fpsmax was specified " | |
792 | "together a non-CFR -vsync/-fps_mode. This is contradictory.\n"); | ||
793 | ✗ | return AVERROR(EINVAL); | |
794 | } | ||
795 | |||
796 |
2/2✓ Branch 0 taken 4688 times.
✓ Branch 1 taken 514 times.
|
5202 | if (*vsync_method == VSYNC_AUTO) { |
797 |
3/4✓ Branch 0 taken 4668 times.
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4668 times.
|
4688 | if (ost->frame_rate.num || ost->max_frame_rate.num) { |
798 | 20 | *vsync_method = VSYNC_CFR; | |
799 |
2/2✓ Branch 0 taken 284 times.
✓ Branch 1 taken 4384 times.
|
4668 | } else if (!strcmp(oc->oformat->name, "avi")) { |
800 | 284 | *vsync_method = VSYNC_VFR; | |
801 | } else { | ||
802 | 4384 | *vsync_method = (oc->oformat->flags & AVFMT_VARIABLE_FPS) ? | |
803 | 4035 | ((oc->oformat->flags & AVFMT_NOTIMESTAMPS) ? | |
804 |
4/4✓ Branch 0 taken 4035 times.
✓ Branch 1 taken 349 times.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 4022 times.
|
4384 | VSYNC_PASSTHROUGH : VSYNC_VFR) : VSYNC_CFR; |
805 | } | ||
806 | |||
807 |
4/4✓ Branch 0 taken 4599 times.
✓ Branch 1 taken 89 times.
✓ Branch 2 taken 369 times.
✓ Branch 3 taken 4230 times.
|
4688 | if (ost->ist && *vsync_method == VSYNC_CFR) { |
808 | 369 | const InputFile *ifile = ost->ist->file; | |
809 | |||
810 |
3/4✓ Branch 0 taken 324 times.
✓ Branch 1 taken 45 times.
✓ Branch 2 taken 324 times.
✗ Branch 3 not taken.
|
369 | if (ifile->nb_streams == 1 && ifile->input_ts_offset == 0) |
811 | 324 | *vsync_method = VSYNC_VSCFR; | |
812 | } | ||
813 | |||
814 |
3/4✓ Branch 0 taken 45 times.
✓ Branch 1 taken 4643 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 45 times.
|
4688 | if (*vsync_method == VSYNC_CFR && copy_ts) { |
815 | ✗ | *vsync_method = VSYNC_VSCFR; | |
816 | } | ||
817 | } | ||
818 | #if FFMPEG_OPT_VSYNC_DROP | ||
819 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5202 times.
|
5202 | if (*vsync_method == VSYNC_DROP) |
820 | ✗ | ms->ts_drop = 1; | |
821 | #endif | ||
822 | } | ||
823 | |||
824 | 5539 | return 0; | |
825 | } | ||
826 | |||
827 | 1512 | static int new_stream_audio(Muxer *mux, const OptionsContext *o, | |
828 | OutputStream *ost) | ||
829 | { | ||
830 | 1512 | MuxStream *ms = ms_from_ost(ost); | |
831 | 1512 | AVFormatContext *oc = mux->fc; | |
832 | 1512 | AVStream *st = ost->st; | |
833 | |||
834 |
2/2✓ Branch 0 taken 1247 times.
✓ Branch 1 taken 265 times.
|
1512 | if (ost->enc_ctx) { |
835 | 1247 | AVCodecContext *audio_enc = ost->enc_ctx; | |
836 | 1247 | int channels = 0; | |
837 | 1247 | char *layout = NULL; | |
838 | 1247 | char *sample_fmt = NULL; | |
839 | |||
840 |
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 1247 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1247 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.
|
1257 | MATCH_PER_STREAM_OPT(audio_channels, i, channels, oc, st); |
841 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1237 times.
|
1247 | if (channels) { |
842 | 10 | audio_enc->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; | |
843 | 10 | audio_enc->ch_layout.nb_channels = channels; | |
844 | } | ||
845 | |||
846 |
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 1247 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1247 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.
|
1248 | MATCH_PER_STREAM_OPT(audio_ch_layouts, str, layout, oc, st); |
847 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1246 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
|
1247 | if (layout && av_channel_layout_from_string(&audio_enc->ch_layout, layout) < 0) { |
848 | ✗ | av_log(ost, AV_LOG_FATAL, "Unknown channel layout: %s\n", layout); | |
849 | ✗ | return AVERROR(EINVAL); | |
850 | } | ||
851 | |||
852 |
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 1247 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1247 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.
|
1247 | MATCH_PER_STREAM_OPT(sample_fmts, str, sample_fmt, oc, st); |
853 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1247 times.
|
1247 | if (sample_fmt && |
854 | ✗ | (audio_enc->sample_fmt = av_get_sample_fmt(sample_fmt)) == AV_SAMPLE_FMT_NONE) { | |
855 | ✗ | av_log(ost, AV_LOG_FATAL, "Invalid sample format '%s'\n", sample_fmt); | |
856 | ✗ | return AVERROR(EINVAL); | |
857 | } | ||
858 | |||
859 |
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 1247 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1247 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.
|
1261 | MATCH_PER_STREAM_OPT(audio_sample_rate, i, audio_enc->sample_rate, oc, st); |
860 | |||
861 |
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 1247 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1247 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.
|
1247 | MATCH_PER_STREAM_OPT(apad, str, ms->apad, oc, st); |
862 | } | ||
863 | |||
864 | 1512 | return 0; | |
865 | } | ||
866 | |||
867 | 71 | static int new_stream_subtitle(Muxer *mux, const OptionsContext *o, | |
868 | OutputStream *ost) | ||
869 | { | ||
870 | AVStream *st; | ||
871 | |||
872 | 71 | st = ost->st; | |
873 | |||
874 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 33 times.
|
71 | if (ost->enc_ctx) { |
875 | 38 | AVCodecContext *subtitle_enc = ost->enc_ctx; | |
876 | |||
877 | AVCodecDescriptor const *input_descriptor = | ||
878 | 38 | avcodec_descriptor_get(ost->ist->par->codec_id); | |
879 | AVCodecDescriptor const *output_descriptor = | ||
880 | 38 | avcodec_descriptor_get(subtitle_enc->codec_id); | |
881 | 38 | int input_props = 0, output_props = 0; | |
882 | |||
883 | 38 | char *frame_size = NULL; | |
884 | |||
885 |
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); |
886 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
|
38 | if (frame_size) { |
887 | ✗ | int ret = av_parse_video_size(&subtitle_enc->width, &subtitle_enc->height, frame_size); | |
888 | ✗ | if (ret < 0) { | |
889 | ✗ | av_log(ost, AV_LOG_FATAL, "Invalid frame size: %s.\n", frame_size); | |
890 | ✗ | return ret; | |
891 | } | ||
892 | } | ||
893 |
1/2✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
|
38 | if (input_descriptor) |
894 | 38 | input_props = input_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB); | |
895 |
1/2✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
|
38 | if (output_descriptor) |
896 | 38 | output_props = output_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB); | |
897 |
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) { |
898 | ✗ | av_log(ost, AV_LOG_ERROR, | |
899 | "Subtitle encoding currently only possible from text to text " | ||
900 | "or bitmap to bitmap\n"); | ||
901 | ✗ | return AVERROR(EINVAL); | |
902 | } | ||
903 | } | ||
904 | |||
905 | 71 | return 0; | |
906 | } | ||
907 | |||
908 | 645 | static int streamcopy_init(const Muxer *mux, OutputStream *ost, AVDictionary **encoder_opts) | |
909 | { | ||
910 | 645 | MuxStream *ms = ms_from_ost(ost); | |
911 | |||
912 | 645 | const InputStream *ist = ost->ist; | |
913 | 645 | const InputFile *ifile = ist->file; | |
914 | |||
915 | 645 | AVCodecParameters *par = ost->par_in; | |
916 | 645 | uint32_t codec_tag = par->codec_tag; | |
917 | |||
918 | 645 | AVCodecContext *codec_ctx = NULL; | |
919 | 645 | AVDictionary *codec_opts = NULL; | |
920 | |||
921 | 645 | AVRational fr = ost->frame_rate; | |
922 | |||
923 | 645 | int ret = 0; | |
924 | |||
925 | 645 | codec_ctx = avcodec_alloc_context3(NULL); | |
926 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 645 times.
|
645 | if (!codec_ctx) |
927 | ✗ | return AVERROR(ENOMEM); | |
928 | |||
929 | 645 | ret = avcodec_parameters_to_context(codec_ctx, ist->par); | |
930 |
1/2✓ Branch 0 taken 645 times.
✗ Branch 1 not taken.
|
645 | if (ret >= 0) |
931 | 645 | ret = av_opt_set_dict(codec_ctx, encoder_opts); | |
932 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 645 times.
|
645 | if (ret < 0) { |
933 | ✗ | av_log(ost, AV_LOG_FATAL, | |
934 | "Error setting up codec context options.\n"); | ||
935 | ✗ | goto fail; | |
936 | } | ||
937 | |||
938 | 645 | ret = avcodec_parameters_from_context(par, codec_ctx); | |
939 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 645 times.
|
645 | if (ret < 0) { |
940 | ✗ | av_log(ost, AV_LOG_FATAL, | |
941 | "Error getting reference codec parameters.\n"); | ||
942 | ✗ | goto fail; | |
943 | } | ||
944 | |||
945 |
2/2✓ Branch 0 taken 639 times.
✓ Branch 1 taken 6 times.
|
645 | if (!codec_tag) { |
946 | 639 | const struct AVCodecTag * const *ct = mux->fc->oformat->codec_tag; | |
947 | unsigned int codec_tag_tmp; | ||
948 |
6/6✓ Branch 0 taken 119 times.
✓ Branch 1 taken 520 times.
✓ Branch 3 taken 86 times.
✓ Branch 4 taken 33 times.
✓ Branch 5 taken 11 times.
✓ Branch 6 taken 75 times.
|
725 | if (!ct || av_codec_get_id (ct, par->codec_tag) == par->codec_id || |
949 | 86 | !av_codec_get_tag2(ct, par->codec_id, &codec_tag_tmp)) | |
950 | 564 | codec_tag = par->codec_tag; | |
951 | } | ||
952 | |||
953 | 645 | par->codec_tag = codec_tag; | |
954 | |||
955 |
2/2✓ Branch 0 taken 644 times.
✓ Branch 1 taken 1 times.
|
645 | if (!fr.num) |
956 | 644 | fr = ist->framerate; | |
957 | |||
958 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 643 times.
|
645 | if (fr.num) |
959 | 2 | ost->st->avg_frame_rate = fr; | |
960 | else | ||
961 | 643 | ost->st->avg_frame_rate = ist->st->avg_frame_rate; | |
962 | |||
963 | // copy timebase while removing common factors | ||
964 |
3/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 643 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
|
645 | if (ost->st->time_base.num <= 0 || ost->st->time_base.den <= 0) { |
965 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 642 times.
|
643 | if (fr.num) |
966 | 1 | ost->st->time_base = av_inv_q(fr); | |
967 | else | ||
968 | 642 | ost->st->time_base = av_add_q(ist->st->time_base, (AVRational){0, 1}); | |
969 | } | ||
970 | |||
971 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 645 times.
|
645 | if (!ms->copy_prior_start) { |
972 | ✗ | ms->ts_copy_start = (mux->of.start_time == AV_NOPTS_VALUE) ? | |
973 | ✗ | 0 : mux->of.start_time; | |
974 | ✗ | if (copy_ts && ifile->start_time != AV_NOPTS_VALUE) { | |
975 | ✗ | ms->ts_copy_start = FFMAX(ms->ts_copy_start, | |
976 | ifile->start_time + ifile->ts_offset); | ||
977 | } | ||
978 | } | ||
979 | |||
980 |
2/2✓ Branch 0 taken 75 times.
✓ Branch 1 taken 645 times.
|
720 | for (int i = 0; i < ist->st->codecpar->nb_coded_side_data; i++) { |
981 | 75 | const AVPacketSideData *sd_src = &ist->st->codecpar->coded_side_data[i]; | |
982 | AVPacketSideData *sd_dst; | ||
983 | |||
984 | 75 | sd_dst = av_packet_side_data_new(&ost->st->codecpar->coded_side_data, | |
985 | 75 | &ost->st->codecpar->nb_coded_side_data, | |
986 | 75 | sd_src->type, sd_src->size, 0); | |
987 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
|
75 | if (!sd_dst) { |
988 | ✗ | ret = AVERROR(ENOMEM); | |
989 | ✗ | goto fail; | |
990 | } | ||
991 | 75 | memcpy(sd_dst->data, sd_src->data, sd_src->size); | |
992 | } | ||
993 | |||
994 |
3/3✓ Branch 0 taken 265 times.
✓ Branch 1 taken 337 times.
✓ Branch 2 taken 43 times.
|
645 | switch (par->codec_type) { |
995 | 265 | case AVMEDIA_TYPE_AUDIO: | |
996 |
4/6✓ Branch 0 taken 260 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 260 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 260 times.
|
265 | if ((par->block_align == 1 || par->block_align == 1152 || par->block_align == 576) && |
997 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | par->codec_id == AV_CODEC_ID_MP3) |
998 | ✗ | par->block_align = 0; | |
999 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 252 times.
|
265 | if (par->codec_id == AV_CODEC_ID_AC3) |
1000 | 13 | par->block_align = 0; | |
1001 | 265 | break; | |
1002 | 337 | case AVMEDIA_TYPE_VIDEO: { | |
1003 | AVRational sar; | ||
1004 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 337 times.
|
337 | if (ost->frame_aspect_ratio.num) { // overridden by the -aspect cli option |
1005 | sar = | ||
1006 | ✗ | av_mul_q(ost->frame_aspect_ratio, | |
1007 | ✗ | (AVRational){ par->height, par->width }); | |
1008 | ✗ | av_log(ost, AV_LOG_WARNING, "Overriding aspect ratio " | |
1009 | "with stream copy may produce invalid files\n"); | ||
1010 | } | ||
1011 |
2/2✓ Branch 0 taken 90 times.
✓ Branch 1 taken 247 times.
|
337 | else if (ist->st->sample_aspect_ratio.num) |
1012 | 90 | sar = ist->st->sample_aspect_ratio; | |
1013 | else | ||
1014 | 247 | sar = par->sample_aspect_ratio; | |
1015 | 337 | ost->st->sample_aspect_ratio = par->sample_aspect_ratio = sar; | |
1016 | 337 | ost->st->avg_frame_rate = ist->st->avg_frame_rate; | |
1017 | 337 | ost->st->r_frame_rate = ist->st->r_frame_rate; | |
1018 | 337 | break; | |
1019 | } | ||
1020 | } | ||
1021 | |||
1022 | 645 | fail: | |
1023 | 645 | avcodec_free_context(&codec_ctx); | |
1024 | 645 | av_dict_free(&codec_opts); | |
1025 | 645 | return ret; | |
1026 | } | ||
1027 | |||
1028 | 7133 | static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type, | |
1029 | InputStream *ist, OutputFilter *ofilter, | ||
1030 | OutputStream **post) | ||
1031 | { | ||
1032 | 7133 | AVFormatContext *oc = mux->fc; | |
1033 | MuxStream *ms; | ||
1034 | OutputStream *ost; | ||
1035 | const AVCodec *enc; | ||
1036 | AVStream *st; | ||
1037 | 7133 | AVDictionary *encoder_opts = NULL; | |
1038 | 7133 | int ret = 0, keep_pix_fmt = 0, autoscale = 1; | |
1039 | 7133 | int threads_manual = 0; | |
1040 | 7133 | AVRational enc_tb = { 0, 0 }; | |
1041 | 7133 | enum VideoSyncMethod vsync_method = VSYNC_AUTO; | |
1042 | 7133 | const char *bsfs = NULL, *time_base = NULL; | |
1043 | 7133 | char *filters = NULL, *next, *codec_tag = NULL; | |
1044 | 7133 | double qscale = -1; | |
1045 | |||
1046 | 7133 | st = avformat_new_stream(oc, NULL); | |
1047 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7133 times.
|
7133 | if (!st) |
1048 | ✗ | return AVERROR(ENOMEM); | |
1049 | |||
1050 | 7133 | ms = mux_stream_alloc(mux, type); | |
1051 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7133 times.
|
7133 | if (!ms) |
1052 | ✗ | return AVERROR(ENOMEM); | |
1053 | |||
1054 | // only streams with sources (i.e. not attachments) | ||
1055 | // are handled by the scheduler | ||
1056 |
4/4✓ Branch 0 taken 169 times.
✓ Branch 1 taken 6964 times.
✓ Branch 2 taken 168 times.
✓ Branch 3 taken 1 times.
|
7133 | if (ist || ofilter) { |
1057 | 7132 | ret = GROW_ARRAY(mux->sch_stream_idx, mux->nb_sch_stream_idx); | |
1058 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7132 times.
|
7132 | if (ret < 0) |
1059 | ✗ | return ret; | |
1060 | |||
1061 | 7132 | ret = sch_add_mux_stream(mux->sch, mux->sch_idx); | |
1062 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7132 times.
|
7132 | if (ret < 0) |
1063 | ✗ | return ret; | |
1064 | |||
1065 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7132 times.
|
7132 | av_assert0(ret == mux->nb_sch_stream_idx - 1); |
1066 | 7132 | mux->sch_stream_idx[ret] = ms->ost.index; | |
1067 | 7132 | ms->sch_idx = ret; | |
1068 | } | ||
1069 | |||
1070 | 7133 | ost = &ms->ost; | |
1071 | |||
1072 |
2/2✓ Branch 0 taken 40 times.
✓ Branch 1 taken 7093 times.
|
7133 | if (o->streamid) { |
1073 | AVDictionaryEntry *e; | ||
1074 | char idx[16], *p; | ||
1075 | 40 | snprintf(idx, sizeof(idx), "%d", ost->index); | |
1076 | |||
1077 | 40 | e = av_dict_get(o->streamid, idx, NULL, 0); | |
1078 |
1/2✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
|
40 | if (e) { |
1079 | 40 | st->id = strtol(e->value, &p, 0); | |
1080 |
2/4✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 40 times.
|
40 | if (!e->value[0] || *p) { |
1081 | ✗ | av_log(ost, AV_LOG_FATAL, "Invalid stream id: %s\n", e->value); | |
1082 | ✗ | return AVERROR(EINVAL); | |
1083 | } | ||
1084 | } | ||
1085 | } | ||
1086 | |||
1087 | 7133 | ost->par_in = avcodec_parameters_alloc(); | |
1088 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7133 times.
|
7133 | if (!ost->par_in) |
1089 | ✗ | return AVERROR(ENOMEM); | |
1090 | |||
1091 | 7133 | ms->last_mux_dts = AV_NOPTS_VALUE; | |
1092 | |||
1093 | 7133 | ost->st = st; | |
1094 | 7133 | ost->ist = ist; | |
1095 | 7133 | ost->kf.ref_pts = AV_NOPTS_VALUE; | |
1096 | 7133 | ost->par_in->codec_type = type; | |
1097 | 7133 | st->codecpar->codec_type = type; | |
1098 | |||
1099 | 7133 | ret = choose_encoder(o, oc, ost, &enc); | |
1100 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7133 times.
|
7133 | if (ret < 0) { |
1101 | ✗ | av_log(ost, AV_LOG_FATAL, "Error selecting an encoder\n"); | |
1102 | ✗ | return ret; | |
1103 | } | ||
1104 | |||
1105 |
2/2✓ Branch 0 taken 6487 times.
✓ Branch 1 taken 646 times.
|
7133 | if (enc) { |
1106 | 6487 | ost->enc_ctx = avcodec_alloc_context3(enc); | |
1107 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6487 times.
|
6487 | if (!ost->enc_ctx) |
1108 | ✗ | return AVERROR(ENOMEM); | |
1109 | |||
1110 | 6487 | ret = sch_add_enc(mux->sch, encoder_thread, ost, | |
1111 |
2/2✓ Branch 0 taken 6449 times.
✓ Branch 1 taken 38 times.
|
6487 | ost->type == AVMEDIA_TYPE_SUBTITLE ? NULL : enc_open); |
1112 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6487 times.
|
6487 | if (ret < 0) |
1113 | ✗ | return ret; | |
1114 | 6487 | ms->sch_idx_enc = ret; | |
1115 | |||
1116 | 6487 | ret = enc_alloc(&ost->enc, enc, mux->sch, ms->sch_idx_enc); | |
1117 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6487 times.
|
6487 | if (ret < 0) |
1118 | ✗ | return ret; | |
1119 | |||
1120 | 6487 | av_strlcat(ms->log_name, "/", sizeof(ms->log_name)); | |
1121 | 6487 | av_strlcat(ms->log_name, enc->name, sizeof(ms->log_name)); | |
1122 | } else { | ||
1123 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 646 times.
|
646 | if (ofilter) { |
1124 | ✗ | av_log(ost, AV_LOG_ERROR, | |
1125 | "Streamcopy requested for output stream fed " | ||
1126 | "from a complex filtergraph. Filtering and streamcopy " | ||
1127 | "cannot be used together.\n"); | ||
1128 | ✗ | return AVERROR(EINVAL); | |
1129 | } | ||
1130 | |||
1131 | 646 | av_strlcat(ms->log_name, "/copy", sizeof(ms->log_name)); | |
1132 | } | ||
1133 | |||
1134 | 7133 | av_log(ost, AV_LOG_VERBOSE, "Created %s stream from ", | |
1135 | av_get_media_type_string(type)); | ||
1136 |
2/2✓ Branch 0 taken 6964 times.
✓ Branch 1 taken 169 times.
|
7133 | if (ist) |
1137 | 6964 | av_log(ost, AV_LOG_VERBOSE, "input stream %d:%d", | |
1138 | 6964 | ist->file->index, ist->index); | |
1139 |
2/2✓ Branch 0 taken 168 times.
✓ Branch 1 taken 1 times.
|
169 | else if (ofilter) |
1140 | 168 | av_log(ost, AV_LOG_VERBOSE, "complex filtergraph %d:[%s]\n", | |
1141 | 168 | ofilter->graph->index, ofilter->name); | |
1142 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | else if (type == AVMEDIA_TYPE_ATTACHMENT) |
1143 | 1 | av_log(ost, AV_LOG_VERBOSE, "attached file"); | |
1144 | ✗ | else av_assert0(0); | |
1145 | 7133 | av_log(ost, AV_LOG_VERBOSE, "\n"); | |
1146 | |||
1147 | 7133 | ms->pkt = av_packet_alloc(); | |
1148 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7133 times.
|
7133 | if (!ms->pkt) |
1149 | ✗ | return AVERROR(ENOMEM); | |
1150 | |||
1151 |
2/2✓ Branch 0 taken 6487 times.
✓ Branch 1 taken 646 times.
|
7133 | if (ost->enc_ctx) { |
1152 | 6487 | AVCodecContext *enc = ost->enc_ctx; | |
1153 | 6487 | AVIOContext *s = NULL; | |
1154 | 6487 | char *buf = NULL, *arg = NULL, *preset = NULL; | |
1155 | 6487 | const char *enc_stats_pre = NULL, *enc_stats_post = NULL, *mux_stats = NULL; | |
1156 | 6487 | const char *enc_time_base = NULL; | |
1157 | |||
1158 | 6487 | ret = filter_codec_opts(o->g->codec_opts, enc->codec_id, | |
1159 | 6487 | oc, st, enc->codec, &encoder_opts, | |
1160 | &mux->enc_opts_used); | ||
1161 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6487 times.
|
6487 | if (ret < 0) |
1162 | ✗ | goto fail; | |
1163 | |||
1164 |
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 6487 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6487 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.
|
6487 | MATCH_PER_STREAM_OPT(presets, str, preset, oc, st); |
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 6487 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6487 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.
|
6487 | MATCH_PER_STREAM_OPT(autoscale, i, autoscale, oc, st); |
1167 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 6487 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
6487 | if (preset && (!(ret = get_preset_file_2(preset, enc->codec->name, &s)))) { |
1168 | AVBPrint bprint; | ||
1169 | ✗ | av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED); | |
1170 | do { | ||
1171 | ✗ | av_bprint_clear(&bprint); | |
1172 | ✗ | buf = get_line(s, &bprint); | |
1173 | ✗ | if (!buf) { | |
1174 | ✗ | ret = AVERROR(ENOMEM); | |
1175 | ✗ | break; | |
1176 | } | ||
1177 | |||
1178 | ✗ | if (!buf[0] || buf[0] == '#') | |
1179 | ✗ | continue; | |
1180 | ✗ | if (!(arg = strchr(buf, '='))) { | |
1181 | ✗ | av_log(ost, AV_LOG_FATAL, "Invalid line found in the preset file.\n"); | |
1182 | ✗ | ret = AVERROR(EINVAL); | |
1183 | ✗ | break; | |
1184 | } | ||
1185 | ✗ | *arg++ = 0; | |
1186 | ✗ | av_dict_set(&encoder_opts, buf, arg, AV_DICT_DONT_OVERWRITE); | |
1187 | ✗ | } while (!s->eof_reached); | |
1188 | ✗ | av_bprint_finalize(&bprint, NULL); | |
1189 | ✗ | avio_closep(&s); | |
1190 | } | ||
1191 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6487 times.
|
6487 | if (ret) { |
1192 | ✗ | av_log(ost, AV_LOG_FATAL, | |
1193 | "Preset %s specified, but could not be opened.\n", preset); | ||
1194 | ✗ | goto fail; | |
1195 | } | ||
1196 | |||
1197 |
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 6487 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6487 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.
|
6487 | MATCH_PER_STREAM_OPT(enc_stats_pre, str, enc_stats_pre, oc, st); |
1198 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 6487 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
6487 | if (enc_stats_pre && |
1199 | ✗ | (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) { | |
1200 | ✗ | const char *format = "{fidx} {sidx} {n} {t}"; | |
1201 | |||
1202 | ✗ | MATCH_PER_STREAM_OPT(enc_stats_pre_fmt, str, format, oc, st); | |
1203 | |||
1204 | ✗ | ret = enc_stats_init(ost, &ost->enc_stats_pre, 1, enc_stats_pre, format); | |
1205 | ✗ | if (ret < 0) | |
1206 | ✗ | goto fail; | |
1207 | } | ||
1208 | |||
1209 |
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 6487 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6487 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.
|
6487 | MATCH_PER_STREAM_OPT(enc_stats_post, str, enc_stats_post, oc, st); |
1210 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 6487 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
6487 | if (enc_stats_post && |
1211 | ✗ | (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) { | |
1212 | ✗ | const char *format = "{fidx} {sidx} {n} {t}"; | |
1213 | |||
1214 | ✗ | MATCH_PER_STREAM_OPT(enc_stats_post_fmt, str, format, oc, st); | |
1215 | |||
1216 | ✗ | ret = enc_stats_init(ost, &ost->enc_stats_post, 0, enc_stats_post, format); | |
1217 | ✗ | if (ret < 0) | |
1218 | ✗ | goto fail; | |
1219 | } | ||
1220 | |||
1221 |
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 6487 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6487 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.
|
6487 | MATCH_PER_STREAM_OPT(mux_stats, str, mux_stats, oc, st); |
1222 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 6487 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
6487 | if (mux_stats && |
1223 | ✗ | (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) { | |
1224 | ✗ | const char *format = "{fidx} {sidx} {n} {t}"; | |
1225 | |||
1226 | ✗ | MATCH_PER_STREAM_OPT(mux_stats_fmt, str, format, oc, st); | |
1227 | |||
1228 | ✗ | ret = enc_stats_init(ost, &ms->stats, 0, mux_stats, format); | |
1229 | ✗ | if (ret < 0) | |
1230 | ✗ | goto fail; | |
1231 | } | ||
1232 | |||
1233 |
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 6487 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6487 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.
|
6488 | MATCH_PER_STREAM_OPT(enc_time_bases, str, enc_time_base, oc, st); |
1234 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6486 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
6487 | if (enc_time_base && type == AVMEDIA_TYPE_SUBTITLE) |
1235 | ✗ | av_log(ost, AV_LOG_WARNING, | |
1236 | "-enc_time_base not supported for subtitles, ignoring\n"); | ||
1237 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6486 times.
|
6487 | else if (enc_time_base) { |
1238 | AVRational q; | ||
1239 | |||
1240 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (!strcmp(enc_time_base, "demux")) { |
1241 | 1 | q = (AVRational){ ENC_TIME_BASE_DEMUX, 0 }; | |
1242 | ✗ | } else if (!strcmp(enc_time_base, "filter")) { | |
1243 | ✗ | q = (AVRational){ ENC_TIME_BASE_FILTER, 0 }; | |
1244 | } else { | ||
1245 | ✗ | ret = av_parse_ratio(&q, enc_time_base, INT_MAX, 0, NULL); | |
1246 | ✗ | if (ret < 0 || q.den <= 0 | |
1247 | #if !FFMPEG_OPT_ENC_TIME_BASE_NUM | ||
1248 | || q.num < 0 | ||
1249 | #endif | ||
1250 | ) { | ||
1251 | ✗ | av_log(ost, AV_LOG_FATAL, "Invalid time base: %s\n", enc_time_base); | |
1252 | ✗ | ret = ret < 0 ? ret : AVERROR(EINVAL); | |
1253 | ✗ | goto fail; | |
1254 | } | ||
1255 | #if FFMPEG_OPT_ENC_TIME_BASE_NUM | ||
1256 | ✗ | if (q.num < 0) | |
1257 | ✗ | av_log(ost, AV_LOG_WARNING, "-enc_time_base -1 is deprecated," | |
1258 | " use -enc_timebase demux\n"); | ||
1259 | #endif | ||
1260 | } | ||
1261 | |||
1262 | 1 | enc_tb = q; | |
1263 | } | ||
1264 | |||
1265 | 6487 | threads_manual = !!av_dict_get(encoder_opts, "threads", NULL, 0); | |
1266 | |||
1267 | 6487 | ret = av_opt_set_dict2(ost->enc_ctx, &encoder_opts, AV_OPT_SEARCH_CHILDREN); | |
1268 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6487 times.
|
6487 | if (ret < 0) { |
1269 | ✗ | av_log(ost, AV_LOG_ERROR, "Error applying encoder options: %s\n", | |
1270 | ✗ | av_err2str(ret)); | |
1271 | ✗ | goto fail; | |
1272 | } | ||
1273 | |||
1274 | 6487 | ret = check_avoptions(encoder_opts); | |
1275 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6487 times.
|
6487 | if (ret < 0) |
1276 | ✗ | goto fail; | |
1277 | |||
1278 | // default to automatic thread count | ||
1279 |
2/2✓ Branch 0 taken 2651 times.
✓ Branch 1 taken 3836 times.
|
6487 | if (!threads_manual) |
1280 | 2651 | ost->enc_ctx->thread_count = 0; | |
1281 | } else { | ||
1282 | 646 | ret = filter_codec_opts(o->g->codec_opts, AV_CODEC_ID_NONE, oc, st, | |
1283 | NULL, &encoder_opts, | ||
1284 | &mux->enc_opts_used); | ||
1285 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 646 times.
|
646 | if (ret < 0) |
1286 | ✗ | goto fail; | |
1287 | } | ||
1288 | |||
1289 | |||
1290 |
2/2✓ Branch 0 taken 1862 times.
✓ Branch 1 taken 5271 times.
|
7133 | if (o->bitexact) { |
1291 | 1862 | ost->bitexact = 1; | |
1292 |
2/2✓ Branch 0 taken 4733 times.
✓ Branch 1 taken 538 times.
|
5271 | } else if (ost->enc_ctx) { |
1293 | 4733 | ost->bitexact = !!(ost->enc_ctx->flags & AV_CODEC_FLAG_BITEXACT); | |
1294 | } | ||
1295 | |||
1296 |
4/20✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 5 times.
✓ Branch 6 taken 7133 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7133 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.
|
7138 | MATCH_PER_STREAM_OPT(time_bases, str, time_base, oc, st); |
1297 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 7128 times.
|
7133 | if (time_base) { |
1298 | AVRational q; | ||
1299 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | if (av_parse_ratio(&q, time_base, INT_MAX, 0, NULL) < 0 || |
1300 |
2/4✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
|
5 | q.num <= 0 || q.den <= 0) { |
1301 | ✗ | av_log(ost, AV_LOG_FATAL, "Invalid time base: %s\n", time_base); | |
1302 | ✗ | ret = AVERROR(EINVAL); | |
1303 | ✗ | goto fail; | |
1304 | } | ||
1305 | 5 | st->time_base = q; | |
1306 | } | ||
1307 | |||
1308 | 7133 | ms->max_frames = INT64_MAX; | |
1309 |
14/20✓ Branch 1 taken 4819 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 4823 times.
✓ Branch 6 taken 7133 times.
✓ Branch 7 taken 2141 times.
✓ Branch 8 taken 4992 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.
|
18379 | MATCH_PER_STREAM_OPT(max_frames, i64, ms->max_frames, oc, st); |
1310 |
2/2✓ Branch 0 taken 4823 times.
✓ Branch 1 taken 7127 times.
|
11950 | for (int i = 0; i < o->max_frames.nb_opt; i++) { |
1311 | 4823 | char *p = o->max_frames.opt[i].specifier; | |
1312 |
4/4✓ Branch 0 taken 169 times.
✓ Branch 1 taken 4654 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 163 times.
|
4823 | if (!*p && type != AVMEDIA_TYPE_VIDEO) { |
1313 | 6 | av_log(ost, AV_LOG_WARNING, "Applying unspecific -frames to non video streams, maybe you meant -vframes ?\n"); | |
1314 | 6 | break; | |
1315 | } | ||
1316 | } | ||
1317 | |||
1318 | 7133 | ms->copy_prior_start = -1; | |
1319 |
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 7133 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7133 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.
|
7133 | MATCH_PER_STREAM_OPT(copy_prior_start, i, ms->copy_prior_start, oc ,st); |
1320 | |||
1321 |
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 7133 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7133 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.
|
7275 | MATCH_PER_STREAM_OPT(bitstream_filters, str, bsfs, oc, st); |
1322 |
3/4✓ Branch 0 taken 132 times.
✓ Branch 1 taken 7001 times.
✓ Branch 2 taken 132 times.
✗ Branch 3 not taken.
|
7133 | if (bsfs && *bsfs) { |
1323 | 132 | ret = av_bsf_list_parse_str(bsfs, &ms->bsf_ctx); | |
1324 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 132 times.
|
132 | if (ret < 0) { |
1325 | ✗ | av_log(ost, AV_LOG_ERROR, "Error parsing bitstream filter sequence '%s': %s\n", bsfs, av_err2str(ret)); | |
1326 | ✗ | goto fail; | |
1327 | } | ||
1328 | } | ||
1329 | |||
1330 |
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 7133 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7133 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.
|
7140 | MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, oc, st); |
1331 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7126 times.
|
7133 | if (codec_tag) { |
1332 | 7 | uint32_t tag = strtol(codec_tag, &next, 0); | |
1333 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | if (*next) { |
1334 | 7 | uint8_t buf[4] = { 0 }; | |
1335 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | memcpy(buf, codec_tag, FFMIN(sizeof(buf), strlen(codec_tag))); |
1336 | 7 | tag = AV_RL32(buf); | |
1337 | } | ||
1338 | 7 | ost->st->codecpar->codec_tag = tag; | |
1339 | 7 | ost->par_in->codec_tag = tag; | |
1340 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
|
7 | if (ost->enc_ctx) |
1341 | 1 | ost->enc_ctx->codec_tag = tag; | |
1342 | } | ||
1343 | |||
1344 |
14/20✓ Branch 1 taken 267 times.
✓ Branch 2 taken 56 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 56 times.
✓ Branch 5 taken 323 times.
✓ Branch 6 taken 7133 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 7132 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.
|
7457 | MATCH_PER_STREAM_OPT(qscale, dbl, qscale, oc, st); |
1345 |
4/4✓ Branch 0 taken 6487 times.
✓ Branch 1 taken 646 times.
✓ Branch 2 taken 266 times.
✓ Branch 3 taken 6221 times.
|
7133 | if (ost->enc_ctx && qscale >= 0) { |
1346 | 266 | ost->enc_ctx->flags |= AV_CODEC_FLAG_QSCALE; | |
1347 | 266 | ost->enc_ctx->global_quality = FF_QP2LAMBDA * qscale; | |
1348 | } | ||
1349 | |||
1350 |
2/2✓ Branch 0 taken 7132 times.
✓ Branch 1 taken 1 times.
|
7133 | if (ms->sch_idx >= 0) { |
1351 | 7132 | int max_muxing_queue_size = 128; | |
1352 | 7132 | int muxing_queue_data_threshold = 50 * 1024 * 1024; | |
1353 | |||
1354 |
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 7132 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7132 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.
|
7134 | MATCH_PER_STREAM_OPT(max_muxing_queue_size, i, max_muxing_queue_size, oc, st); |
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 7132 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7132 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.
|
7132 | MATCH_PER_STREAM_OPT(muxing_queue_data_threshold, i, muxing_queue_data_threshold, oc, st); |
1356 | |||
1357 | 7132 | sch_mux_stream_buffering(mux->sch, mux->sch_idx, ms->sch_idx, | |
1358 | max_muxing_queue_size, muxing_queue_data_threshold); | ||
1359 | } | ||
1360 | |||
1361 |
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 7133 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7133 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.
|
7134 | MATCH_PER_STREAM_OPT(bits_per_raw_sample, i, ost->bits_per_raw_sample, |
1362 | oc, st); | ||
1363 | |||
1364 |
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 7133 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7133 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.
|
7135 | MATCH_PER_STREAM_OPT(fix_sub_duration_heartbeat, i, ost->fix_sub_duration_heartbeat, |
1365 | oc, st); | ||
1366 | |||
1367 |
4/4✓ Branch 0 taken 2757 times.
✓ Branch 1 taken 4376 times.
✓ Branch 2 taken 2654 times.
✓ Branch 3 taken 103 times.
|
7133 | if (oc->oformat->flags & AVFMT_GLOBALHEADER && ost->enc_ctx) |
1368 | 2654 | ost->enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; | |
1369 | |||
1370 |
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 7133 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7133 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.
|
7133 | MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, |
1371 | ms->copy_initial_nonkeyframes, oc, st); | ||
1372 | |||
1373 |
4/4✓ Branch 0 taken 5539 times.
✓ Branch 1 taken 1512 times.
✓ Branch 2 taken 71 times.
✓ Branch 3 taken 11 times.
|
7133 | switch (type) { |
1374 | 5539 | case AVMEDIA_TYPE_VIDEO: ret = new_stream_video (mux, o, ost, &keep_pix_fmt, &vsync_method); break; | |
1375 | 1512 | case AVMEDIA_TYPE_AUDIO: ret = new_stream_audio (mux, o, ost); break; | |
1376 | 71 | case AVMEDIA_TYPE_SUBTITLE: ret = new_stream_subtitle (mux, o, ost); break; | |
1377 | } | ||
1378 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7133 times.
|
7133 | if (ret < 0) |
1379 | ✗ | goto fail; | |
1380 | |||
1381 |
4/4✓ Branch 0 taken 1594 times.
✓ Branch 1 taken 5539 times.
✓ Branch 2 taken 1512 times.
✓ Branch 3 taken 82 times.
|
7133 | if (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO) { |
1382 | 7051 | ret = ost_get_filters(o, oc, ost, &filters); | |
1383 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7051 times.
|
7051 | if (ret < 0) |
1384 | ✗ | goto fail; | |
1385 | } | ||
1386 | |||
1387 |
4/4✓ Branch 0 taken 6487 times.
✓ Branch 1 taken 646 times.
✓ Branch 2 taken 1285 times.
✓ Branch 3 taken 5202 times.
|
7133 | if (ost->enc && |
1388 |
2/2✓ Branch 0 taken 1247 times.
✓ Branch 1 taken 38 times.
|
7734 | (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) { |
1389 | char name[16]; | ||
1390 | 25796 | OutputFilterOptions opts = { | |
1391 | .enc = enc, | ||
1392 | .name = name, | ||
1393 | .format = (type == AVMEDIA_TYPE_VIDEO) ? | ||
1394 | 6449 | ost->enc_ctx->pix_fmt : ost->enc_ctx->sample_fmt, | |
1395 | 6449 | .width = ost->enc_ctx->width, | |
1396 | 6449 | .height = ost->enc_ctx->height, | |
1397 | .vsync_method = vsync_method, | ||
1398 | 6449 | .sample_rate = ost->enc_ctx->sample_rate, | |
1399 | 6449 | .ch_layout = ost->enc_ctx->ch_layout, | |
1400 | 6449 | .sws_opts = o->g->sws_dict, | |
1401 | 6449 | .swr_opts = o->g->swr_opts, | |
1402 | .output_tb = enc_tb, | ||
1403 | 6449 | .trim_start_us = mux->of.start_time, | |
1404 | 6449 | .trim_duration_us = mux->of.recording_time, | |
1405 | 6449 | .ts_offset = mux->of.start_time == AV_NOPTS_VALUE ? | |
1406 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6448 times.
|
6449 | 0 : mux->of.start_time, |
1407 | 12898 | .flags = OFILTER_FLAG_DISABLE_CONVERT * !!keep_pix_fmt | | |
1408 |
3/4✓ Branch 0 taken 6449 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5202 times.
✓ Branch 3 taken 1247 times.
|
12898 | OFILTER_FLAG_AUTOSCALE * !!autoscale | |
1409 |
2/2✓ Branch 1 taken 59 times.
✓ Branch 2 taken 6390 times.
|
6449 | OFILTER_FLAG_AUDIO_24BIT * !!(av_get_exact_bits_per_sample(ost->enc_ctx->codec_id) == 24), |
1410 | }; | ||
1411 | |||
1412 | 6449 | snprintf(name, sizeof(name), "#%d:%d", mux->of.index, ost->index); | |
1413 | |||
1414 | // MJPEG encoder exports a full list of supported pixel formats, | ||
1415 | // but the full-range ones are experimental-only. | ||
1416 | // Restrict the auto-conversion list unless -strict experimental | ||
1417 | // has been specified. | ||
1418 |
2/2✓ Branch 0 taken 27 times.
✓ Branch 1 taken 6422 times.
|
6449 | if (!strcmp(enc->name, "mjpeg")) { |
1419 | // FIXME: YUV420P etc. are actually supported with full color range, | ||
1420 | // yet the latter information isn't available here. | ||
1421 | static const enum AVPixelFormat mjpeg_formats[] = | ||
1422 | { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, | ||
1423 | AV_PIX_FMT_NONE }; | ||
1424 | |||
1425 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | if (ost->enc_ctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) |
1426 | 27 | opts.pix_fmts = mjpeg_formats; | |
1427 | } | ||
1428 | |||
1429 |
2/2✓ Branch 0 taken 3836 times.
✓ Branch 1 taken 2613 times.
|
6449 | if (threads_manual) { |
1430 | 3836 | ret = av_opt_get(ost->enc_ctx, "threads", 0, (uint8_t**)&opts.nb_threads); | |
1431 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3836 times.
|
3836 | if (ret < 0) |
1432 | ✗ | goto fail; | |
1433 | } | ||
1434 | |||
1435 |
2/2✓ Branch 0 taken 168 times.
✓ Branch 1 taken 6281 times.
|
6449 | if (ofilter) { |
1436 | 168 | ost->filter = ofilter; | |
1437 | 168 | ret = ofilter_bind_ost(ofilter, ost, ms->sch_idx_enc, &opts); | |
1438 | } else { | ||
1439 | 6281 | ret = init_simple_filtergraph(ost->ist, ost, filters, | |
1440 | 6281 | mux->sch, ms->sch_idx_enc, &opts); | |
1441 | } | ||
1442 | 6449 | av_freep(&opts.nb_threads); | |
1443 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6449 times.
|
6449 | if (ret < 0) |
1444 | ✗ | goto fail; | |
1445 | |||
1446 | 6449 | ret = sch_connect(mux->sch, SCH_ENC(ms->sch_idx_enc), | |
1447 | 6449 | SCH_MSTREAM(mux->sch_idx, ms->sch_idx)); | |
1448 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6449 times.
|
6449 | if (ret < 0) |
1449 | ✗ | goto fail; | |
1450 |
2/2✓ Branch 0 taken 683 times.
✓ Branch 1 taken 1 times.
|
684 | } else if (ost->ist) { |
1451 | 683 | int sched_idx = ist_output_add(ost->ist, ost); | |
1452 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 683 times.
|
683 | if (sched_idx < 0) { |
1453 | ✗ | av_log(ost, AV_LOG_ERROR, | |
1454 | "Error binding an input stream\n"); | ||
1455 | ✗ | ret = sched_idx; | |
1456 | ✗ | goto fail; | |
1457 | } | ||
1458 | 683 | ms->sch_idx_src = sched_idx; | |
1459 | |||
1460 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 645 times.
|
683 | if (ost->enc) { |
1461 | 38 | ret = sch_connect(mux->sch, SCH_DEC(sched_idx), | |
1462 | 38 | SCH_ENC(ms->sch_idx_enc)); | |
1463 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
|
38 | if (ret < 0) |
1464 | ✗ | goto fail; | |
1465 | |||
1466 | 38 | ret = sch_connect(mux->sch, SCH_ENC(ms->sch_idx_enc), | |
1467 | 38 | SCH_MSTREAM(mux->sch_idx, ms->sch_idx)); | |
1468 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
|
38 | if (ret < 0) |
1469 | ✗ | goto fail; | |
1470 | } else { | ||
1471 | 645 | ret = sch_connect(mux->sch, SCH_DSTREAM(ost->ist->file->index, sched_idx), | |
1472 | 645 | SCH_MSTREAM(ost->file->index, ms->sch_idx)); | |
1473 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 645 times.
|
645 | if (ret < 0) |
1474 | ✗ | goto fail; | |
1475 | } | ||
1476 | } | ||
1477 | |||
1478 |
4/4✓ Branch 0 taken 6964 times.
✓ Branch 1 taken 169 times.
✓ Branch 2 taken 645 times.
✓ Branch 3 taken 6319 times.
|
7133 | if (ost->ist && !ost->enc) { |
1479 | 645 | ret = streamcopy_init(mux, ost, &encoder_opts); | |
1480 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 645 times.
|
645 | if (ret < 0) |
1481 | ✗ | goto fail; | |
1482 | } | ||
1483 | |||
1484 | // copy estimated duration as a hint to the muxer | ||
1485 |
4/4✓ Branch 0 taken 6964 times.
✓ Branch 1 taken 169 times.
✓ Branch 2 taken 5446 times.
✓ Branch 3 taken 1518 times.
|
7133 | if (ost->ist && ost->ist->st->duration > 0) { |
1486 | 5446 | ms->stream_duration = ist->st->duration; | |
1487 | 5446 | ms->stream_duration_tb = ist->st->time_base; | |
1488 | } | ||
1489 | |||
1490 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7132 times.
|
7133 | if (post) |
1491 | 1 | *post = ost; | |
1492 | |||
1493 | 7133 | ret = 0; | |
1494 | |||
1495 | 7133 | fail: | |
1496 | 7133 | av_dict_free(&encoder_opts); | |
1497 | |||
1498 | 7133 | return ret; | |
1499 | } | ||
1500 | |||
1501 | 6380 | static int map_auto_video(Muxer *mux, const OptionsContext *o) | |
1502 | { | ||
1503 | 6380 | AVFormatContext *oc = mux->fc; | |
1504 | 6380 | InputStream *best_ist = NULL; | |
1505 | 6380 | int best_score = 0; | |
1506 | int qcr; | ||
1507 | |||
1508 | /* video: highest resolution */ | ||
1509 |
2/2✓ Branch 1 taken 732 times.
✓ Branch 2 taken 5648 times.
|
6380 | if (av_guess_codec(oc->oformat, NULL, oc->url, NULL, AVMEDIA_TYPE_VIDEO) == AV_CODEC_ID_NONE) |
1510 | 732 | return 0; | |
1511 | |||
1512 | 5648 | qcr = avformat_query_codec(oc->oformat, oc->oformat->video_codec, 0); | |
1513 |
2/2✓ Branch 0 taken 5689 times.
✓ Branch 1 taken 5648 times.
|
11337 | for (int j = 0; j < nb_input_files; j++) { |
1514 | 5689 | InputFile *ifile = input_files[j]; | |
1515 | 5689 | InputStream *file_best_ist = NULL; | |
1516 | 5689 | int file_best_score = 0; | |
1517 |
2/2✓ Branch 0 taken 5968 times.
✓ Branch 1 taken 5689 times.
|
11657 | for (int i = 0; i < ifile->nb_streams; i++) { |
1518 | 5968 | InputStream *ist = ifile->streams[i]; | |
1519 | int score; | ||
1520 | |||
1521 |
2/2✓ Branch 0 taken 5967 times.
✓ Branch 1 taken 1 times.
|
5968 | if (ist->user_set_discard == AVDISCARD_ALL || |
1522 |
2/2✓ Branch 0 taken 633 times.
✓ Branch 1 taken 5334 times.
|
5967 | ist->st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO) |
1523 | 634 | continue; | |
1524 | |||
1525 | 10668 | score = ist->st->codecpar->width * ist->st->codecpar->height | |
1526 |
2/2✓ Branch 0 taken 5332 times.
✓ Branch 1 taken 2 times.
|
5334 | + 100000000 * !!(ist->st->event_flags & AVSTREAM_EVENT_FLAG_NEW_PACKETS) |
1527 |
2/2✓ Branch 0 taken 514 times.
✓ Branch 1 taken 4820 times.
|
5334 | + 5000000*!!(ist->st->disposition & AV_DISPOSITION_DEFAULT); |
1528 |
3/4✓ Branch 0 taken 5334 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 5325 times.
|
5334 | if((qcr!=MKTAG('A', 'P', 'I', 'C')) && (ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC)) |
1529 | 9 | score = 1; | |
1530 | |||
1531 |
2/2✓ Branch 0 taken 5333 times.
✓ Branch 1 taken 1 times.
|
5334 | if (score > file_best_score) { |
1532 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 5333 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
5333 | if((qcr==MKTAG('A', 'P', 'I', 'C')) && !(ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC)) |
1533 | ✗ | continue; | |
1534 | 5333 | file_best_score = score; | |
1535 | 5333 | file_best_ist = ist; | |
1536 | } | ||
1537 | } | ||
1538 |
2/2✓ Branch 0 taken 5333 times.
✓ Branch 1 taken 356 times.
|
5689 | if (file_best_ist) { |
1539 |
1/2✓ Branch 0 taken 5333 times.
✗ Branch 1 not taken.
|
5333 | if((qcr == MKTAG('A', 'P', 'I', 'C')) || |
1540 |
2/2✓ Branch 0 taken 5325 times.
✓ Branch 1 taken 8 times.
|
5333 | !(file_best_ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC)) |
1541 |
2/2✓ Branch 0 taken 514 times.
✓ Branch 1 taken 4811 times.
|
5325 | file_best_score -= 5000000*!!(file_best_ist->st->disposition & AV_DISPOSITION_DEFAULT); |
1542 |
1/2✓ Branch 0 taken 5333 times.
✗ Branch 1 not taken.
|
5333 | if (file_best_score > best_score) { |
1543 | 5333 | best_score = file_best_score; | |
1544 | 5333 | best_ist = file_best_ist; | |
1545 | } | ||
1546 | } | ||
1547 | } | ||
1548 |
2/2✓ Branch 0 taken 5333 times.
✓ Branch 1 taken 315 times.
|
5648 | if (best_ist) |
1549 | 5333 | return ost_add(mux, o, AVMEDIA_TYPE_VIDEO, best_ist, NULL, NULL); | |
1550 | |||
1551 | 315 | return 0; | |
1552 | } | ||
1553 | |||
1554 | 6473 | static int map_auto_audio(Muxer *mux, const OptionsContext *o) | |
1555 | { | ||
1556 | 6473 | AVFormatContext *oc = mux->fc; | |
1557 | 6473 | InputStream *best_ist = NULL; | |
1558 | 6473 | int best_score = 0; | |
1559 | |||
1560 | /* audio: most channels */ | ||
1561 |
2/2✓ Branch 1 taken 843 times.
✓ Branch 2 taken 5630 times.
|
6473 | if (av_guess_codec(oc->oformat, NULL, oc->url, NULL, AVMEDIA_TYPE_AUDIO) == AV_CODEC_ID_NONE) |
1562 | 843 | return 0; | |
1563 | |||
1564 |
2/2✓ Branch 0 taken 5629 times.
✓ Branch 1 taken 5630 times.
|
11259 | for (int j = 0; j < nb_input_files; j++) { |
1565 | 5629 | InputFile *ifile = input_files[j]; | |
1566 | 5629 | InputStream *file_best_ist = NULL; | |
1567 | 5629 | int file_best_score = 0; | |
1568 |
2/2✓ Branch 0 taken 5834 times.
✓ Branch 1 taken 5629 times.
|
11463 | for (int i = 0; i < ifile->nb_streams; i++) { |
1569 | 5834 | InputStream *ist = ifile->streams[i]; | |
1570 | int score; | ||
1571 | |||
1572 |
2/2✓ Branch 0 taken 5833 times.
✓ Branch 1 taken 1 times.
|
5834 | if (ist->user_set_discard == AVDISCARD_ALL || |
1573 |
2/2✓ Branch 0 taken 4537 times.
✓ Branch 1 taken 1296 times.
|
5833 | ist->st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) |
1574 | 4538 | continue; | |
1575 | |||
1576 | 2592 | score = ist->st->codecpar->ch_layout.nb_channels | |
1577 |
2/2✓ Branch 0 taken 1295 times.
✓ Branch 1 taken 1 times.
|
1296 | + 100000000 * !!(ist->st->event_flags & AVSTREAM_EVENT_FLAG_NEW_PACKETS) |
1578 |
2/2✓ Branch 0 taken 174 times.
✓ Branch 1 taken 1122 times.
|
1296 | + 5000000*!!(ist->st->disposition & AV_DISPOSITION_DEFAULT); |
1579 |
2/2✓ Branch 0 taken 1286 times.
✓ Branch 1 taken 10 times.
|
1296 | if (score > file_best_score) { |
1580 | 1286 | file_best_score = score; | |
1581 | 1286 | file_best_ist = ist; | |
1582 | } | ||
1583 | } | ||
1584 |
2/2✓ Branch 0 taken 1286 times.
✓ Branch 1 taken 4343 times.
|
5629 | if (file_best_ist) { |
1585 |
2/2✓ Branch 0 taken 174 times.
✓ Branch 1 taken 1112 times.
|
1286 | file_best_score -= 5000000*!!(file_best_ist->st->disposition & AV_DISPOSITION_DEFAULT); |
1586 |
1/2✓ Branch 0 taken 1286 times.
✗ Branch 1 not taken.
|
1286 | if (file_best_score > best_score) { |
1587 | 1286 | best_score = file_best_score; | |
1588 | 1286 | best_ist = file_best_ist; | |
1589 | } | ||
1590 | } | ||
1591 | } | ||
1592 |
2/2✓ Branch 0 taken 1286 times.
✓ Branch 1 taken 4344 times.
|
5630 | if (best_ist) |
1593 | 1286 | return ost_add(mux, o, AVMEDIA_TYPE_AUDIO, best_ist, NULL, NULL); | |
1594 | |||
1595 | 4344 | return 0; | |
1596 | } | ||
1597 | |||
1598 | 6630 | static int map_auto_subtitle(Muxer *mux, const OptionsContext *o) | |
1599 | { | ||
1600 | 6630 | AVFormatContext *oc = mux->fc; | |
1601 | 6630 | const char *subtitle_codec_name = NULL; | |
1602 | |||
1603 | /* subtitles: pick first */ | ||
1604 | 6630 | subtitle_codec_name = opt_match_per_type_str(&o->codec_names, 's'); | |
1605 |
4/4✓ Branch 1 taken 6570 times.
✓ Branch 2 taken 60 times.
✓ Branch 3 taken 6563 times.
✓ Branch 4 taken 7 times.
|
6630 | if (!avcodec_find_encoder(oc->oformat->subtitle_codec) && !subtitle_codec_name) |
1606 | 6563 | return 0; | |
1607 | |||
1608 |
2/2✓ Branch 2 taken 81 times.
✓ Branch 3 taken 19 times.
|
100 | for (InputStream *ist = ist_iter(NULL); ist; ist = ist_iter(ist)) |
1609 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 33 times.
|
81 | if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) { |
1610 | AVCodecDescriptor const *input_descriptor = | ||
1611 | 48 | avcodec_descriptor_get(ist->st->codecpar->codec_id); | |
1612 | 48 | AVCodecDescriptor const *output_descriptor = NULL; | |
1613 | AVCodec const *output_codec = | ||
1614 | 48 | avcodec_find_encoder(oc->oformat->subtitle_codec); | |
1615 | 48 | int input_props = 0, output_props = 0; | |
1616 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
|
48 | if (ist->user_set_discard == AVDISCARD_ALL) |
1617 | ✗ | continue; | |
1618 |
2/2✓ Branch 0 taken 41 times.
✓ Branch 1 taken 7 times.
|
48 | if (output_codec) |
1619 | 41 | output_descriptor = avcodec_descriptor_get(output_codec->id); | |
1620 |
1/2✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
|
48 | if (input_descriptor) |
1621 | 48 | input_props = input_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB); | |
1622 |
2/2✓ Branch 0 taken 41 times.
✓ Branch 1 taken 7 times.
|
48 | if (output_descriptor) |
1623 | 41 | output_props = output_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB); | |
1624 |
2/2✓ Branch 0 taken 32 times.
✓ Branch 1 taken 16 times.
|
48 | if (subtitle_codec_name || |
1625 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
32 | input_props & output_props || |
1626 | // Map dvb teletext which has neither property to any output subtitle encoder | ||
1627 | ✗ | input_descriptor && output_descriptor && | |
1628 | ✗ | (!input_descriptor->props || | |
1629 | ✗ | !output_descriptor->props)) { | |
1630 | 48 | return ost_add(mux, o, AVMEDIA_TYPE_SUBTITLE, ist, NULL, NULL); | |
1631 | } | ||
1632 | } | ||
1633 | |||
1634 | 19 | return 0; | |
1635 | } | ||
1636 | |||
1637 | 6631 | static int map_auto_data(Muxer *mux, const OptionsContext *o) | |
1638 | { | ||
1639 | 6631 | AVFormatContext *oc = mux->fc; | |
1640 | /* Data only if codec id match */ | ||
1641 | 6631 | enum AVCodecID codec_id = av_guess_codec(oc->oformat, NULL, oc->url, NULL, AVMEDIA_TYPE_DATA); | |
1642 | |||
1643 |
1/2✓ Branch 0 taken 6631 times.
✗ Branch 1 not taken.
|
6631 | if (codec_id == AV_CODEC_ID_NONE) |
1644 | 6631 | return 0; | |
1645 | |||
1646 | ✗ | for (InputStream *ist = ist_iter(NULL); ist; ist = ist_iter(ist)) { | |
1647 | ✗ | if (ist->user_set_discard == AVDISCARD_ALL) | |
1648 | ✗ | continue; | |
1649 | ✗ | if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_DATA && | |
1650 | ✗ | ist->st->codecpar->codec_id == codec_id) { | |
1651 | ✗ | int ret = ost_add(mux, o, AVMEDIA_TYPE_DATA, ist, NULL, NULL); | |
1652 | ✗ | if (ret < 0) | |
1653 | ✗ | return ret; | |
1654 | } | ||
1655 | } | ||
1656 | |||
1657 | ✗ | return 0; | |
1658 | } | ||
1659 | |||
1660 | 351 | static int map_manual(Muxer *mux, const OptionsContext *o, const StreamMap *map) | |
1661 | { | ||
1662 | InputStream *ist; | ||
1663 | int ret; | ||
1664 | |||
1665 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 351 times.
|
351 | if (map->disabled) |
1666 | ✗ | return 0; | |
1667 | |||
1668 |
2/2✓ Branch 0 taken 54 times.
✓ Branch 1 taken 297 times.
|
351 | if (map->linklabel) { |
1669 | FilterGraph *fg; | ||
1670 | 54 | OutputFilter *ofilter = NULL; | |
1671 | int j, k; | ||
1672 | |||
1673 |
1/2✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
|
54 | for (j = 0; j < nb_filtergraphs; j++) { |
1674 | 54 | fg = filtergraphs[j]; | |
1675 |
1/2✓ Branch 0 taken 176 times.
✗ Branch 1 not taken.
|
176 | for (k = 0; k < fg->nb_outputs; k++) { |
1676 | 176 | const char *linklabel = fg->outputs[k]->linklabel; | |
1677 |
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)) { |
1678 | 54 | ofilter = fg->outputs[k]; | |
1679 | 54 | goto loop_end; | |
1680 | } | ||
1681 | } | ||
1682 | } | ||
1683 | ✗ | loop_end: | |
1684 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
|
54 | if (!ofilter) { |
1685 | ✗ | av_log(mux, AV_LOG_FATAL, "Output with label '%s' does not exist " | |
1686 | ✗ | "in any defined filter graph, or was already used elsewhere.\n", map->linklabel); | |
1687 | ✗ | return AVERROR(EINVAL); | |
1688 | } | ||
1689 | |||
1690 | 54 | av_log(mux, AV_LOG_VERBOSE, "Creating output stream from an explicitly " | |
1691 | 54 | "mapped complex filtergraph %d, output [%s]\n", fg->index, map->linklabel); | |
1692 | |||
1693 | 54 | ret = ost_add(mux, o, ofilter->type, NULL, ofilter, NULL); | |
1694 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
|
54 | if (ret < 0) |
1695 | ✗ | return ret; | |
1696 | } else { | ||
1697 | 297 | ist = input_files[map->file_index]->streams[map->stream_index]; | |
1698 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 297 times.
|
297 | if (ist->user_set_discard == AVDISCARD_ALL) { |
1699 | ✗ | av_log(mux, AV_LOG_FATAL, "Stream #%d:%d is disabled and cannot be mapped.\n", | |
1700 | ✗ | map->file_index, map->stream_index); | |
1701 | ✗ | return AVERROR(EINVAL); | |
1702 | } | ||
1703 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 297 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
297 | if(o->subtitle_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) |
1704 | ✗ | return 0; | |
1705 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 297 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
297 | if(o-> audio_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) |
1706 | ✗ | return 0; | |
1707 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 296 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
297 | if(o-> video_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) |
1708 | ✗ | return 0; | |
1709 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 297 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
297 | if(o-> data_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_DATA) |
1710 | ✗ | return 0; | |
1711 | |||
1712 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 297 times.
|
297 | if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_UNKNOWN && |
1713 | ✗ | !copy_unknown_streams) { | |
1714 | ✗ | av_log(mux, ignore_unknown_streams ? AV_LOG_WARNING : AV_LOG_FATAL, | |
1715 | "Cannot map stream #%d:%d - unsupported type.\n", | ||
1716 | ✗ | map->file_index, map->stream_index); | |
1717 | ✗ | if (!ignore_unknown_streams) { | |
1718 | ✗ | av_log(mux, AV_LOG_FATAL, | |
1719 | "If you want unsupported types ignored instead " | ||
1720 | "of failing, please use the -ignore_unknown option\n" | ||
1721 | "If you want them copied, please use -copy_unknown\n"); | ||
1722 | ✗ | return AVERROR(EINVAL); | |
1723 | } | ||
1724 | ✗ | return 0; | |
1725 | } | ||
1726 | |||
1727 | 297 | ret = ost_add(mux, o, ist->st->codecpar->codec_type, ist, NULL, NULL); | |
1728 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 297 times.
|
297 | if (ret < 0) |
1729 | ✗ | return ret; | |
1730 | } | ||
1731 | |||
1732 | 351 | return 0; | |
1733 | } | ||
1734 | |||
1735 | 6780 | static int of_add_attachments(Muxer *mux, const OptionsContext *o) | |
1736 | { | ||
1737 | OutputStream *ost; | ||
1738 | int err; | ||
1739 | |||
1740 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6780 times.
|
6781 | for (int i = 0; i < o->nb_attachments; i++) { |
1741 | AVIOContext *pb; | ||
1742 | uint8_t *attachment; | ||
1743 | char *attachment_filename; | ||
1744 | const char *p; | ||
1745 | int64_t len; | ||
1746 | |||
1747 |
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) { |
1748 | ✗ | av_log(mux, AV_LOG_FATAL, "Could not open attachment file %s.\n", | |
1749 | ✗ | o->attachments[i]); | |
1750 | ✗ | return err; | |
1751 | } | ||
1752 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if ((len = avio_size(pb)) <= 0) { |
1753 | ✗ | av_log(mux, AV_LOG_FATAL, "Could not get size of the attachment %s.\n", | |
1754 | ✗ | o->attachments[i]); | |
1755 | ✗ | err = len ? len : AVERROR_INVALIDDATA; | |
1756 | ✗ | goto read_fail; | |
1757 | } | ||
1758 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (len > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) { |
1759 | ✗ | av_log(mux, AV_LOG_FATAL, "Attachment %s too large.\n", | |
1760 | ✗ | o->attachments[i]); | |
1761 | ✗ | err = AVERROR(ERANGE); | |
1762 | ✗ | goto read_fail; | |
1763 | } | ||
1764 | |||
1765 | 1 | attachment = av_malloc(len + AV_INPUT_BUFFER_PADDING_SIZE); | |
1766 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!attachment) { |
1767 | ✗ | err = AVERROR(ENOMEM); | |
1768 | ✗ | goto read_fail; | |
1769 | } | ||
1770 | |||
1771 | 1 | err = avio_read(pb, attachment, len); | |
1772 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (err < 0) |
1773 | ✗ | av_log(mux, AV_LOG_FATAL, "Error reading attachment file %s: %s\n", | |
1774 | ✗ | o->attachments[i], av_err2str(err)); | |
1775 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | else if (err != len) { |
1776 | ✗ | av_log(mux, AV_LOG_FATAL, "Could not read all %"PRId64" bytes for " | |
1777 | ✗ | "attachment file %s\n", len, o->attachments[i]); | |
1778 | ✗ | err = AVERROR(EIO); | |
1779 | } | ||
1780 | |||
1781 | 1 | read_fail: | |
1782 | 1 | avio_closep(&pb); | |
1783 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (err < 0) |
1784 | ✗ | return err; | |
1785 | |||
1786 | 1 | memset(attachment + len, 0, AV_INPUT_BUFFER_PADDING_SIZE); | |
1787 | |||
1788 | 1 | av_log(mux, AV_LOG_VERBOSE, "Creating attachment stream from file %s\n", | |
1789 | 1 | o->attachments[i]); | |
1790 | |||
1791 | 1 | attachment_filename = av_strdup(o->attachments[i]); | |
1792 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!attachment_filename) { |
1793 | ✗ | av_free(attachment); | |
1794 | ✗ | return AVERROR(ENOMEM); | |
1795 | } | ||
1796 | |||
1797 | 1 | err = ost_add(mux, o, AVMEDIA_TYPE_ATTACHMENT, NULL, NULL, &ost); | |
1798 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (err < 0) { |
1799 | ✗ | av_free(attachment_filename); | |
1800 | ✗ | av_freep(&attachment); | |
1801 | ✗ | return err; | |
1802 | } | ||
1803 | |||
1804 | 1 | ost->attachment_filename = attachment_filename; | |
1805 | 1 | ost->par_in->extradata = attachment; | |
1806 | 1 | ost->par_in->extradata_size = len; | |
1807 | |||
1808 | 1 | p = strrchr(o->attachments[i], '/'); | |
1809 |
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); |
1810 | } | ||
1811 | |||
1812 | 6780 | return 0; | |
1813 | } | ||
1814 | |||
1815 | 6780 | static int create_streams(Muxer *mux, const OptionsContext *o) | |
1816 | { | ||
1817 | static int (* const map_func[])(Muxer *mux, const OptionsContext *o) = { | ||
1818 | [AVMEDIA_TYPE_VIDEO] = map_auto_video, | ||
1819 | [AVMEDIA_TYPE_AUDIO] = map_auto_audio, | ||
1820 | [AVMEDIA_TYPE_SUBTITLE] = map_auto_subtitle, | ||
1821 | [AVMEDIA_TYPE_DATA] = map_auto_data, | ||
1822 | }; | ||
1823 | |||
1824 | 6780 | AVFormatContext *oc = mux->fc; | |
1825 | |||
1826 | 6780 | int auto_disable = | |
1827 | 6780 | o->video_disable * (1 << AVMEDIA_TYPE_VIDEO) | | |
1828 | 6780 | o->audio_disable * (1 << AVMEDIA_TYPE_AUDIO) | | |
1829 | 6780 | o->subtitle_disable * (1 << AVMEDIA_TYPE_SUBTITLE) | | |
1830 | 6780 | o->data_disable * (1 << AVMEDIA_TYPE_DATA); | |
1831 | |||
1832 | int ret; | ||
1833 | |||
1834 | /* create streams for all unlabeled output pads */ | ||
1835 |
2/2✓ Branch 0 taken 119 times.
✓ Branch 1 taken 6780 times.
|
6899 | for (int i = 0; i < nb_filtergraphs; i++) { |
1836 | 119 | FilterGraph *fg = filtergraphs[i]; | |
1837 |
2/2✓ Branch 0 taken 169 times.
✓ Branch 1 taken 119 times.
|
288 | for (int j = 0; j < fg->nb_outputs; j++) { |
1838 | 169 | OutputFilter *ofilter = fg->outputs[j]; | |
1839 | |||
1840 |
3/4✓ Branch 0 taken 114 times.
✓ Branch 1 taken 55 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 114 times.
|
169 | if (ofilter->linklabel || ofilter->bound) |
1841 | 55 | continue; | |
1842 | |||
1843 | 114 | auto_disable |= 1 << ofilter->type; | |
1844 | |||
1845 | 114 | av_log(mux, AV_LOG_VERBOSE, "Creating output stream from unlabeled " | |
1846 | "output of complex filtergraph %d.", fg->index); | ||
1847 |
1/2✓ Branch 0 taken 114 times.
✗ Branch 1 not taken.
|
114 | if (!o->nb_stream_maps) |
1848 | 114 | av_log(mux, AV_LOG_VERBOSE, " This overrides automatic %s mapping.", | |
1849 | av_get_media_type_string(ofilter->type)); | ||
1850 | 114 | av_log(mux, AV_LOG_VERBOSE, "\n"); | |
1851 | |||
1852 | 114 | ret = ost_add(mux, o, ofilter->type, NULL, ofilter, NULL); | |
1853 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 114 times.
|
114 | if (ret < 0) |
1854 | ✗ | return ret; | |
1855 | } | ||
1856 | } | ||
1857 | |||
1858 |
2/2✓ Branch 0 taken 6631 times.
✓ Branch 1 taken 149 times.
|
6780 | if (!o->nb_stream_maps) { |
1859 | 6631 | av_log(mux, AV_LOG_VERBOSE, "No explicit maps, mapping streams automatically...\n"); | |
1860 | |||
1861 | /* pick the "best" stream of each type */ | ||
1862 |
2/2✓ Branch 0 taken 26524 times.
✓ Branch 1 taken 6631 times.
|
33155 | for (int i = 0; i < FF_ARRAY_ELEMS(map_func); i++) { |
1863 |
3/4✓ Branch 0 taken 26524 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 410 times.
✓ Branch 3 taken 26114 times.
|
26524 | if (!map_func[i] || auto_disable & (1 << i)) |
1864 | 410 | continue; | |
1865 | 26114 | ret = map_func[i](mux, o); | |
1866 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 26114 times.
|
26114 | if (ret < 0) |
1867 | ✗ | return ret; | |
1868 | } | ||
1869 | } else { | ||
1870 | 149 | av_log(mux, AV_LOG_VERBOSE, "Adding streams from explicit maps...\n"); | |
1871 | |||
1872 |
2/2✓ Branch 0 taken 351 times.
✓ Branch 1 taken 149 times.
|
500 | for (int i = 0; i < o->nb_stream_maps; i++) { |
1873 | 351 | ret = map_manual(mux, o, &o->stream_maps[i]); | |
1874 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 351 times.
|
351 | if (ret < 0) |
1875 | ✗ | return ret; | |
1876 | } | ||
1877 | } | ||
1878 | |||
1879 | 6780 | ret = of_add_attachments(mux, o); | |
1880 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6780 times.
|
6780 | if (ret < 0) |
1881 | ✗ | return ret; | |
1882 | |||
1883 | // setup fix_sub_duration_heartbeat mappings | ||
1884 |
2/2✓ Branch 0 taken 7133 times.
✓ Branch 1 taken 6780 times.
|
13913 | for (unsigned i = 0; i < oc->nb_streams; i++) { |
1885 | 7133 | MuxStream *src = ms_from_ost(mux->of.streams[i]); | |
1886 | |||
1887 |
2/2✓ Branch 0 taken 7132 times.
✓ Branch 1 taken 1 times.
|
7133 | if (!src->ost.fix_sub_duration_heartbeat) |
1888 | 7132 | continue; | |
1889 | |||
1890 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
3 | for (unsigned j = 0; j < oc->nb_streams; j++) { |
1891 | 2 | MuxStream *dst = ms_from_ost(mux->of.streams[j]); | |
1892 | |||
1893 |
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 || |
1894 |
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) |
1895 | 1 | continue; | |
1896 | |||
1897 | 1 | ret = sch_mux_sub_heartbeat_add(mux->sch, mux->sch_idx, src->sch_idx, | |
1898 | 1 | dst->sch_idx_src); | |
1899 | |||
1900 | } | ||
1901 | } | ||
1902 | |||
1903 | // handle -apad | ||
1904 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 6776 times.
|
6780 | if (o->shortest) { |
1905 | 4 | int have_video = 0; | |
1906 | |||
1907 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | for (unsigned i = 0; i < mux->of.nb_streams; i++) |
1908 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | if (mux->of.streams[i]->type == AVMEDIA_TYPE_VIDEO) { |
1909 | 4 | have_video = 1; | |
1910 | 4 | break; | |
1911 | } | ||
1912 | |||
1913 |
3/4✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 4 times.
|
12 | for (unsigned i = 0; have_video && i < mux->of.nb_streams; i++) { |
1914 | 8 | MuxStream *ms = ms_from_ost(mux->of.streams[i]); | |
1915 | 8 | OutputFilter *ofilter = ms->ost.filter; | |
1916 | |||
1917 |
3/6✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
8 | if (ms->ost.type != AVMEDIA_TYPE_AUDIO || !ms->apad || !ofilter) |
1918 | 8 | continue; | |
1919 | |||
1920 | ✗ | ofilter->apad = av_strdup(ms->apad); | |
1921 | ✗ | if (!ofilter->apad) | |
1922 | ✗ | return AVERROR(ENOMEM); | |
1923 | } | ||
1924 | } | ||
1925 |
2/2✓ Branch 0 taken 7133 times.
✓ Branch 1 taken 6780 times.
|
13913 | for (unsigned i = 0; i < mux->of.nb_streams; i++) { |
1926 | 7133 | MuxStream *ms = ms_from_ost(mux->of.streams[i]); | |
1927 | 7133 | ms->apad = NULL; | |
1928 | } | ||
1929 | |||
1930 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 6780 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
6780 | if (!oc->nb_streams && !(oc->oformat->flags & AVFMT_NOSTREAMS)) { |
1931 | ✗ | av_dump_format(oc, nb_output_files - 1, oc->url, 1); | |
1932 | ✗ | av_log(mux, AV_LOG_ERROR, "Output file does not contain any stream\n"); | |
1933 | ✗ | return AVERROR(EINVAL); | |
1934 | } | ||
1935 | |||
1936 | 6780 | return 0; | |
1937 | } | ||
1938 | |||
1939 | 6780 | static int setup_sync_queues(Muxer *mux, AVFormatContext *oc, | |
1940 | int64_t buf_size_us, int shortest) | ||
1941 | { | ||
1942 | 6780 | OutputFile *of = &mux->of; | |
1943 | 6780 | int nb_av_enc = 0, nb_audio_fs = 0, nb_interleaved = 0; | |
1944 | 6780 | int limit_frames = 0, limit_frames_av_enc = 0; | |
1945 | |||
1946 | #define IS_AV_ENC(ost, type) \ | ||
1947 | (ost->enc_ctx && (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) | ||
1948 | #define IS_INTERLEAVED(type) (type != AVMEDIA_TYPE_ATTACHMENT) | ||
1949 | |||
1950 |
2/2✓ Branch 0 taken 7133 times.
✓ Branch 1 taken 6780 times.
|
13913 | for (int i = 0; i < oc->nb_streams; i++) { |
1951 | 7133 | OutputStream *ost = of->streams[i]; | |
1952 | 7133 | MuxStream *ms = ms_from_ost(ost); | |
1953 | 7133 | enum AVMediaType type = ost->type; | |
1954 | |||
1955 | 7133 | ms->sq_idx_mux = -1; | |
1956 | |||
1957 | 7133 | nb_interleaved += IS_INTERLEAVED(type); | |
1958 |
6/6✓ Branch 0 taken 6487 times.
✓ Branch 1 taken 646 times.
✓ Branch 2 taken 1285 times.
✓ Branch 3 taken 5202 times.
✓ Branch 4 taken 1247 times.
✓ Branch 5 taken 38 times.
|
7133 | nb_av_enc += IS_AV_ENC(ost, type); |
1959 |
4/4✓ Branch 0 taken 6487 times.
✓ Branch 1 taken 646 times.
✓ Branch 2 taken 1247 times.
✓ Branch 3 taken 5240 times.
|
8380 | nb_audio_fs += (ost->enc_ctx && type == AVMEDIA_TYPE_AUDIO && |
1960 |
2/2✓ Branch 0 taken 156 times.
✓ Branch 1 taken 1091 times.
|
1247 | !(ost->enc_ctx->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)); |
1961 | |||
1962 | 7133 | limit_frames |= ms->max_frames < INT64_MAX; | |
1963 |
7/8✓ Branch 0 taken 2678 times.
✓ Branch 1 taken 4455 times.
✓ Branch 2 taken 2651 times.
✓ Branch 3 taken 27 times.
✓ Branch 4 taken 28 times.
✓ Branch 5 taken 2623 times.
✓ Branch 6 taken 28 times.
✗ Branch 7 not taken.
|
7133 | limit_frames_av_enc |= (ms->max_frames < INT64_MAX) && IS_AV_ENC(ost, type); |
1964 | } | ||
1965 | |||
1966 |
7/8✓ Branch 0 taken 228 times.
✓ Branch 1 taken 6552 times.
✓ Branch 2 taken 224 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 6776 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3993 times.
✓ Branch 7 taken 122 times.
|
10895 | if (!((nb_interleaved > 1 && shortest) || |
1967 |
2/2✓ Branch 0 taken 4115 times.
✓ Branch 1 taken 2661 times.
|
6776 | (nb_interleaved > 0 && limit_frames) || |
1968 | nb_audio_fs)) | ||
1969 | 3993 | return 0; | |
1970 | |||
1971 | /* we use a sync queue before encoding when: | ||
1972 | * - 'shortest' is in effect and we have two or more encoded audio/video | ||
1973 | * streams | ||
1974 | * - at least one encoded audio/video stream is frame-limited, since | ||
1975 | * that has similar semantics to 'shortest' | ||
1976 | * - at least one audio encoder requires constant frame sizes | ||
1977 | * | ||
1978 | * Note that encoding sync queues are handled in the scheduler, because | ||
1979 | * different encoders run in different threads and need external | ||
1980 | * synchronization, while muxer sync queues can be handled inside the muxer | ||
1981 | */ | ||
1982 |
8/8✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2783 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 135 times.
✓ Branch 5 taken 2651 times.
✓ Branch 6 taken 124 times.
✓ Branch 7 taken 11 times.
|
2787 | if ((shortest && nb_av_enc > 1) || limit_frames_av_enc || nb_audio_fs) { |
1983 | int sq_idx, ret; | ||
1984 | |||
1985 | 2776 | sq_idx = sch_add_sq_enc(mux->sch, buf_size_us, mux); | |
1986 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2776 times.
|
2776 | if (sq_idx < 0) |
1987 | ✗ | return sq_idx; | |
1988 | |||
1989 |
2/2✓ Branch 0 taken 2828 times.
✓ Branch 1 taken 2776 times.
|
5604 | for (int i = 0; i < oc->nb_streams; i++) { |
1990 | 2828 | OutputStream *ost = of->streams[i]; | |
1991 | 2828 | MuxStream *ms = ms_from_ost(ost); | |
1992 | 2828 | enum AVMediaType type = ost->type; | |
1993 | |||
1994 |
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)) |
1995 | 7 | continue; | |
1996 | |||
1997 | 2821 | ret = sch_sq_add_enc(mux->sch, sq_idx, ms->sch_idx_enc, | |
1998 |
2/2✓ Branch 0 taken 2651 times.
✓ Branch 1 taken 166 times.
|
2817 | shortest || ms->max_frames < INT64_MAX, |
1999 |
2/2✓ Branch 0 taken 2817 times.
✓ Branch 1 taken 4 times.
|
2821 | ms->max_frames); |
2000 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2821 times.
|
2821 | if (ret < 0) |
2001 | ✗ | return ret; | |
2002 | } | ||
2003 | } | ||
2004 | |||
2005 | /* if there are any additional interleaved streams, then ALL the streams | ||
2006 | * are also synchronized before sending them to the muxer */ | ||
2007 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 2772 times.
|
2787 | if (nb_interleaved > nb_av_enc) { |
2008 | 15 | mux->sq_mux = sq_alloc(SYNC_QUEUE_PACKETS, buf_size_us, mux); | |
2009 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
|
15 | if (!mux->sq_mux) |
2010 | ✗ | return AVERROR(ENOMEM); | |
2011 | |||
2012 | 15 | mux->sq_pkt = av_packet_alloc(); | |
2013 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
|
15 | if (!mux->sq_pkt) |
2014 | ✗ | return AVERROR(ENOMEM); | |
2015 | |||
2016 |
2/2✓ Branch 0 taken 43 times.
✓ Branch 1 taken 15 times.
|
58 | for (int i = 0; i < oc->nb_streams; i++) { |
2017 | 43 | OutputStream *ost = of->streams[i]; | |
2018 | 43 | MuxStream *ms = ms_from_ost(ost); | |
2019 | 43 | enum AVMediaType type = ost->type; | |
2020 | |||
2021 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
|
43 | if (!IS_INTERLEAVED(type)) |
2022 | ✗ | continue; | |
2023 | |||
2024 |
2/2✓ Branch 0 taken 37 times.
✓ Branch 1 taken 6 times.
|
80 | ms->sq_idx_mux = sq_add_stream(mux->sq_mux, |
2025 |
2/2✓ Branch 0 taken 27 times.
✓ Branch 1 taken 10 times.
|
37 | shortest || ms->max_frames < INT64_MAX); |
2026 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
|
43 | if (ms->sq_idx_mux < 0) |
2027 | ✗ | return ms->sq_idx_mux; | |
2028 | |||
2029 |
2/2✓ Branch 0 taken 27 times.
✓ Branch 1 taken 16 times.
|
43 | if (ms->max_frames != INT64_MAX) |
2030 | 27 | sq_limit_frames(mux->sq_mux, ms->sq_idx_mux, ms->max_frames); | |
2031 | } | ||
2032 | } | ||
2033 | |||
2034 | #undef IS_AV_ENC | ||
2035 | #undef IS_INTERLEAVED | ||
2036 | |||
2037 | 2787 | return 0; | |
2038 | } | ||
2039 | |||
2040 | 9 | static int of_parse_iamf_audio_element_layers(Muxer *mux, AVStreamGroup *stg, char *ptr) | |
2041 | { | ||
2042 | 9 | AVIAMFAudioElement *audio_element = stg->params.iamf_audio_element; | |
2043 | 9 | AVDictionary *dict = NULL; | |
2044 | const char *token; | ||
2045 | 9 | int ret = 0; | |
2046 | |||
2047 | 9 | audio_element->demixing_info = | |
2048 | 9 | av_iamf_param_definition_alloc(AV_IAMF_PARAMETER_DEFINITION_DEMIXING, 1, NULL); | |
2049 | 9 | audio_element->recon_gain_info = | |
2050 | 9 | av_iamf_param_definition_alloc(AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN, 1, NULL); | |
2051 | |||
2052 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | if (!audio_element->demixing_info || |
2053 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | !audio_element->recon_gain_info) |
2054 | ✗ | return AVERROR(ENOMEM); | |
2055 | |||
2056 | /* process manually set layers and parameters */ | ||
2057 | 9 | token = av_strtok(NULL, ",", &ptr); | |
2058 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 9 times.
|
45 | while (token) { |
2059 | const AVDictionaryEntry *e; | ||
2060 | 36 | int demixing = 0, recon_gain = 0; | |
2061 | 36 | int layer = 0; | |
2062 | |||
2063 |
2/2✓ Branch 0 taken 35 times.
✓ Branch 1 taken 1 times.
|
36 | if (ptr) |
2064 | 35 | ptr += strspn(ptr, " \n\t\r"); | |
2065 |
2/2✓ Branch 1 taken 22 times.
✓ Branch 2 taken 14 times.
|
36 | if (av_strstart(token, "layer=", &token)) |
2066 | 22 | layer = 1; | |
2067 |
2/2✓ Branch 1 taken 7 times.
✓ Branch 2 taken 7 times.
|
14 | else if (av_strstart(token, "demixing=", &token)) |
2068 | 7 | demixing = 1; | |
2069 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | else if (av_strstart(token, "recon_gain=", &token)) |
2070 | 7 | recon_gain = 1; | |
2071 | |||
2072 | 36 | av_dict_free(&dict); | |
2073 | 36 | ret = av_dict_parse_string(&dict, token, "=", ":", 0); | |
2074 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
|
36 | if (ret < 0) { |
2075 | ✗ | av_log(mux, AV_LOG_ERROR, "Error parsing audio element specification %s\n", token); | |
2076 | ✗ | goto fail; | |
2077 | } | ||
2078 | |||
2079 |
2/2✓ Branch 0 taken 22 times.
✓ Branch 1 taken 14 times.
|
36 | if (layer) { |
2080 | 22 | AVIAMFLayer *audio_layer = av_iamf_audio_element_add_layer(audio_element); | |
2081 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
|
22 | if (!audio_layer) { |
2082 | ✗ | av_log(mux, AV_LOG_ERROR, "Error adding layer to stream group %d\n", stg->index); | |
2083 | ✗ | ret = AVERROR(ENOMEM); | |
2084 | ✗ | goto fail; | |
2085 | } | ||
2086 | 22 | av_opt_set_dict(audio_layer, &dict); | |
2087 |
3/4✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
14 | } else if (demixing || recon_gain) { |
2088 | 14 | AVIAMFParamDefinition *param = demixing ? audio_element->demixing_info | |
2089 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
|
14 | : audio_element->recon_gain_info; |
2090 | 14 | void *subblock = av_iamf_param_definition_get_subblock(param, 0); | |
2091 | |||
2092 | 14 | av_opt_set_dict(param, &dict); | |
2093 | 14 | av_opt_set_dict(subblock, &dict); | |
2094 | } | ||
2095 | |||
2096 | // make sure that no entries are left in the dict | ||
2097 | 36 | e = NULL; | |
2098 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
|
36 | if (e = av_dict_iterate(dict, e)) { |
2099 | ✗ | av_log(mux, AV_LOG_FATAL, "Unknown layer key %s.\n", e->key); | |
2100 | ✗ | ret = AVERROR(EINVAL); | |
2101 | ✗ | goto fail; | |
2102 | } | ||
2103 | 36 | token = av_strtok(NULL, ",", &ptr); | |
2104 | } | ||
2105 | |||
2106 | 9 | fail: | |
2107 | 9 | av_dict_free(&dict); | |
2108 |
2/4✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
|
9 | if (!ret && !audio_element->nb_layers) { |
2109 | ✗ | av_log(mux, AV_LOG_ERROR, "No layer in audio element specification\n"); | |
2110 | ✗ | ret = AVERROR(EINVAL); | |
2111 | } | ||
2112 | |||
2113 | 9 | return ret; | |
2114 | } | ||
2115 | |||
2116 | 9 | static int of_parse_iamf_submixes(Muxer *mux, AVStreamGroup *stg, char *ptr) | |
2117 | { | ||
2118 | 9 | AVFormatContext *oc = mux->fc; | |
2119 | 9 | AVIAMFMixPresentation *mix = stg->params.iamf_mix_presentation; | |
2120 | 9 | AVDictionary *dict = NULL; | |
2121 | const char *token; | ||
2122 | 9 | char *submix_str = NULL; | |
2123 | 9 | int ret = 0; | |
2124 | |||
2125 | /* process manually set submixes */ | ||
2126 | 9 | token = av_strtok(NULL, ",", &ptr); | |
2127 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 9 times.
|
20 | while (token) { |
2128 | 11 | AVIAMFSubmix *submix = NULL; | |
2129 | const char *subtoken; | ||
2130 | 11 | char *subptr = NULL; | |
2131 | |||
2132 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1 times.
|
11 | if (ptr) |
2133 | 10 | ptr += strspn(ptr, " \n\t\r"); | |
2134 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
|
11 | if (!av_strstart(token, "submix=", &token)) { |
2135 | ✗ | av_log(mux, AV_LOG_ERROR, "No submix in mix presentation specification \"%s\"\n", token); | |
2136 | ✗ | goto fail; | |
2137 | } | ||
2138 | |||
2139 | 11 | submix_str = av_strdup(token); | |
2140 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | if (!submix_str) |
2141 | ✗ | goto fail; | |
2142 | |||
2143 | 11 | submix = av_iamf_mix_presentation_add_submix(mix); | |
2144 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | if (!submix) { |
2145 | ✗ | av_log(mux, AV_LOG_ERROR, "Error adding submix to stream group %d\n", stg->index); | |
2146 | ✗ | ret = AVERROR(ENOMEM); | |
2147 | ✗ | goto fail; | |
2148 | } | ||
2149 | 11 | submix->output_mix_config = | |
2150 | 11 | av_iamf_param_definition_alloc(AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN, 0, NULL); | |
2151 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | if (!submix->output_mix_config) { |
2152 | ✗ | ret = AVERROR(ENOMEM); | |
2153 | ✗ | goto fail; | |
2154 | } | ||
2155 | |||
2156 | 11 | subptr = NULL; | |
2157 | 11 | subtoken = av_strtok(submix_str, "|", &subptr); | |
2158 |
2/2✓ Branch 0 taken 46 times.
✓ Branch 1 taken 11 times.
|
57 | while (subtoken) { |
2159 | const AVDictionaryEntry *e; | ||
2160 | 46 | int element = 0, layout = 0; | |
2161 | |||
2162 |
2/2✓ Branch 0 taken 35 times.
✓ Branch 1 taken 11 times.
|
46 | if (subptr) |
2163 | 35 | subptr += strspn(subptr, " \n\t\r"); | |
2164 |
2/2✓ Branch 1 taken 11 times.
✓ Branch 2 taken 35 times.
|
46 | if (av_strstart(subtoken, "element=", &subtoken)) |
2165 | 11 | element = 1; | |
2166 |
2/2✓ Branch 1 taken 24 times.
✓ Branch 2 taken 11 times.
|
35 | else if (av_strstart(subtoken, "layout=", &subtoken)) |
2167 | 24 | layout = 1; | |
2168 | |||
2169 | 46 | av_dict_free(&dict); | |
2170 | 46 | ret = av_dict_parse_string(&dict, subtoken, "=", ":", 0); | |
2171 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
|
46 | if (ret < 0) { |
2172 | ✗ | av_log(mux, AV_LOG_ERROR, "Error parsing submix specification \"%s\"\n", subtoken); | |
2173 | ✗ | goto fail; | |
2174 | } | ||
2175 | |||
2176 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 35 times.
|
46 | if (element) { |
2177 | AVIAMFSubmixElement *submix_element; | ||
2178 | 11 | char *endptr = NULL; | |
2179 | 11 | int64_t idx = -1; | |
2180 | |||
2181 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
11 | if (e = av_dict_get(dict, "stg", NULL, 0)) |
2182 | 11 | idx = strtoll(e->value, &endptr, 0); | |
2183 |
4/8✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 11 times.
✗ Branch 7 not taken.
|
11 | if (!endptr || *endptr || idx < 0 || idx >= oc->nb_stream_groups - 1 || |
2184 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | oc->stream_groups[idx]->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT) { |
2185 | ✗ | av_log(mux, AV_LOG_ERROR, "Invalid or missing stream group index in " | |
2186 | "submix element specification \"%s\"\n", subtoken); | ||
2187 | ✗ | ret = AVERROR(EINVAL); | |
2188 | ✗ | goto fail; | |
2189 | } | ||
2190 | 11 | submix_element = av_iamf_submix_add_element(submix); | |
2191 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | if (!submix_element) { |
2192 | ✗ | av_log(mux, AV_LOG_ERROR, "Error adding element to submix\n"); | |
2193 | ✗ | ret = AVERROR(ENOMEM); | |
2194 | ✗ | goto fail; | |
2195 | } | ||
2196 | |||
2197 | 11 | submix_element->audio_element_id = oc->stream_groups[idx]->id; | |
2198 | |||
2199 | 11 | submix_element->element_mix_config = | |
2200 | 11 | av_iamf_param_definition_alloc(AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN, 0, NULL); | |
2201 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | if (!submix_element->element_mix_config) |
2202 | ✗ | ret = AVERROR(ENOMEM); | |
2203 | 11 | av_dict_set(&dict, "stg", NULL, 0); | |
2204 | 11 | av_opt_set_dict2(submix_element, &dict, AV_OPT_SEARCH_CHILDREN); | |
2205 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 11 times.
|
35 | } else if (layout) { |
2206 | 24 | AVIAMFSubmixLayout *submix_layout = av_iamf_submix_add_layout(submix); | |
2207 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
|
24 | if (!submix_layout) { |
2208 | ✗ | av_log(mux, AV_LOG_ERROR, "Error adding layout to submix\n"); | |
2209 | ✗ | ret = AVERROR(ENOMEM); | |
2210 | ✗ | goto fail; | |
2211 | } | ||
2212 | 24 | av_opt_set_dict(submix_layout, &dict); | |
2213 | } else | ||
2214 | 11 | av_opt_set_dict2(submix, &dict, AV_OPT_SEARCH_CHILDREN); | |
2215 | |||
2216 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
|
46 | if (ret < 0) { |
2217 | ✗ | goto fail; | |
2218 | } | ||
2219 | |||
2220 | // make sure that no entries are left in the dict | ||
2221 | 46 | e = NULL; | |
2222 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
|
46 | while (e = av_dict_iterate(dict, e)) { |
2223 | ✗ | av_log(mux, AV_LOG_FATAL, "Unknown submix key %s.\n", e->key); | |
2224 | ✗ | ret = AVERROR(EINVAL); | |
2225 | ✗ | goto fail; | |
2226 | } | ||
2227 | 46 | subtoken = av_strtok(NULL, "|", &subptr); | |
2228 | } | ||
2229 | 11 | av_freep(&submix_str); | |
2230 | |||
2231 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | if (!submix->nb_elements) { |
2232 | ✗ | av_log(mux, AV_LOG_ERROR, "No audio elements in submix specification \"%s\"\n", token); | |
2233 | ✗ | ret = AVERROR(EINVAL); | |
2234 | } | ||
2235 | 11 | token = av_strtok(NULL, ",", &ptr); | |
2236 | } | ||
2237 | |||
2238 | 9 | fail: | |
2239 | 9 | av_dict_free(&dict); | |
2240 | 9 | av_free(submix_str); | |
2241 | |||
2242 | 9 | return ret; | |
2243 | } | ||
2244 | |||
2245 | 12 | static int of_serialize_options(Muxer *mux, void *obj, AVBPrint *bp) | |
2246 | { | ||
2247 | char *ptr; | ||
2248 | int ret; | ||
2249 | |||
2250 | 12 | ret = av_opt_serialize(obj, 0, AV_OPT_SERIALIZE_SKIP_DEFAULTS | AV_OPT_SERIALIZE_SEARCH_CHILDREN, | |
2251 | &ptr, '=', ':'); | ||
2252 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if (ret < 0) { |
2253 | ✗ | av_log(mux, AV_LOG_ERROR, "Failed to serialize group\n"); | |
2254 | ✗ | return ret; | |
2255 | } | ||
2256 | |||
2257 | 12 | av_bprintf(bp, "%s", ptr); | |
2258 | 12 | ret = strlen(ptr); | |
2259 | 12 | av_free(ptr); | |
2260 | |||
2261 | 12 | return ret; | |
2262 | } | ||
2263 | |||
2264 | #define SERIALIZE(parent, child) do { \ | ||
2265 | ret = of_serialize_options(mux, parent->child, bp); \ | ||
2266 | if (ret < 0) \ | ||
2267 | return ret; \ | ||
2268 | } while (0) | ||
2269 | |||
2270 | #define SERIALIZE_LOOP_SUBBLOCK(obj) do { \ | ||
2271 | for (int k = 0; k < obj->nb_subblocks; k++) { \ | ||
2272 | ret = of_serialize_options(mux, \ | ||
2273 | av_iamf_param_definition_get_subblock(obj, k), bp); \ | ||
2274 | if (ret < 0) \ | ||
2275 | return ret; \ | ||
2276 | } \ | ||
2277 | } while (0) | ||
2278 | |||
2279 | #define SERIALIZE_LOOP(parent, child, suffix, separator) do { \ | ||
2280 | for (int j = 0; j < parent->nb_## child ## suffix; j++) { \ | ||
2281 | av_bprintf(bp, separator#child "="); \ | ||
2282 | SERIALIZE(parent, child ## suffix[j]); \ | ||
2283 | } \ | ||
2284 | } while (0) | ||
2285 | |||
2286 | 1 | static int64_t get_stream_group_index_from_id(Muxer *mux, int64_t id) | |
2287 | { | ||
2288 | 1 | AVFormatContext *oc = mux->fc; | |
2289 | |||
2290 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | for (unsigned i = 0; i < oc->nb_stream_groups; i++) |
2291 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (oc->stream_groups[i]->id == id) |
2292 | 1 | return oc->stream_groups[i]->index; | |
2293 | |||
2294 | ✗ | return AVERROR(EINVAL); | |
2295 | } | ||
2296 | |||
2297 | 2 | static int of_map_group(Muxer *mux, AVDictionary **dict, AVBPrint *bp, const char *map) | |
2298 | { | ||
2299 | AVStreamGroup *stg; | ||
2300 | int ret, file_idx, stream_idx; | ||
2301 | char *ptr; | ||
2302 | |||
2303 | 2 | file_idx = strtol(map, &ptr, 0); | |
2304 |
3/6✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
2 | if (file_idx >= nb_input_files || file_idx < 0 || map == ptr) { |
2305 | ✗ | av_log(mux, AV_LOG_ERROR, "Invalid input file index: %d.\n", file_idx); | |
2306 | ✗ | return AVERROR(EINVAL); | |
2307 | } | ||
2308 | |||
2309 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | stream_idx = strtol(*ptr == '=' ? ptr + 1 : ptr, &ptr, 0); |
2310 |
3/6✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
2 | if (*ptr || stream_idx >= input_files[file_idx]->ctx->nb_stream_groups || stream_idx < 0) { |
2311 | ✗ | av_log(mux, AV_LOG_ERROR, "Invalid input stream group index: %d.\n", stream_idx); | |
2312 | ✗ | return AVERROR(EINVAL); | |
2313 | } | ||
2314 | |||
2315 | 2 | stg = input_files[file_idx]->ctx->stream_groups[stream_idx]; | |
2316 | 2 | ret = of_serialize_options(mux, stg, bp); | |
2317 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (ret < 0) |
2318 | ✗ | return ret; | |
2319 | |||
2320 | 2 | ret = av_dict_parse_string(dict, bp->str, "=", ":", 0); | |
2321 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (ret < 0) |
2322 | ✗ | av_log(mux, AV_LOG_ERROR, "Error parsing mapped group specification %s\n", ptr); | |
2323 | 2 | av_dict_set_int(dict, "type", stg->type, 0); | |
2324 | |||
2325 | 2 | av_bprint_clear(bp); | |
2326 |
2/3✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | switch(stg->type) { |
2327 | 1 | case AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT: { | |
2328 | 1 | AVIAMFAudioElement *audio_element = stg->params.iamf_audio_element; | |
2329 | |||
2330 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (audio_element->demixing_info) { |
2331 | 1 | AVIAMFParamDefinition *demixing_info = audio_element->demixing_info; | |
2332 | 1 | av_bprintf(bp, ",demixing="); | |
2333 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | SERIALIZE(audio_element, demixing_info); |
2334 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | if (ret && demixing_info->nb_subblocks) |
2335 | 1 | av_bprintf(bp, ":"); | |
2336 |
3/4✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
|
2 | SERIALIZE_LOOP_SUBBLOCK(demixing_info); |
2337 | } | ||
2338 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (audio_element->recon_gain_info) { |
2339 | 1 | AVIAMFParamDefinition *recon_gain_info = audio_element->recon_gain_info; | |
2340 | 1 | av_bprintf(bp, ",recon_gain="); | |
2341 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | SERIALIZE(audio_element, recon_gain_info); |
2342 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | if (ret && recon_gain_info->nb_subblocks) |
2343 | 1 | av_bprintf(bp, ":"); | |
2344 |
3/4✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
|
2 | SERIALIZE_LOOP_SUBBLOCK(recon_gain_info); |
2345 | } | ||
2346 |
3/4✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 1 times.
|
3 | SERIALIZE_LOOP(audio_element, layer, s, ","); |
2347 | 1 | break; | |
2348 | } | ||
2349 | 1 | case AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION: { | |
2350 | 1 | AVIAMFMixPresentation *mix = stg->params.iamf_mix_presentation; | |
2351 | |||
2352 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | for (int i = 0; i < mix->nb_submixes; i++) { |
2353 | 1 | AVIAMFSubmix *submix = mix->submixes[i]; | |
2354 | 1 | AVIAMFParamDefinition *output_mix_config = submix->output_mix_config; | |
2355 | |||
2356 | 1 | av_bprintf(bp, ",submix="); | |
2357 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | SERIALIZE(mix, submixes[i]); |
2358 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | if (ret && output_mix_config->nb_subblocks) |
2359 | ✗ | av_bprintf(bp, ":"); | |
2360 |
1/4✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
|
1 | SERIALIZE_LOOP_SUBBLOCK(output_mix_config); |
2361 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | for (int j = 0; j < submix->nb_elements; j++) { |
2362 | 1 | AVIAMFSubmixElement *element = submix->elements[j]; | |
2363 | 1 | AVIAMFParamDefinition *element_mix_config = element->element_mix_config; | |
2364 | 1 | int64_t id = get_stream_group_index_from_id(mux, element->audio_element_id); | |
2365 | |||
2366 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (id < 0) { |
2367 | ✗ | av_log(mux, AV_LOG_ERROR, "Invalid or missing stream group index in" | |
2368 | "submix element"); | ||
2369 | ✗ | return id; | |
2370 | } | ||
2371 | |||
2372 | 1 | av_bprintf(bp, "|element="); | |
2373 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | SERIALIZE(submix, elements[j]); |
2374 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | if (ret && element_mix_config->nb_subblocks) |
2375 | ✗ | av_bprintf(bp, ":"); | |
2376 |
1/4✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
|
1 | SERIALIZE_LOOP_SUBBLOCK(element_mix_config); |
2377 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (ret) |
2378 | 1 | av_bprintf(bp, ":"); | |
2379 | 1 | av_bprintf(bp, "stg=%"PRId64, id); | |
2380 | } | ||
2381 |
3/4✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 1 times.
|
3 | SERIALIZE_LOOP(submix, layout, s, "|"); |
2382 | } | ||
2383 | 1 | break; | |
2384 | } | ||
2385 | ✗ | default: | |
2386 | ✗ | av_log(mux, AV_LOG_ERROR, "Unsupported mapped group type %d.\n", stg->type); | |
2387 | ✗ | ret = AVERROR(EINVAL); | |
2388 | ✗ | break; | |
2389 | } | ||
2390 | 2 | return 0; | |
2391 | } | ||
2392 | |||
2393 | 18 | static int of_parse_group_token(Muxer *mux, const char *token, char *ptr) | |
2394 | { | ||
2395 | 18 | AVFormatContext *oc = mux->fc; | |
2396 | AVStreamGroup *stg; | ||
2397 | 18 | AVDictionary *dict = NULL, *tmp = NULL; | |
2398 | 18 | char *mapped_string = NULL; | |
2399 | const AVDictionaryEntry *e; | ||
2400 | 18 | const AVOption opts[] = { | |
2401 | { "type", "Set group type", offsetof(AVStreamGroup, type), AV_OPT_TYPE_INT, | ||
2402 | { .i64 = 0 }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, .unit = "type" }, | ||
2403 | { "iamf_audio_element", NULL, 0, AV_OPT_TYPE_CONST, | ||
2404 | { .i64 = AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT }, .unit = "type" }, | ||
2405 | { "iamf_mix_presentation", NULL, 0, AV_OPT_TYPE_CONST, | ||
2406 | { .i64 = AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION }, .unit = "type" }, | ||
2407 | { NULL }, | ||
2408 | }; | ||
2409 | 18 | const AVClass class = { | |
2410 | .class_name = "StreamGroupType", | ||
2411 | .item_name = av_default_item_name, | ||
2412 | .option = opts, | ||
2413 | .version = LIBAVUTIL_VERSION_INT, | ||
2414 | }; | ||
2415 | 18 | const AVClass *pclass = &class; | |
2416 | int type, ret; | ||
2417 | |||
2418 | 18 | ret = av_dict_parse_string(&dict, token, "=", ":", AV_DICT_MULTIKEY); | |
2419 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
|
18 | if (ret < 0) { |
2420 | ✗ | av_log(mux, AV_LOG_ERROR, "Error parsing group specification %s\n", token); | |
2421 | ✗ | return ret; | |
2422 | } | ||
2423 | |||
2424 | 18 | av_dict_copy(&tmp, dict, 0); | |
2425 | 18 | e = av_dict_get(dict, "map", NULL, 0); | |
2426 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 16 times.
|
18 | if (e) { |
2427 | AVBPrint bp; | ||
2428 | |||
2429 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (ptr) { |
2430 | ✗ | av_log(mux, AV_LOG_ERROR, "Unexpected extra parameters when mapping a" | |
2431 | " stream group\n"); | ||
2432 | ✗ | ret = AVERROR(EINVAL); | |
2433 | ✗ | goto end; | |
2434 | } | ||
2435 | |||
2436 | 2 | av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC); | |
2437 | 2 | ret = of_map_group(mux, &tmp, &bp, e->value); | |
2438 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (ret < 0) { |
2439 | ✗ | av_bprint_finalize(&bp, NULL); | |
2440 | ✗ | goto end; | |
2441 | } | ||
2442 | |||
2443 | 2 | av_bprint_finalize(&bp, &mapped_string); | |
2444 | 2 | ptr = mapped_string; | |
2445 | } | ||
2446 | |||
2447 | // "type" is not a user settable AVOption in AVStreamGroup, so handle it here | ||
2448 | 18 | e = av_dict_get(tmp, "type", NULL, 0); | |
2449 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
|
18 | if (!e) { |
2450 | ✗ | av_log(mux, AV_LOG_ERROR, "No type specified for Stream Group in \"%s\"\n", token); | |
2451 | ✗ | ret = AVERROR(EINVAL); | |
2452 | ✗ | goto end; | |
2453 | } | ||
2454 | |||
2455 | 18 | ret = av_opt_eval_int(&pclass, opts, e->value, &type); | |
2456 |
2/4✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
|
18 | if (!ret && type == AV_STREAM_GROUP_PARAMS_NONE) |
2457 | ✗ | ret = AVERROR(EINVAL); | |
2458 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
|
18 | if (ret < 0) { |
2459 | ✗ | av_log(mux, AV_LOG_ERROR, "Invalid group type \"%s\"\n", e->value); | |
2460 | ✗ | goto end; | |
2461 | } | ||
2462 | |||
2463 | 18 | stg = avformat_stream_group_create(oc, type, &tmp); | |
2464 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
|
18 | if (!stg) { |
2465 | ✗ | ret = AVERROR(ENOMEM); | |
2466 | ✗ | goto end; | |
2467 | } | ||
2468 | |||
2469 | 18 | e = NULL; | |
2470 |
2/2✓ Branch 1 taken 40 times.
✓ Branch 2 taken 18 times.
|
58 | while (e = av_dict_get(dict, "st", e, 0)) { |
2471 | char *endptr; | ||
2472 | 40 | int64_t idx = strtoll(e->value, &endptr, 0); | |
2473 |
3/6✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 40 times.
|
40 | if (*endptr || idx < 0 || idx >= oc->nb_streams) { |
2474 | ✗ | av_log(mux, AV_LOG_ERROR, "Invalid stream index %"PRId64"\n", idx); | |
2475 | ✗ | ret = AVERROR(EINVAL); | |
2476 | ✗ | goto end; | |
2477 | } | ||
2478 | 40 | ret = avformat_stream_group_add_stream(stg, oc->streams[idx]); | |
2479 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
|
40 | if (ret < 0) |
2480 | ✗ | goto end; | |
2481 | } | ||
2482 |
2/2✓ Branch 1 taken 9 times.
✓ Branch 2 taken 18 times.
|
27 | while (e = av_dict_get(dict, "stg", e, 0)) { |
2483 | char *endptr; | ||
2484 | 9 | int64_t idx = strtoll(e->value, &endptr, 0); | |
2485 |
3/6✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 9 times.
|
9 | if (*endptr || idx < 0 || idx >= oc->nb_stream_groups - 1) { |
2486 | ✗ | av_log(mux, AV_LOG_ERROR, "Invalid stream group index %"PRId64"\n", idx); | |
2487 | ✗ | ret = AVERROR(EINVAL); | |
2488 | ✗ | goto end; | |
2489 | } | ||
2490 |
2/2✓ Branch 0 taken 40 times.
✓ Branch 1 taken 9 times.
|
49 | for (unsigned i = 0; i < oc->stream_groups[idx]->nb_streams; i++) { |
2491 | 40 | ret = avformat_stream_group_add_stream(stg, oc->stream_groups[idx]->streams[i]); | |
2492 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
|
40 | if (ret < 0) |
2493 | ✗ | goto end; | |
2494 | } | ||
2495 | } | ||
2496 | |||
2497 |
2/3✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
|
18 | switch(type) { |
2498 | 9 | case AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT: | |
2499 | 9 | ret = of_parse_iamf_audio_element_layers(mux, stg, ptr); | |
2500 | 9 | break; | |
2501 | 9 | case AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION: | |
2502 | 9 | ret = of_parse_iamf_submixes(mux, stg, ptr); | |
2503 | 9 | break; | |
2504 | ✗ | default: | |
2505 | ✗ | av_log(mux, AV_LOG_FATAL, "Unknown group type %d.\n", type); | |
2506 | ✗ | ret = AVERROR(EINVAL); | |
2507 | ✗ | break; | |
2508 | } | ||
2509 | |||
2510 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
|
18 | if (ret < 0) |
2511 | ✗ | goto end; | |
2512 | |||
2513 | // make sure that nothing but "st" and "stg" entries are left in the dict | ||
2514 | 18 | e = NULL; | |
2515 | 18 | av_dict_set(&tmp, "map", NULL, 0); | |
2516 | 18 | av_dict_set(&tmp, "type", NULL, 0); | |
2517 |
2/2✓ Branch 1 taken 18 times.
✓ Branch 2 taken 18 times.
|
36 | while (e = av_dict_iterate(tmp, e)) { |
2518 |
3/4✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
|
18 | if (!strcmp(e->key, "st") || !strcmp(e->key, "stg")) |
2519 | 18 | continue; | |
2520 | |||
2521 | ✗ | av_log(mux, AV_LOG_FATAL, "Unknown group key %s.\n", e->key); | |
2522 | ✗ | ret = AVERROR(EINVAL); | |
2523 | ✗ | goto end; | |
2524 | } | ||
2525 | |||
2526 | 18 | ret = 0; | |
2527 | 18 | end: | |
2528 | 18 | av_free(mapped_string); | |
2529 | 18 | av_dict_free(&dict); | |
2530 | 18 | av_dict_free(&tmp); | |
2531 | |||
2532 | 18 | return ret; | |
2533 | } | ||
2534 | |||
2535 | 6780 | static int of_add_groups(Muxer *mux, const OptionsContext *o) | |
2536 | { | ||
2537 | /* process manually set groups */ | ||
2538 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 6780 times.
|
6798 | for (int i = 0; i < o->stream_groups.nb_opt; i++) { |
2539 | const char *token; | ||
2540 | 18 | char *str, *ptr = NULL; | |
2541 | 18 | int ret = 0; | |
2542 | |||
2543 | 18 | str = av_strdup(o->stream_groups.opt[i].u.str); | |
2544 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
|
18 | if (!str) |
2545 | ✗ | return ret; | |
2546 | |||
2547 | 18 | token = av_strtok(str, ",", &ptr); | |
2548 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | if (token) { |
2549 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 2 times.
|
18 | if (ptr) |
2550 | 16 | ptr += strspn(ptr, " \n\t\r"); | |
2551 | 18 | ret = of_parse_group_token(mux, token, ptr); | |
2552 | } | ||
2553 | |||
2554 | 18 | av_free(str); | |
2555 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
|
18 | if (ret < 0) |
2556 | ✗ | return ret; | |
2557 | } | ||
2558 | |||
2559 | 6780 | return 0; | |
2560 | } | ||
2561 | |||
2562 | 6780 | static int of_add_programs(Muxer *mux, const OptionsContext *o) | |
2563 | { | ||
2564 | 6780 | AVFormatContext *oc = mux->fc; | |
2565 | /* process manually set programs */ | ||
2566 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6780 times.
|
6780 | for (int i = 0; i < o->program.nb_opt; i++) { |
2567 | ✗ | AVDictionary *dict = NULL; | |
2568 | const AVDictionaryEntry *e; | ||
2569 | AVProgram *program; | ||
2570 | ✗ | int ret, progid = i + 1; | |
2571 | |||
2572 | ✗ | ret = av_dict_parse_string(&dict, o->program.opt[i].u.str, "=", ":", | |
2573 | AV_DICT_MULTIKEY); | ||
2574 | ✗ | if (ret < 0) { | |
2575 | ✗ | av_log(mux, AV_LOG_ERROR, "Error parsing program specification %s\n", | |
2576 | ✗ | o->program.opt[i].u.str); | |
2577 | ✗ | return ret; | |
2578 | } | ||
2579 | |||
2580 | ✗ | e = av_dict_get(dict, "program_num", NULL, 0); | |
2581 | ✗ | if (e) { | |
2582 | ✗ | progid = strtol(e->value, NULL, 0); | |
2583 | ✗ | av_dict_set(&dict, e->key, NULL, 0); | |
2584 | } | ||
2585 | |||
2586 | ✗ | program = av_new_program(oc, progid); | |
2587 | ✗ | if (!program) { | |
2588 | ✗ | ret = AVERROR(ENOMEM); | |
2589 | ✗ | goto fail; | |
2590 | } | ||
2591 | |||
2592 | ✗ | e = av_dict_get(dict, "title", NULL, 0); | |
2593 | ✗ | if (e) { | |
2594 | ✗ | av_dict_set(&program->metadata, e->key, e->value, 0); | |
2595 | ✗ | av_dict_set(&dict, e->key, NULL, 0); | |
2596 | } | ||
2597 | |||
2598 | ✗ | e = NULL; | |
2599 | ✗ | while (e = av_dict_get(dict, "st", e, 0)) { | |
2600 | ✗ | int st_num = strtol(e->value, NULL, 0); | |
2601 | ✗ | av_program_add_stream_index(oc, progid, st_num); | |
2602 | } | ||
2603 | |||
2604 | // make sure that nothing but "st" entries are left in the dict | ||
2605 | ✗ | e = NULL; | |
2606 | ✗ | while (e = av_dict_iterate(dict, e)) { | |
2607 | ✗ | if (!strcmp(e->key, "st")) | |
2608 | ✗ | continue; | |
2609 | |||
2610 | ✗ | av_log(mux, AV_LOG_FATAL, "Unknown program key %s.\n", e->key); | |
2611 | ✗ | ret = AVERROR(EINVAL); | |
2612 | ✗ | goto fail; | |
2613 | } | ||
2614 | |||
2615 | ✗ | fail: | |
2616 | ✗ | av_dict_free(&dict); | |
2617 | ✗ | if (ret < 0) | |
2618 | ✗ | return ret; | |
2619 | } | ||
2620 | |||
2621 | 6780 | return 0; | |
2622 | } | ||
2623 | |||
2624 | /** | ||
2625 | * Parse a metadata specifier passed as 'arg' parameter. | ||
2626 | * @param arg metadata string to parse | ||
2627 | * @param type metadata type is written here -- g(lobal)/s(tream)/c(hapter)/p(rogram) | ||
2628 | * @param index for type c/p, chapter/program index is written here | ||
2629 | * @param stream_spec for type s, the stream specifier is written here | ||
2630 | */ | ||
2631 | 234 | static int parse_meta_type(void *logctx, const char *arg, | |
2632 | char *type, int *index, const char **stream_spec) | ||
2633 | { | ||
2634 |
2/2✓ Branch 0 taken 71 times.
✓ Branch 1 taken 163 times.
|
234 | if (*arg) { |
2635 | 71 | *type = *arg; | |
2636 |
3/4✓ Branch 0 taken 21 times.
✓ Branch 1 taken 46 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
71 | switch (*arg) { |
2637 | 21 | case 'g': | |
2638 | 21 | break; | |
2639 | 46 | case 's': | |
2640 |
2/4✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 46 times.
|
46 | if (*(++arg) && *arg != ':') { |
2641 | ✗ | av_log(logctx, AV_LOG_FATAL, "Invalid metadata specifier %s.\n", arg); | |
2642 | ✗ | return AVERROR(EINVAL); | |
2643 | } | ||
2644 |
1/2✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
|
46 | *stream_spec = *arg == ':' ? arg + 1 : ""; |
2645 | 46 | break; | |
2646 | 4 | case 'c': | |
2647 | case 'p': | ||
2648 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
|
4 | if (*(++arg) == ':') |
2649 | 3 | *index = strtol(++arg, NULL, 0); | |
2650 | 4 | break; | |
2651 | ✗ | default: | |
2652 | ✗ | av_log(logctx, AV_LOG_FATAL, "Invalid metadata type %c.\n", *arg); | |
2653 | ✗ | return AVERROR(EINVAL); | |
2654 | } | ||
2655 | } else | ||
2656 | 163 | *type = 'g'; | |
2657 | |||
2658 | 234 | return 0; | |
2659 | } | ||
2660 | |||
2661 | 6780 | static int of_add_metadata(OutputFile *of, AVFormatContext *oc, | |
2662 | const OptionsContext *o) | ||
2663 | { | ||
2664 |
2/2✓ Branch 0 taken 220 times.
✓ Branch 1 taken 6780 times.
|
7000 | for (int i = 0; i < o->metadata.nb_opt; i++) { |
2665 | AVDictionary **m; | ||
2666 | char type, *val; | ||
2667 | const char *stream_spec; | ||
2668 | 220 | int index = 0, ret = 0; | |
2669 | |||
2670 | 220 | val = strchr(o->metadata.opt[i].u.str, '='); | |
2671 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 220 times.
|
220 | if (!val) { |
2672 | ✗ | av_log(of, AV_LOG_FATAL, "No '=' character in metadata string %s.\n", | |
2673 | ✗ | o->metadata.opt[i].u.str); | |
2674 | ✗ | return AVERROR(EINVAL); | |
2675 | } | ||
2676 | 220 | *val++ = 0; | |
2677 | |||
2678 | 220 | ret = parse_meta_type(of, o->metadata.opt[i].specifier, &type, &index, &stream_spec); | |
2679 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 220 times.
|
220 | if (ret < 0) |
2680 | ✗ | return ret; | |
2681 | |||
2682 |
2/2✓ Branch 0 taken 41 times.
✓ Branch 1 taken 179 times.
|
220 | if (type == 's') { |
2683 |
2/2✓ Branch 0 taken 219 times.
✓ Branch 1 taken 41 times.
|
260 | for (int j = 0; j < oc->nb_streams; j++) { |
2684 |
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) { |
2685 |
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); |
2686 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 178 times.
|
178 | } else if (ret < 0) |
2687 | ✗ | return ret; | |
2688 | } | ||
2689 | } else { | ||
2690 |
2/4✓ Branch 0 taken 175 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
179 | switch (type) { |
2691 | 175 | case 'g': | |
2692 | 175 | m = &oc->metadata; | |
2693 | 175 | break; | |
2694 | 4 | case 'c': | |
2695 |
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) { |
2696 | ✗ | av_log(of, AV_LOG_FATAL, "Invalid chapter index %d in metadata specifier.\n", index); | |
2697 | ✗ | return AVERROR(EINVAL); | |
2698 | } | ||
2699 | 4 | m = &oc->chapters[index]->metadata; | |
2700 | 4 | break; | |
2701 | ✗ | case 'p': | |
2702 | ✗ | if (index < 0 || index >= oc->nb_programs) { | |
2703 | ✗ | av_log(of, AV_LOG_FATAL, "Invalid program index %d in metadata specifier.\n", index); | |
2704 | ✗ | return AVERROR(EINVAL); | |
2705 | } | ||
2706 | ✗ | m = &oc->programs[index]->metadata; | |
2707 | ✗ | break; | |
2708 | ✗ | default: | |
2709 | ✗ | av_log(of, AV_LOG_FATAL, "Invalid metadata specifier %s.\n", o->metadata.opt[i].specifier); | |
2710 | ✗ | return AVERROR(EINVAL); | |
2711 | } | ||
2712 |
2/2✓ Branch 0 taken 178 times.
✓ Branch 1 taken 1 times.
|
179 | av_dict_set(m, o->metadata.opt[i].u.str, *val ? val : NULL, 0); |
2713 | } | ||
2714 | } | ||
2715 | |||
2716 | 6780 | return 0; | |
2717 | } | ||
2718 | |||
2719 | 19 | static int copy_chapters(InputFile *ifile, OutputFile *ofile, AVFormatContext *os, | |
2720 | int copy_metadata) | ||
2721 | { | ||
2722 | 19 | AVFormatContext *is = ifile->ctx; | |
2723 | AVChapter **tmp; | ||
2724 | |||
2725 | 19 | tmp = av_realloc_f(os->chapters, is->nb_chapters + os->nb_chapters, sizeof(*os->chapters)); | |
2726 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
|
19 | if (!tmp) |
2727 | ✗ | return AVERROR(ENOMEM); | |
2728 | 19 | os->chapters = tmp; | |
2729 | |||
2730 |
2/2✓ Branch 0 taken 37 times.
✓ Branch 1 taken 16 times.
|
53 | for (int i = 0; i < is->nb_chapters; i++) { |
2731 | 37 | AVChapter *in_ch = is->chapters[i], *out_ch; | |
2732 |
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; |
2733 | 37 | int64_t ts_off = av_rescale_q(start_time - ifile->ts_offset, | |
2734 | 37 | AV_TIME_BASE_Q, in_ch->time_base); | |
2735 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 32 times.
|
37 | int64_t rt = (ofile->recording_time == INT64_MAX) ? INT64_MAX : |
2736 | 5 | av_rescale_q(ofile->recording_time, AV_TIME_BASE_Q, in_ch->time_base); | |
2737 | |||
2738 | |||
2739 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
|
37 | if (in_ch->end < ts_off) |
2740 | ✗ | continue; | |
2741 |
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) |
2742 | 3 | break; | |
2743 | |||
2744 | 34 | out_ch = av_mallocz(sizeof(AVChapter)); | |
2745 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
|
34 | if (!out_ch) |
2746 | ✗ | return AVERROR(ENOMEM); | |
2747 | |||
2748 | 34 | out_ch->id = in_ch->id; | |
2749 | 34 | out_ch->time_base = in_ch->time_base; | |
2750 | 34 | out_ch->start = FFMAX(0, in_ch->start - ts_off); | |
2751 | 34 | out_ch->end = FFMIN(rt, in_ch->end - ts_off); | |
2752 | |||
2753 |
1/2✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
|
34 | if (copy_metadata) |
2754 | 34 | av_dict_copy(&out_ch->metadata, in_ch->metadata, 0); | |
2755 | |||
2756 | 34 | os->chapters[os->nb_chapters++] = out_ch; | |
2757 | } | ||
2758 | 19 | return 0; | |
2759 | } | ||
2760 | |||
2761 | 7 | static int copy_metadata(Muxer *mux, AVFormatContext *ic, | |
2762 | const char *outspec, const char *inspec, | ||
2763 | int *metadata_global_manual, int *metadata_streams_manual, | ||
2764 | int *metadata_chapters_manual) | ||
2765 | { | ||
2766 | 7 | AVFormatContext *oc = mux->fc; | |
2767 | 7 | AVDictionary **meta_in = NULL; | |
2768 | 7 | AVDictionary **meta_out = NULL; | |
2769 | 7 | int i, ret = 0; | |
2770 | char type_in, type_out; | ||
2771 | 7 | const char *istream_spec = NULL, *ostream_spec = NULL; | |
2772 | 7 | int idx_in = 0, idx_out = 0; | |
2773 | |||
2774 | 7 | ret = parse_meta_type(mux, inspec, &type_in, &idx_in, &istream_spec); | |
2775 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | if (ret >= 0) |
2776 | 7 | ret = parse_meta_type(mux, outspec, &type_out, &idx_out, &ostream_spec); | |
2777 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (ret < 0) |
2778 | ✗ | return ret; | |
2779 | |||
2780 |
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)) |
2781 | 5 | *metadata_global_manual = 1; | |
2782 |
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)) |
2783 | 3 | *metadata_streams_manual = 1; | |
2784 |
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)) |
2785 | ✗ | *metadata_chapters_manual = 1; | |
2786 | |||
2787 | /* ic is NULL when just disabling automatic mappings */ | ||
2788 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5 times.
|
7 | if (!ic) |
2789 | 2 | return 0; | |
2790 | |||
2791 | #define METADATA_CHECK_INDEX(index, nb_elems, desc)\ | ||
2792 | if ((index) < 0 || (index) >= (nb_elems)) {\ | ||
2793 | av_log(mux, AV_LOG_FATAL, "Invalid %s index %d while processing metadata maps.\n",\ | ||
2794 | (desc), (index));\ | ||
2795 | return AVERROR(EINVAL);\ | ||
2796 | } | ||
2797 | |||
2798 | #define SET_DICT(type, meta, context, index)\ | ||
2799 | switch (type) {\ | ||
2800 | case 'g':\ | ||
2801 | meta = &context->metadata;\ | ||
2802 | break;\ | ||
2803 | case 'c':\ | ||
2804 | METADATA_CHECK_INDEX(index, context->nb_chapters, "chapter")\ | ||
2805 | meta = &context->chapters[index]->metadata;\ | ||
2806 | break;\ | ||
2807 | case 'p':\ | ||
2808 | METADATA_CHECK_INDEX(index, context->nb_programs, "program")\ | ||
2809 | meta = &context->programs[index]->metadata;\ | ||
2810 | break;\ | ||
2811 | case 's':\ | ||
2812 | break; /* handled separately below */ \ | ||
2813 | default: av_assert0(0);\ | ||
2814 | }\ | ||
2815 | |||
2816 |
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); |
2817 |
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); |
2818 | |||
2819 | /* for input streams choose first matching stream */ | ||
2820 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
|
5 | if (type_in == 's') { |
2821 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | for (i = 0; i < ic->nb_streams; i++) { |
2822 |
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) { |
2823 | 2 | meta_in = &ic->streams[i]->metadata; | |
2824 | 2 | break; | |
2825 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | } else if (ret < 0) |
2826 | ✗ | return ret; | |
2827 | } | ||
2828 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (!meta_in) { |
2829 | ✗ | av_log(mux, AV_LOG_FATAL, "Stream specifier %s does not match any streams.\n", istream_spec); | |
2830 | ✗ | return AVERROR(EINVAL); | |
2831 | } | ||
2832 | } | ||
2833 | |||
2834 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
|
5 | if (type_out == 's') { |
2835 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3 times.
|
11 | for (i = 0; i < oc->nb_streams; i++) { |
2836 |
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) { |
2837 | 3 | meta_out = &oc->streams[i]->metadata; | |
2838 | 3 | av_dict_copy(meta_out, *meta_in, AV_DICT_DONT_OVERWRITE); | |
2839 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | } else if (ret < 0) |
2840 | ✗ | return ret; | |
2841 | } | ||
2842 | } else | ||
2843 | 2 | av_dict_copy(meta_out, *meta_in, AV_DICT_DONT_OVERWRITE); | |
2844 | |||
2845 | 5 | return 0; | |
2846 | } | ||
2847 | |||
2848 | 6780 | static int copy_meta(Muxer *mux, const OptionsContext *o) | |
2849 | { | ||
2850 | 6780 | OutputFile *of = &mux->of; | |
2851 | 6780 | AVFormatContext *oc = mux->fc; | |
2852 | 6780 | int chapters_input_file = o->chapters_input_file; | |
2853 | 6780 | int metadata_global_manual = 0; | |
2854 | 6780 | int metadata_streams_manual = 0; | |
2855 | 6780 | int metadata_chapters_manual = 0; | |
2856 | int ret; | ||
2857 | |||
2858 | /* copy metadata */ | ||
2859 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 6780 times.
|
6787 | for (int i = 0; i < o->metadata_map.nb_opt; i++) { |
2860 | char *p; | ||
2861 | 7 | int in_file_index = strtol(o->metadata_map.opt[i].u.str, &p, 0); | |
2862 | |||
2863 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (in_file_index >= nb_input_files) { |
2864 | ✗ | av_log(mux, AV_LOG_FATAL, "Invalid input file index %d while " | |
2865 | "processing metadata maps\n", in_file_index); | ||
2866 | ✗ | return AVERROR(EINVAL); | |
2867 | } | ||
2868 | 10 | ret = copy_metadata(mux, | |
2869 | 5 | in_file_index >= 0 ? input_files[in_file_index]->ctx : NULL, | |
2870 |
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, |
2871 | &metadata_global_manual, &metadata_streams_manual, | ||
2872 | &metadata_chapters_manual); | ||
2873 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (ret < 0) |
2874 | ✗ | return ret; | |
2875 | } | ||
2876 | |||
2877 | /* copy chapters */ | ||
2878 |
1/2✓ Branch 0 taken 6780 times.
✗ Branch 1 not taken.
|
6780 | if (chapters_input_file >= nb_input_files) { |
2879 |
1/2✓ Branch 0 taken 6780 times.
✗ Branch 1 not taken.
|
6780 | if (chapters_input_file == INT_MAX) { |
2880 | /* copy chapters from the first input file that has them*/ | ||
2881 | 6780 | chapters_input_file = -1; | |
2882 |
2/2✓ Branch 0 taken 6811 times.
✓ Branch 1 taken 6761 times.
|
13572 | for (int i = 0; i < nb_input_files; i++) |
2883 |
2/2✓ Branch 0 taken 19 times.
✓ Branch 1 taken 6792 times.
|
6811 | if (input_files[i]->ctx->nb_chapters) { |
2884 | 19 | chapters_input_file = i; | |
2885 | 19 | break; | |
2886 | } | ||
2887 | } else { | ||
2888 | ✗ | av_log(mux, AV_LOG_FATAL, "Invalid input file index %d in chapter mapping.\n", | |
2889 | chapters_input_file); | ||
2890 | ✗ | return AVERROR(EINVAL); | |
2891 | } | ||
2892 | } | ||
2893 |
2/2✓ Branch 0 taken 19 times.
✓ Branch 1 taken 6761 times.
|
6780 | if (chapters_input_file >= 0) |
2894 | 19 | copy_chapters(input_files[chapters_input_file], of, oc, | |
2895 | !metadata_chapters_manual); | ||
2896 | |||
2897 | /* copy global metadata by default */ | ||
2898 |
4/4✓ Branch 0 taken 6776 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 6721 times.
✓ Branch 3 taken 55 times.
|
6780 | if (!metadata_global_manual && nb_input_files){ |
2899 | 6721 | av_dict_copy(&oc->metadata, input_files[0]->ctx->metadata, | |
2900 | AV_DICT_DONT_OVERWRITE); | ||
2901 |
2/2✓ Branch 0 taken 180 times.
✓ Branch 1 taken 6541 times.
|
6721 | if (of->recording_time != INT64_MAX) |
2902 | 180 | av_dict_set(&oc->metadata, "duration", NULL, 0); | |
2903 | 6721 | av_dict_set(&oc->metadata, "creation_time", NULL, 0); | |
2904 | 6721 | av_dict_set(&oc->metadata, "company_name", NULL, 0); | |
2905 | 6721 | av_dict_set(&oc->metadata, "product_name", NULL, 0); | |
2906 | 6721 | av_dict_set(&oc->metadata, "product_version", NULL, 0); | |
2907 | } | ||
2908 |
2/2✓ Branch 0 taken 6778 times.
✓ Branch 1 taken 2 times.
|
6780 | if (!metadata_streams_manual) |
2909 |
2/2✓ Branch 0 taken 7128 times.
✓ Branch 1 taken 6778 times.
|
13906 | for (int i = 0; i < of->nb_streams; i++) { |
2910 | 7128 | OutputStream *ost = of->streams[i]; | |
2911 | |||
2912 |
2/2✓ Branch 0 taken 169 times.
✓ Branch 1 taken 6959 times.
|
7128 | if (!ost->ist) /* this is true e.g. for attached files */ |
2913 | 169 | continue; | |
2914 | 6959 | av_dict_copy(&ost->st->metadata, ost->ist->st->metadata, AV_DICT_DONT_OVERWRITE); | |
2915 |
2/2✓ Branch 0 taken 6315 times.
✓ Branch 1 taken 644 times.
|
6959 | if (ost->enc_ctx) { |
2916 | 6315 | av_dict_set(&ost->st->metadata, "encoder", NULL, 0); | |
2917 | } | ||
2918 | } | ||
2919 | |||
2920 | 6780 | return 0; | |
2921 | } | ||
2922 | |||
2923 | 6780 | static int set_dispositions(Muxer *mux, const OptionsContext *o) | |
2924 | { | ||
2925 | 6780 | OutputFile *of = &mux->of; | |
2926 | 6780 | AVFormatContext *ctx = mux->fc; | |
2927 | |||
2928 | // indexed by type+1, because AVMEDIA_TYPE_UNKNOWN=-1 | ||
2929 | 6780 | int nb_streams[AVMEDIA_TYPE_NB + 1] = { 0 }; | |
2930 | 6780 | int have_default[AVMEDIA_TYPE_NB + 1] = { 0 }; | |
2931 | 6780 | int have_manual = 0; | |
2932 | 6780 | int ret = 0; | |
2933 | |||
2934 | const char **dispositions; | ||
2935 | |||
2936 | 6780 | dispositions = av_calloc(ctx->nb_streams, sizeof(*dispositions)); | |
2937 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6780 times.
|
6780 | if (!dispositions) |
2938 | ✗ | return AVERROR(ENOMEM); | |
2939 | |||
2940 | // first, copy the input dispositions | ||
2941 |
2/2✓ Branch 0 taken 7133 times.
✓ Branch 1 taken 6780 times.
|
13913 | for (int i = 0; i < ctx->nb_streams; i++) { |
2942 | 7133 | OutputStream *ost = of->streams[i]; | |
2943 | |||
2944 | 7133 | nb_streams[ost->type + 1]++; | |
2945 | |||
2946 |
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 7133 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7133 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.
|
7192 | MATCH_PER_STREAM_OPT_CLEAN(disposition, str, dispositions[i], ctx, ost->st, goto finish); |
2947 | |||
2948 | 7133 | have_manual |= !!dispositions[i]; | |
2949 | |||
2950 |
2/2✓ Branch 0 taken 6964 times.
✓ Branch 1 taken 169 times.
|
7133 | if (ost->ist) { |
2951 | 6964 | ost->st->disposition = ost->ist->st->disposition; | |
2952 | |||
2953 |
2/2✓ Branch 0 taken 777 times.
✓ Branch 1 taken 6187 times.
|
6964 | if (ost->st->disposition & AV_DISPOSITION_DEFAULT) |
2954 | 777 | have_default[ost->type + 1] = 1; | |
2955 | } | ||
2956 | } | ||
2957 | |||
2958 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 6772 times.
|
6780 | if (have_manual) { |
2959 | // process manually set dispositions - they override the above copy | ||
2960 |
2/2✓ Branch 0 taken 23 times.
✓ Branch 1 taken 8 times.
|
31 | for (int i = 0; i < ctx->nb_streams; i++) { |
2961 | 23 | OutputStream *ost = of->streams[i]; | |
2962 | 23 | const char *disp = dispositions[i]; | |
2963 | |||
2964 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 16 times.
|
23 | if (!disp) |
2965 | 7 | continue; | |
2966 | |||
2967 | 16 | ret = av_opt_set(ost->st, "disposition", disp, 0); | |
2968 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
|
16 | if (ret < 0) |
2969 | ✗ | goto finish; | |
2970 | } | ||
2971 | } else { | ||
2972 | // For each media type with more than one stream, find a suitable stream to | ||
2973 | // mark as default, unless one is already marked default. | ||
2974 | // "Suitable" means the first of that type, skipping attached pictures. | ||
2975 |
2/2✓ Branch 0 taken 7110 times.
✓ Branch 1 taken 6772 times.
|
13882 | for (int i = 0; i < ctx->nb_streams; i++) { |
2976 | 7110 | OutputStream *ost = of->streams[i]; | |
2977 | 7110 | enum AVMediaType type = ost->type; | |
2978 | |||
2979 |
4/4✓ Branch 0 taken 238 times.
✓ Branch 1 taken 6872 times.
✓ Branch 2 taken 62 times.
✓ Branch 3 taken 176 times.
|
7110 | if (nb_streams[type + 1] < 2 || have_default[type + 1] || |
2980 |
2/2✓ Branch 0 taken 32 times.
✓ Branch 1 taken 30 times.
|
62 | ost->st->disposition & AV_DISPOSITION_ATTACHED_PIC) |
2981 | 7080 | continue; | |
2982 | |||
2983 | 30 | ost->st->disposition |= AV_DISPOSITION_DEFAULT; | |
2984 | 30 | have_default[type + 1] = 1; | |
2985 | } | ||
2986 | } | ||
2987 | |||
2988 | 6772 | finish: | |
2989 | 6780 | av_freep(&dispositions); | |
2990 | |||
2991 | 6780 | return ret; | |
2992 | } | ||
2993 | |||
2994 | const char *const forced_keyframes_const_names[] = { | ||
2995 | "n", | ||
2996 | "n_forced", | ||
2997 | "prev_forced_n", | ||
2998 | "prev_forced_t", | ||
2999 | "t", | ||
3000 | NULL | ||
3001 | }; | ||
3002 | |||
3003 | 1 | static int compare_int64(const void *a, const void *b) | |
3004 | { | ||
3005 | 1 | return FFDIFFSIGN(*(const int64_t *)a, *(const int64_t *)b); | |
3006 | } | ||
3007 | |||
3008 | 1 | static int parse_forced_key_frames(void *log, KeyframeForceCtx *kf, | |
3009 | const Muxer *mux, const char *spec) | ||
3010 | { | ||
3011 | const char *p; | ||
3012 | 1 | int n = 1, i, ret, size, index = 0; | |
3013 | int64_t t, *pts; | ||
3014 | |||
3015 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1 times.
|
14 | for (p = spec; *p; p++) |
3016 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12 times.
|
13 | if (*p == ',') |
3017 | 1 | n++; | |
3018 | 1 | size = n; | |
3019 | 1 | pts = av_malloc_array(size, sizeof(*pts)); | |
3020 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!pts) |
3021 | ✗ | return AVERROR(ENOMEM); | |
3022 | |||
3023 | 1 | p = spec; | |
3024 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
3 | for (i = 0; i < n; i++) { |
3025 | 2 | char *next = strchr(p, ','); | |
3026 | |||
3027 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | if (next) |
3028 | 1 | *next++ = 0; | |
3029 | |||
3030 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (strstr(p, "chapters") == p) { |
3031 | ✗ | AVChapter * const *ch = mux->fc->chapters; | |
3032 | ✗ | unsigned int nb_ch = mux->fc->nb_chapters; | |
3033 | int j; | ||
3034 | |||
3035 | ✗ | if (nb_ch > INT_MAX - size) { | |
3036 | ✗ | ret = AVERROR(ERANGE); | |
3037 | ✗ | goto fail; | |
3038 | } | ||
3039 | ✗ | size += nb_ch - 1; | |
3040 | ✗ | pts = av_realloc_f(pts, size, sizeof(*pts)); | |
3041 | ✗ | if (!pts) | |
3042 | ✗ | return AVERROR(ENOMEM); | |
3043 | |||
3044 | ✗ | if (p[8]) { | |
3045 | ✗ | ret = av_parse_time(&t, p + 8, 1); | |
3046 | ✗ | if (ret < 0) { | |
3047 | ✗ | av_log(log, AV_LOG_ERROR, | |
3048 | "Invalid chapter time offset: %s\n", p + 8); | ||
3049 | ✗ | goto fail; | |
3050 | } | ||
3051 | } else | ||
3052 | ✗ | t = 0; | |
3053 | |||
3054 | ✗ | for (j = 0; j < nb_ch; j++) { | |
3055 | ✗ | const AVChapter *c = ch[j]; | |
3056 | av_assert1(index < size); | ||
3057 | ✗ | pts[index++] = av_rescale_q(c->start, c->time_base, | |
3058 | ✗ | AV_TIME_BASE_Q) + t; | |
3059 | } | ||
3060 | |||
3061 | } else { | ||
3062 | av_assert1(index < size); | ||
3063 | 2 | ret = av_parse_time(&t, p, 1); | |
3064 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (ret < 0) { |
3065 | ✗ | av_log(log, AV_LOG_ERROR, "Invalid keyframe time: %s\n", p); | |
3066 | ✗ | goto fail; | |
3067 | } | ||
3068 | |||
3069 | 2 | pts[index++] = t; | |
3070 | } | ||
3071 | |||
3072 | 2 | p = next; | |
3073 | } | ||
3074 | |||
3075 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | av_assert0(index == size); |
3076 | 1 | qsort(pts, size, sizeof(*pts), compare_int64); | |
3077 | 1 | kf->nb_pts = size; | |
3078 | 1 | kf->pts = pts; | |
3079 | |||
3080 | 1 | return 0; | |
3081 | ✗ | fail: | |
3082 | ✗ | av_freep(&pts); | |
3083 | ✗ | return ret; | |
3084 | } | ||
3085 | |||
3086 | 6780 | static int process_forced_keyframes(Muxer *mux, const OptionsContext *o) | |
3087 | { | ||
3088 |
2/2✓ Branch 0 taken 7133 times.
✓ Branch 1 taken 6780 times.
|
13913 | for (int i = 0; i < mux->of.nb_streams; i++) { |
3089 | 7133 | OutputStream *ost = mux->of.streams[i]; | |
3090 | 7133 | const char *forced_keyframes = NULL; | |
3091 | |||
3092 |
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 7133 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7133 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.
|
7137 | MATCH_PER_STREAM_OPT(forced_key_frames, str, forced_keyframes, mux->fc, ost->st); |
3093 | |||
3094 |
4/4✓ Branch 0 taken 5539 times.
✓ Branch 1 taken 1594 times.
✓ Branch 2 taken 5198 times.
✓ Branch 3 taken 4 times.
|
12335 | if (!(ost->type == AVMEDIA_TYPE_VIDEO && |
3095 |
2/2✓ Branch 0 taken 5202 times.
✓ Branch 1 taken 337 times.
|
5539 | ost->enc_ctx && forced_keyframes)) |
3096 | 7129 | continue; | |
3097 | |||
3098 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (!strncmp(forced_keyframes, "expr:", 5)) { |
3099 | ✗ | int ret = av_expr_parse(&ost->kf.pexpr, forced_keyframes + 5, | |
3100 | forced_keyframes_const_names, NULL, NULL, NULL, NULL, 0, NULL); | ||
3101 | ✗ | if (ret < 0) { | |
3102 | ✗ | av_log(ost, AV_LOG_ERROR, | |
3103 | "Invalid force_key_frames expression '%s'\n", forced_keyframes + 5); | ||
3104 | ✗ | return ret; | |
3105 | } | ||
3106 | ✗ | ost->kf.expr_const_values[FKF_N] = 0; | |
3107 | ✗ | ost->kf.expr_const_values[FKF_N_FORCED] = 0; | |
3108 | ✗ | ost->kf.expr_const_values[FKF_PREV_FORCED_N] = NAN; | |
3109 | ✗ | ost->kf.expr_const_values[FKF_PREV_FORCED_T] = NAN; | |
3110 | |||
3111 | // Don't parse the 'forced_keyframes' in case of 'keep-source-keyframes', | ||
3112 | // parse it only for static kf timings | ||
3113 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
|
4 | } else if (!strcmp(forced_keyframes, "source")) { |
3114 | 3 | ost->kf.type = KF_FORCE_SOURCE; | |
3115 | #if FFMPEG_OPT_FORCE_KF_SOURCE_NO_DROP | ||
3116 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | } else if (!strcmp(forced_keyframes, "source_no_drop")) { |
3117 | ✗ | av_log(ost, AV_LOG_WARNING, "The 'source_no_drop' value for " | |
3118 | "-force_key_frames is deprecated, use just 'source'\n"); | ||
3119 | ✗ | ost->kf.type = KF_FORCE_SOURCE; | |
3120 | #endif | ||
3121 | } else { | ||
3122 | 1 | int ret = parse_forced_key_frames(ost, &ost->kf, mux, forced_keyframes); | |
3123 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (ret < 0) |
3124 | ✗ | return ret; | |
3125 | } | ||
3126 | } | ||
3127 | |||
3128 | 6780 | return 0; | |
3129 | } | ||
3130 | |||
3131 | 7158 | static const char *output_file_item_name(void *obj) | |
3132 | { | ||
3133 | 7158 | const Muxer *mux = obj; | |
3134 | |||
3135 | 7158 | return mux->log_name; | |
3136 | } | ||
3137 | |||
3138 | static const AVClass output_file_class = { | ||
3139 | .class_name = "OutputFile", | ||
3140 | .version = LIBAVUTIL_VERSION_INT, | ||
3141 | .item_name = output_file_item_name, | ||
3142 | .category = AV_CLASS_CATEGORY_MUXER, | ||
3143 | }; | ||
3144 | |||
3145 | 6780 | static Muxer *mux_alloc(void) | |
3146 | { | ||
3147 | 6780 | Muxer *mux = allocate_array_elem(&output_files, sizeof(*mux), &nb_output_files); | |
3148 | |||
3149 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6780 times.
|
6780 | if (!mux) |
3150 | ✗ | return NULL; | |
3151 | |||
3152 | 6780 | mux->of.class = &output_file_class; | |
3153 | 6780 | mux->of.index = nb_output_files - 1; | |
3154 | |||
3155 | 6780 | snprintf(mux->log_name, sizeof(mux->log_name), "out#%d", mux->of.index); | |
3156 | |||
3157 | 6780 | return mux; | |
3158 | } | ||
3159 | |||
3160 | 6780 | int of_open(const OptionsContext *o, const char *filename, Scheduler *sch) | |
3161 | { | ||
3162 | Muxer *mux; | ||
3163 | AVFormatContext *oc; | ||
3164 | int err; | ||
3165 | OutputFile *of; | ||
3166 | |||
3167 | 6780 | int64_t recording_time = o->recording_time; | |
3168 | 6780 | int64_t stop_time = o->stop_time; | |
3169 | |||
3170 | 6780 | mux = mux_alloc(); | |
3171 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6780 times.
|
6780 | if (!mux) |
3172 | ✗ | return AVERROR(ENOMEM); | |
3173 | |||
3174 | 6780 | of = &mux->of; | |
3175 | |||
3176 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 6780 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
6780 | if (stop_time != INT64_MAX && recording_time != INT64_MAX) { |
3177 | ✗ | stop_time = INT64_MAX; | |
3178 | ✗ | av_log(mux, AV_LOG_WARNING, "-t and -to cannot be used together; using -t.\n"); | |
3179 | } | ||
3180 | |||
3181 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 6780 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
6780 | if (stop_time != INT64_MAX && recording_time == INT64_MAX) { |
3182 | ✗ | int64_t start_time = o->start_time == AV_NOPTS_VALUE ? 0 : o->start_time; | |
3183 | ✗ | if (stop_time <= start_time) { | |
3184 | ✗ | av_log(mux, AV_LOG_ERROR, "-to value smaller than -ss; aborting.\n"); | |
3185 | ✗ | return AVERROR(EINVAL); | |
3186 | } else { | ||
3187 | ✗ | recording_time = stop_time - start_time; | |
3188 | } | ||
3189 | } | ||
3190 | |||
3191 | 6780 | of->recording_time = recording_time; | |
3192 | 6780 | of->start_time = o->start_time; | |
3193 | |||
3194 | 6780 | mux->limit_filesize = o->limit_filesize; | |
3195 | 6780 | av_dict_copy(&mux->opts, o->g->format_opts, 0); | |
3196 | |||
3197 |
2/2✓ Branch 0 taken 2605 times.
✓ Branch 1 taken 4175 times.
|
6780 | if (!strcmp(filename, "-")) |
3198 | 2605 | filename = "pipe:"; | |
3199 | |||
3200 | 6780 | err = avformat_alloc_output_context2(&oc, NULL, o->format, filename); | |
3201 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6780 times.
|
6780 | if (!oc) { |
3202 | ✗ | av_log(mux, AV_LOG_FATAL, "Error initializing the muxer for %s: %s\n", | |
3203 | ✗ | filename, av_err2str(err)); | |
3204 | ✗ | return err; | |
3205 | } | ||
3206 | 6780 | mux->fc = oc; | |
3207 | |||
3208 | 6780 | av_strlcat(mux->log_name, "/", sizeof(mux->log_name)); | |
3209 | 6780 | av_strlcat(mux->log_name, oc->oformat->name, sizeof(mux->log_name)); | |
3210 | |||
3211 | |||
3212 |
2/2✓ Branch 0 taken 186 times.
✓ Branch 1 taken 6594 times.
|
6780 | if (recording_time != INT64_MAX) |
3213 | 186 | oc->duration = recording_time; | |
3214 | |||
3215 | 6780 | oc->interrupt_callback = int_cb; | |
3216 | |||
3217 |
2/2✓ Branch 0 taken 1798 times.
✓ Branch 1 taken 4982 times.
|
6780 | if (o->bitexact) { |
3218 | 1798 | oc->flags |= AVFMT_FLAG_BITEXACT; | |
3219 | 1798 | of->bitexact = 1; | |
3220 | } else { | ||
3221 | 4982 | of->bitexact = check_opt_bitexact(oc, mux->opts, "fflags", | |
3222 | AVFMT_FLAG_BITEXACT); | ||
3223 | } | ||
3224 | |||
3225 | 6780 | err = sch_add_mux(sch, muxer_thread, mux_check_init, mux, | |
3226 | 6780 | !strcmp(oc->oformat->name, "rtp"), o->thread_queue_size); | |
3227 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6780 times.
|
6780 | if (err < 0) |
3228 | ✗ | return err; | |
3229 | 6780 | mux->sch = sch; | |
3230 | 6780 | mux->sch_idx = err; | |
3231 | |||
3232 | /* create all output streams for this file */ | ||
3233 | 6780 | err = create_streams(mux, o); | |
3234 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6780 times.
|
6780 | if (err < 0) |
3235 | ✗ | return err; | |
3236 | |||
3237 | /* check if all codec options have been used */ | ||
3238 | 6780 | err = check_avoptions_used(o->g->codec_opts, mux->enc_opts_used, mux, 0); | |
3239 | 6780 | av_dict_free(&mux->enc_opts_used); | |
3240 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6780 times.
|
6780 | if (err < 0) |
3241 | ✗ | return err; | |
3242 | |||
3243 | /* check filename in case of an image number is expected */ | ||
3244 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 6780 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
6780 | if (oc->oformat->flags & AVFMT_NEEDNUMBER && !av_filename_number_test(oc->url)) { |
3245 | ✗ | av_log(mux, AV_LOG_FATAL, | |
3246 | "Output filename '%s' does not contain a numeric pattern like " | ||
3247 | "'%%d', which is required by output format '%s'.\n", | ||
3248 | ✗ | oc->url, oc->oformat->name); | |
3249 | ✗ | return AVERROR(EINVAL); | |
3250 | } | ||
3251 | |||
3252 |
2/2✓ Branch 0 taken 6689 times.
✓ Branch 1 taken 91 times.
|
6780 | if (!(oc->oformat->flags & AVFMT_NOFILE)) { |
3253 | /* test if it already exists to avoid losing precious files */ | ||
3254 | 6689 | err = assert_file_overwrite(filename); | |
3255 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6689 times.
|
6689 | if (err < 0) |
3256 | ✗ | return err; | |
3257 | |||
3258 | /* open the file */ | ||
3259 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6689 times.
|
6689 | if ((err = avio_open2(&oc->pb, filename, AVIO_FLAG_WRITE, |
3260 | 6689 | &oc->interrupt_callback, | |
3261 | &mux->opts)) < 0) { | ||
3262 | ✗ | av_log(mux, AV_LOG_FATAL, "Error opening output %s: %s\n", | |
3263 | ✗ | filename, av_err2str(err)); | |
3264 | ✗ | return err; | |
3265 | } | ||
3266 |
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)) { |
3267 | 7 | err = assert_file_overwrite(filename); | |
3268 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (err < 0) |
3269 | ✗ | return err; | |
3270 | } | ||
3271 | |||
3272 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6780 times.
|
6780 | if (o->mux_preload) { |
3273 | ✗ | av_dict_set_int(&mux->opts, "preload", o->mux_preload*AV_TIME_BASE, 0); | |
3274 | } | ||
3275 | 6780 | oc->max_delay = (int)(o->mux_max_delay * AV_TIME_BASE); | |
3276 | |||
3277 | /* copy metadata and chapters from input files */ | ||
3278 | 6780 | err = copy_meta(mux, o); | |
3279 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6780 times.
|
6780 | if (err < 0) |
3280 | ✗ | return err; | |
3281 | |||
3282 | 6780 | err = of_add_groups(mux, o); | |
3283 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6780 times.
|
6780 | if (err < 0) |
3284 | ✗ | return err; | |
3285 | |||
3286 | 6780 | err = of_add_programs(mux, o); | |
3287 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6780 times.
|
6780 | if (err < 0) |
3288 | ✗ | return err; | |
3289 | |||
3290 | 6780 | err = of_add_metadata(of, oc, o); | |
3291 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6780 times.
|
6780 | if (err < 0) |
3292 | ✗ | return err; | |
3293 | |||
3294 | 6780 | err = set_dispositions(mux, o); | |
3295 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6780 times.
|
6780 | if (err < 0) { |
3296 | ✗ | av_log(mux, AV_LOG_FATAL, "Error setting output stream dispositions\n"); | |
3297 | ✗ | return err; | |
3298 | } | ||
3299 | |||
3300 | // parse forced keyframe specifications; | ||
3301 | // must be done after chapters are created | ||
3302 | 6780 | err = process_forced_keyframes(mux, o); | |
3303 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6780 times.
|
6780 | if (err < 0) { |
3304 | ✗ | av_log(mux, AV_LOG_FATAL, "Error processing forced keyframes\n"); | |
3305 | ✗ | return err; | |
3306 | } | ||
3307 | |||
3308 | 6780 | err = setup_sync_queues(mux, oc, o->shortest_buf_duration * AV_TIME_BASE, | |
3309 | 6780 | o->shortest); | |
3310 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6780 times.
|
6780 | if (err < 0) { |
3311 | ✗ | av_log(mux, AV_LOG_FATAL, "Error setting up output sync queues\n"); | |
3312 | ✗ | return err; | |
3313 | } | ||
3314 | |||
3315 | 6780 | of->url = filename; | |
3316 | |||
3317 | /* initialize streamcopy streams. */ | ||
3318 |
2/2✓ Branch 0 taken 7133 times.
✓ Branch 1 taken 6780 times.
|
13913 | for (int i = 0; i < of->nb_streams; i++) { |
3319 | 7133 | OutputStream *ost = of->streams[i]; | |
3320 | |||
3321 |
2/2✓ Branch 0 taken 646 times.
✓ Branch 1 taken 6487 times.
|
7133 | if (!ost->enc) { |
3322 | 646 | err = of_stream_init(of, ost); | |
3323 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 646 times.
|
646 | if (err < 0) |
3324 | ✗ | return err; | |
3325 | } | ||
3326 | } | ||
3327 | |||
3328 | 6780 | return 0; | |
3329 | } | ||
3330 |