2 * Muxer/output file setup.
4 * This file is part of FFmpeg.
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.
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.
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
25 #include "ffmpeg_mux.h"
26 #include "ffmpeg_sched.h"
27 #include "fopen_utf8.h"
29 #include "libavformat/avformat.h"
30 #include "libavformat/avio.h"
32 #include "libavcodec/avcodec.h"
34 #include "libavfilter/avfilter.h"
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"
51 #define DEFAULT_PASS_LOGFILENAME_PREFIX "ffmpeg2pass"
53 static int check_opt_bitexact(void *ctx
, const AVDictionary
*opts
,
54 const char *opt_name
, int flag
)
56 const AVDictionaryEntry
*e
= av_dict_get(opts
, opt_name
, NULL
, 0);
59 const AVOption
*o
= av_opt_find(ctx
, opt_name
, NULL
, 0, 0);
63 av_opt_eval_flags(ctx
, o
, e
->value
, &val
);
64 return !!(val
& flag
);
69 static int choose_encoder(const OptionsContext
*o
, AVFormatContext
*s
,
70 MuxStream
*ms
, const AVCodec
**enc
)
72 OutputStream
*ost
= &ms
->ost
;
73 enum AVMediaType type
= ost
->type
;
74 const char *codec_name
= NULL
;
78 opt_match_per_stream_str(ost
, &o
->codec_names
, s
, ost
->st
, &codec_name
);
80 if (type
!= AVMEDIA_TYPE_VIDEO
&&
81 type
!= AVMEDIA_TYPE_AUDIO
&&
82 type
!= AVMEDIA_TYPE_SUBTITLE
) {
83 if (codec_name
&& strcmp(codec_name
, "copy")) {
84 const char *type_str
= av_get_media_type_string(type
);
85 av_log(ost
, AV_LOG_FATAL
,
86 "Encoder '%s' specified, but only '-codec copy' supported "
87 "for %s streams\n", codec_name
, type_str
);
88 return AVERROR(ENOSYS
);
94 ms
->par_in
->codec_id
= av_guess_codec(s
->oformat
, NULL
, s
->url
, NULL
, ost
->type
);
95 *enc
= avcodec_find_encoder(ms
->par_in
->codec_id
);
97 av_log(ost
, AV_LOG_FATAL
, "Automatic encoder selection failed "
98 "Default encoder for format %s (codec %s) is "
99 "probably disabled. Please choose an encoder manually.\n",
100 s
->oformat
->name
, avcodec_get_name(ms
->par_in
->codec_id
));
101 return AVERROR_ENCODER_NOT_FOUND
;
103 } else if (strcmp(codec_name
, "copy")) {
104 int ret
= find_codec(ost
, codec_name
, ost
->type
, 1, enc
);
107 ms
->par_in
->codec_id
= (*enc
)->id
;
113 static char *get_line(AVIOContext
*s
, AVBPrint
*bprint
)
117 while ((c
= avio_r8(s
)) && c
!= '\n')
118 av_bprint_chars(bprint
, c
, 1);
120 if (!av_bprint_is_complete(bprint
))
126 static int get_preset_file_2(const char *preset_name
, const char *codec_name
, AVIOContext
**s
)
130 char *env_avconv_datadir
= getenv_utf8("AVCONV_DATADIR");
131 char *env_home
= getenv_utf8("HOME");
132 const char *base
[3] = { env_avconv_datadir
,
137 for (i
= 0; i
< FF_ARRAY_ELEMS(base
) && ret
< 0; i
++) {
141 snprintf(filename
, sizeof(filename
), "%s%s/%s-%s.avpreset", base
[i
],
142 i
!= 1 ? "" : "/.avconv", codec_name
, preset_name
);
143 ret
= avio_open2(s
, filename
, AVIO_FLAG_READ
, &int_cb
, NULL
);
146 snprintf(filename
, sizeof(filename
), "%s%s/%s.avpreset", base
[i
],
147 i
!= 1 ? "" : "/.avconv", preset_name
);
148 ret
= avio_open2(s
, filename
, AVIO_FLAG_READ
, &int_cb
, NULL
);
151 freeenv_utf8(env_home
);
152 freeenv_utf8(env_avconv_datadir
);
156 typedef struct EncStatsFile
{
161 static EncStatsFile
*enc_stats_files
;
162 static int nb_enc_stats_files
;
164 static int enc_stats_get_file(AVIOContext
**io
, const char *path
)
169 for (int i
= 0; i
< nb_enc_stats_files
; i
++)
170 if (!strcmp(path
, enc_stats_files
[i
].path
)) {
171 *io
= enc_stats_files
[i
].io
;
175 ret
= GROW_ARRAY(enc_stats_files
, nb_enc_stats_files
);
179 esf
= &enc_stats_files
[nb_enc_stats_files
- 1];
181 ret
= avio_open2(&esf
->io
, path
, AVIO_FLAG_WRITE
, &int_cb
, NULL
);
183 av_log(NULL
, AV_LOG_ERROR
, "Error opening stats file '%s': %s\n",
184 path
, av_err2str(ret
));
188 esf
->path
= av_strdup(path
);
190 return AVERROR(ENOMEM
);
197 void of_enc_stats_close(void)
199 for (int i
= 0; i
< nb_enc_stats_files
; i
++) {
200 av_freep(&enc_stats_files
[i
].path
);
201 avio_closep(&enc_stats_files
[i
].io
);
203 av_freep(&enc_stats_files
);
204 nb_enc_stats_files
= 0;
207 static int unescape(char **pdst
, size_t *dst_len
,
208 const char **pstr
, char delim
)
210 const char *str
= *pstr
;
220 dst
= av_malloc(len
+ 1);
222 return AVERROR(ENOMEM
);
224 for (idx
= 0; *str
; idx
++, str
++) {
225 if (str
[0] == '\\' && str
[1])
227 else if (*str
== delim
)
246 static int enc_stats_init(OutputStream
*ost
, EncStats
*es
, int pre
,
247 const char *path
, const char *fmt_spec
)
249 static const struct {
250 enum EncStatsType type
;
253 unsigned post_only
:1;
254 unsigned need_input_data
:1;
256 { ENC_STATS_FILE_IDX
, "fidx" },
257 { ENC_STATS_STREAM_IDX
, "sidx" },
258 { ENC_STATS_FRAME_NUM
, "n" },
259 { ENC_STATS_FRAME_NUM_IN
, "ni", 0, 0, 1 },
260 { ENC_STATS_TIMEBASE
, "tb" },
261 { ENC_STATS_TIMEBASE_IN
, "tbi", 0, 0, 1 },
262 { ENC_STATS_PTS
, "pts" },
263 { ENC_STATS_PTS_TIME
, "t" },
264 { ENC_STATS_PTS_IN
, "ptsi", 0, 0, 1 },
265 { ENC_STATS_PTS_TIME_IN
, "ti", 0, 0, 1 },
266 { ENC_STATS_DTS
, "dts", 0, 1 },
267 { ENC_STATS_DTS_TIME
, "dt", 0, 1 },
268 { ENC_STATS_SAMPLE_NUM
, "sn", 1 },
269 { ENC_STATS_NB_SAMPLES
, "samp", 1 },
270 { ENC_STATS_PKT_SIZE
, "size", 0, 1 },
271 { ENC_STATS_BITRATE
, "br", 0, 1 },
272 { ENC_STATS_AVG_BITRATE
, "abr", 0, 1 },
273 { ENC_STATS_KEYFRAME
, "key", 0, 1 },
275 const char *next
= fmt_spec
;
280 EncStatsComponent
*c
;
284 // get the sequence up until next opening brace
285 ret
= unescape(&val
, &val_len
, &next
, '{');
290 ret
= GROW_ARRAY(es
->components
, es
->nb_components
);
296 c
= &es
->components
[es
->nb_components
- 1];
297 c
->type
= ENC_STATS_LITERAL
;
299 c
->str_len
= val_len
;
306 // get the part inside braces
307 ret
= unescape(&val
, &val_len
, &next
, '}');
312 av_log(NULL
, AV_LOG_ERROR
,
313 "Empty formatting directive in: %s\n", fmt_spec
);
314 return AVERROR(EINVAL
);
318 av_log(NULL
, AV_LOG_ERROR
,
319 "Missing closing brace in: %s\n", fmt_spec
);
320 ret
= AVERROR(EINVAL
);
325 ret
= GROW_ARRAY(es
->components
, es
->nb_components
);
329 c
= &es
->components
[es
->nb_components
- 1];
331 for (size_t i
= 0; i
< FF_ARRAY_ELEMS(fmt_specs
); i
++) {
332 if (!strcmp(val
, fmt_specs
[i
].str
)) {
333 if ((pre
&& fmt_specs
[i
].post_only
) || (!pre
&& fmt_specs
[i
].pre_only
)) {
334 av_log(NULL
, AV_LOG_ERROR
,
335 "Format directive '%s' may only be used %s-encoding\n",
336 val
, pre
? "post" : "pre");
337 ret
= AVERROR(EINVAL
);
341 c
->type
= fmt_specs
[i
].type
;
343 if (fmt_specs
[i
].need_input_data
&& !ost
->ist
) {
344 av_log(ost
, AV_LOG_WARNING
,
345 "Format directive '%s' is unavailable, because "
346 "this output stream has no associated input stream\n",
355 av_log(NULL
, AV_LOG_ERROR
, "Invalid format directive: %s\n", val
);
356 ret
= AVERROR(EINVAL
);
366 ret
= pthread_mutex_init(&es
->lock
, NULL
);
369 es
->lock_initialized
= 1;
371 ret
= enc_stats_get_file(&es
->io
, path
);
378 static const char *output_stream_item_name(void *obj
)
380 const MuxStream
*ms
= obj
;
385 static const AVClass output_stream_class
= {
386 .class_name
= "OutputStream",
387 .version
= LIBAVUTIL_VERSION_INT
,
388 .item_name
= output_stream_item_name
,
389 .category
= AV_CLASS_CATEGORY_MUXER
,
392 static MuxStream
*mux_stream_alloc(Muxer
*mux
, enum AVMediaType type
)
394 const char *type_str
= av_get_media_type_string(type
);
397 ms
= allocate_array_elem(&mux
->of
.streams
, sizeof(*ms
), &mux
->of
.nb_streams
);
401 ms
->ost
.file
= &mux
->of
;
402 ms
->ost
.index
= mux
->of
.nb_streams
- 1;
405 ms
->ost
.class = &output_stream_class
;
408 ms
->sch_idx_enc
= -1;
410 snprintf(ms
->log_name
, sizeof(ms
->log_name
), "%cost#%d:%d",
411 type_str
? *type_str
: '?', mux
->of
.index
, ms
->ost
.index
);
416 static int ost_get_filters(const OptionsContext
*o
, AVFormatContext
*oc
,
417 OutputStream
*ost
, char **dst
)
419 const char *filters
= NULL
;
420 #if FFMPEG_OPT_FILTER_SCRIPT
421 const char *filters_script
= NULL
;
423 opt_match_per_stream_str(ost
, &o
->filter_scripts
, oc
, ost
->st
, &filters_script
);
425 opt_match_per_stream_str(ost
, &o
->filters
, oc
, ost
->st
, &filters
);
429 #if FFMPEG_OPT_FILTER_SCRIPT
433 av_log(ost
, AV_LOG_ERROR
,
434 "%s '%s' was specified for a stream fed from a complex "
435 "filtergraph. Simple and complex filtering cannot be used "
436 "together for the same stream.\n",
437 #if FFMPEG_OPT_FILTER_SCRIPT
438 filters
? "Filtergraph" : "Filtergraph script",
439 filters
? filters
: filters_script
441 "Filtergraph", filters
444 return AVERROR(EINVAL
);
449 #if FFMPEG_OPT_FILTER_SCRIPT
450 if (filters_script
&& filters
) {
451 av_log(ost
, AV_LOG_ERROR
, "Both -filter and -filter_script set\n");
452 return AVERROR(EINVAL
);
456 *dst
= file_read(filters_script
);
460 *dst
= av_strdup(filters
);
462 *dst
= av_strdup(ost
->type
== AVMEDIA_TYPE_VIDEO
? "null" : "anull");
463 return *dst
? 0 : AVERROR(ENOMEM
);
466 static int parse_matrix_coeffs(void *logctx
, uint16_t *dest
, const char *str
)
469 for (int i
= 0;; i
++) {
475 av_log(logctx
, AV_LOG_FATAL
,
476 "Syntax error in matrix \"%s\" at coeff %d\n", str
, i
);
477 return AVERROR(EINVAL
);
485 static int fmt_in_list(const int *formats
, int format
)
487 for (; *formats
!= -1; formats
++)
488 if (*formats
== format
)
493 static enum AVPixelFormat
494 choose_pixel_fmt(const AVCodecContext
*avctx
, enum AVPixelFormat target
)
496 const enum AVPixelFormat
*p
;
497 const AVPixFmtDescriptor
*desc
= av_pix_fmt_desc_get(target
);
498 //FIXME: This should check for AV_PIX_FMT_FLAG_ALPHA after PAL8 pixel format without alpha is implemented
499 int has_alpha
= desc
? desc
->nb_components
% 2 == 0 : 0;
500 enum AVPixelFormat best
= AV_PIX_FMT_NONE
;
503 ret
= avcodec_get_supported_config(avctx
, NULL
, AV_CODEC_CONFIG_PIX_FORMAT
,
504 0, (const void **) &p
, NULL
);
506 return AV_PIX_FMT_NONE
;
508 for (; *p
!= AV_PIX_FMT_NONE
; p
++) {
509 best
= av_find_best_pix_fmt_of_2(best
, *p
, target
, has_alpha
, NULL
);
513 if (*p
== AV_PIX_FMT_NONE
) {
514 if (target
!= AV_PIX_FMT_NONE
)
515 av_log(NULL
, AV_LOG_WARNING
,
516 "Incompatible pixel format '%s' for codec '%s', auto-selecting format '%s'\n",
517 av_get_pix_fmt_name(target
),
519 av_get_pix_fmt_name(best
));
525 static enum AVPixelFormat
pix_fmt_parse(OutputStream
*ost
, const char *name
)
527 const enum AVPixelFormat
*fmts
;
528 enum AVPixelFormat fmt
;
531 fmt
= av_get_pix_fmt(name
);
532 if (fmt
== AV_PIX_FMT_NONE
) {
533 av_log(ost
, AV_LOG_FATAL
, "Unknown pixel format requested: %s.\n", name
);
534 return AV_PIX_FMT_NONE
;
537 ret
= avcodec_get_supported_config(ost
->enc
->enc_ctx
, NULL
, AV_CODEC_CONFIG_PIX_FORMAT
,
538 0, (const void **) &fmts
, NULL
);
540 return AV_PIX_FMT_NONE
;
542 /* when the user specified-format is an alias for an endianness-specific
543 * one (e.g. rgb48 -> rgb48be/le), it gets translated into the native
544 * endianness by av_get_pix_fmt();
545 * the following code handles the case when the native endianness is not
546 * supported by the encoder, but the other one is */
547 if (fmts
&& !fmt_in_list(fmts
, fmt
)) {
548 const char *name_canonical
= av_get_pix_fmt_name(fmt
);
549 int len
= strlen(name_canonical
);
551 if (strcmp(name
, name_canonical
) &&
552 (!strcmp(name_canonical
+ len
- 2, "le") ||
553 !strcmp(name_canonical
+ len
- 2, "be"))) {
555 enum AVPixelFormat fmt_other
;
557 snprintf(name_other
, sizeof(name_other
), "%s%ce",
558 name
, name_canonical
[len
- 2] == 'l' ? 'b' : 'l');
559 fmt_other
= av_get_pix_fmt(name_other
);
560 if (fmt_other
!= AV_PIX_FMT_NONE
&& fmt_in_list(fmts
, fmt_other
)) {
561 av_log(ost
, AV_LOG_VERBOSE
, "Mapping pixel format %s->%s\n",
568 if (fmts
&& !fmt_in_list(fmts
, fmt
))
569 fmt
= choose_pixel_fmt(ost
->enc
->enc_ctx
, fmt
);
574 static int new_stream_video(Muxer
*mux
, const OptionsContext
*o
,
575 OutputStream
*ost
, int *keep_pix_fmt
,
576 enum VideoSyncMethod
*vsync_method
)
578 MuxStream
*ms
= ms_from_ost(ost
);
579 AVFormatContext
*oc
= mux
->fc
;
581 const char *frame_rate
= NULL
, *max_frame_rate
= NULL
, *frame_aspect_ratio
= NULL
;
586 opt_match_per_stream_str(ost
, &o
->frame_rates
, oc
, st
, &frame_rate
);
587 if (frame_rate
&& av_parse_video_rate(&ms
->frame_rate
, frame_rate
) < 0) {
588 av_log(ost
, AV_LOG_FATAL
, "Invalid framerate value: %s\n", frame_rate
);
589 return AVERROR(EINVAL
);
592 opt_match_per_stream_str(ost
, &o
->max_frame_rates
, oc
, st
, &max_frame_rate
);
593 if (max_frame_rate
&& av_parse_video_rate(&ms
->max_frame_rate
, max_frame_rate
) < 0) {
594 av_log(ost
, AV_LOG_FATAL
, "Invalid maximum framerate value: %s\n", max_frame_rate
);
595 return AVERROR(EINVAL
);
598 if (frame_rate
&& max_frame_rate
) {
599 av_log(ost
, AV_LOG_ERROR
, "Only one of -fpsmax and -r can be set for a stream.\n");
600 return AVERROR(EINVAL
);
603 opt_match_per_stream_str(ost
, &o
->frame_aspect_ratios
, oc
, st
, &frame_aspect_ratio
);
604 if (frame_aspect_ratio
) {
606 if (av_parse_ratio(&q
, frame_aspect_ratio
, 255, 0, NULL
) < 0 ||
607 q
.num
<= 0 || q
.den
<= 0) {
608 av_log(ost
, AV_LOG_FATAL
, "Invalid aspect ratio: %s\n", frame_aspect_ratio
);
609 return AVERROR(EINVAL
);
611 ost
->frame_aspect_ratio
= q
;
615 AVCodecContext
*video_enc
= ost
->enc
->enc_ctx
;
616 const char *p
= NULL
, *fps_mode
= NULL
;
617 const char *frame_size
= NULL
;
618 const char *frame_pix_fmt
= NULL
;
619 const char *intra_matrix
= NULL
, *inter_matrix
= NULL
;
620 const char *chroma_intra_matrix
= NULL
;
624 opt_match_per_stream_str(ost
, &o
->frame_sizes
, oc
, st
, &frame_size
);
626 ret
= av_parse_video_size(&video_enc
->width
, &video_enc
->height
, frame_size
);
628 av_log(ost
, AV_LOG_FATAL
, "Invalid frame size: %s.\n", frame_size
);
629 return AVERROR(EINVAL
);
633 opt_match_per_stream_str(ost
, &o
->frame_pix_fmts
, oc
, st
, &frame_pix_fmt
);
634 if (frame_pix_fmt
&& *frame_pix_fmt
== '+') {
636 if (!*++frame_pix_fmt
)
637 frame_pix_fmt
= NULL
;
640 video_enc
->pix_fmt
= pix_fmt_parse(ost
, frame_pix_fmt
);
641 if (video_enc
->pix_fmt
== AV_PIX_FMT_NONE
)
642 return AVERROR(EINVAL
);
645 opt_match_per_stream_str(ost
, &o
->intra_matrices
, oc
, st
, &intra_matrix
);
647 if (!(video_enc
->intra_matrix
= av_mallocz(sizeof(*video_enc
->intra_matrix
) * 64)))
648 return AVERROR(ENOMEM
);
650 ret
= parse_matrix_coeffs(ost
, video_enc
->intra_matrix
, intra_matrix
);
654 opt_match_per_stream_str(ost
, &o
->chroma_intra_matrices
, oc
, st
, &chroma_intra_matrix
);
655 if (chroma_intra_matrix
) {
656 if (!(video_enc
->chroma_intra_matrix
= av_mallocz(sizeof(*video_enc
->chroma_intra_matrix
) * 64)))
657 return AVERROR(ENOMEM
);
658 ret
= parse_matrix_coeffs(ost
, video_enc
->chroma_intra_matrix
, chroma_intra_matrix
);
662 opt_match_per_stream_str(ost
, &o
->inter_matrices
, oc
, st
, &inter_matrix
);
664 if (!(video_enc
->inter_matrix
= av_mallocz(sizeof(*video_enc
->inter_matrix
) * 64)))
665 return AVERROR(ENOMEM
);
666 ret
= parse_matrix_coeffs(ost
, video_enc
->inter_matrix
, inter_matrix
);
671 opt_match_per_stream_str(ost
, &o
->rc_overrides
, oc
, st
, &p
);
672 for (i
= 0; p
; i
++) {
674 int e
= sscanf(p
, "%d,%d,%d", &start
, &end
, &q
);
676 av_log(ost
, AV_LOG_FATAL
, "error parsing rc_override\n");
677 return AVERROR(EINVAL
);
679 video_enc
->rc_override
=
680 av_realloc_array(video_enc
->rc_override
,
681 i
+ 1, sizeof(RcOverride
));
682 if (!video_enc
->rc_override
) {
683 av_log(ost
, AV_LOG_FATAL
, "Could not (re)allocate memory for rc_override.\n");
684 return AVERROR(ENOMEM
);
686 video_enc
->rc_override
[i
].start_frame
= start
;
687 video_enc
->rc_override
[i
].end_frame
= end
;
689 video_enc
->rc_override
[i
].qscale
= q
;
690 video_enc
->rc_override
[i
].quality_factor
= 1.0;
693 video_enc
->rc_override
[i
].qscale
= 0;
694 video_enc
->rc_override
[i
].quality_factor
= -q
/100.0;
699 video_enc
->rc_override_count
= i
;
702 opt_match_per_stream_int(ost
, &o
->pass
, oc
, st
, &do_pass
);
705 video_enc
->flags
|= AV_CODEC_FLAG_PASS1
;
707 video_enc
->flags
|= AV_CODEC_FLAG_PASS2
;
710 opt_match_per_stream_str(ost
, &o
->passlogfiles
, oc
, st
, &ost
->logfile_prefix
);
711 if (ost
->logfile_prefix
&&
712 !(ost
->logfile_prefix
= av_strdup(ost
->logfile_prefix
)))
713 return AVERROR(ENOMEM
);
717 char logfilename
[1024];
720 /* compute this stream's global index */
721 for (int idx
= 0; idx
<= ost
->file
->index
; idx
++)
722 ost_idx
+= output_files
[idx
]->nb_streams
;
724 snprintf(logfilename
, sizeof(logfilename
), "%s-%d.log",
725 ost
->logfile_prefix
? ost
->logfile_prefix
:
726 DEFAULT_PASS_LOGFILENAME_PREFIX
,
728 if (!strcmp(video_enc
->codec
->name
, "libx264") || !strcmp(video_enc
->codec
->name
, "libvvenc")) {
729 if (av_opt_is_set_to_default_by_name(video_enc
, "stats",
730 AV_OPT_SEARCH_CHILDREN
) > 0)
731 av_opt_set(video_enc
, "stats", logfilename
,
732 AV_OPT_SEARCH_CHILDREN
);
734 if (video_enc
->flags
& AV_CODEC_FLAG_PASS2
) {
735 char *logbuffer
= file_read(logfilename
);
738 av_log(ost
, AV_LOG_FATAL
, "Error reading log file '%s' for pass-2 encoding\n",
742 video_enc
->stats_in
= logbuffer
;
744 if (video_enc
->flags
& AV_CODEC_FLAG_PASS1
) {
745 f
= fopen_utf8(logfilename
, "wb");
747 av_log(ost
, AV_LOG_FATAL
,
748 "Cannot write log file '%s' for pass-1 encoding: %s\n",
749 logfilename
, strerror(errno
));
750 return AVERROR(errno
);
757 opt_match_per_stream_int(ost
, &o
->force_fps
, oc
, st
, &ms
->force_fps
);
760 ost
->top_field_first
= -1;
761 opt_match_per_stream_int(ost
, &o
->top_field_first
, oc
, st
, &ost
->top_field_first
);
762 if (ost
->top_field_first
>= 0)
763 av_log(ost
, AV_LOG_WARNING
, "-top is deprecated, use the setfield filter instead\n");
767 *vsync_method
= video_sync_method
;
769 *vsync_method
= VSYNC_AUTO
;
771 opt_match_per_stream_str(ost
, &o
->fps_mode
, oc
, st
, &fps_mode
);
773 ret
= parse_and_set_vsync(fps_mode
, vsync_method
, ost
->file
->index
, ost
->index
, 0);
778 if ((ms
->frame_rate
.num
|| ms
->max_frame_rate
.num
) &&
779 !(*vsync_method
== VSYNC_AUTO
||
780 *vsync_method
== VSYNC_CFR
|| *vsync_method
== VSYNC_VSCFR
)) {
781 av_log(ost
, AV_LOG_FATAL
, "One of -r/-fpsmax was specified "
782 "together a non-CFR -vsync/-fps_mode. This is contradictory.\n");
783 return AVERROR(EINVAL
);
786 if (*vsync_method
== VSYNC_AUTO
) {
787 if (ms
->frame_rate
.num
|| ms
->max_frame_rate
.num
) {
788 *vsync_method
= VSYNC_CFR
;
789 } else if (!strcmp(oc
->oformat
->name
, "avi")) {
790 *vsync_method
= VSYNC_VFR
;
792 *vsync_method
= (oc
->oformat
->flags
& AVFMT_VARIABLE_FPS
) ?
793 ((oc
->oformat
->flags
& AVFMT_NOTIMESTAMPS
) ?
794 VSYNC_PASSTHROUGH
: VSYNC_VFR
) : VSYNC_CFR
;
797 if (ost
->ist
&& *vsync_method
== VSYNC_CFR
) {
798 const InputFile
*ifile
= ost
->ist
->file
;
800 if (ifile
->nb_streams
== 1 && ifile
->input_ts_offset
== 0)
801 *vsync_method
= VSYNC_VSCFR
;
804 if (*vsync_method
== VSYNC_CFR
&& copy_ts
) {
805 *vsync_method
= VSYNC_VSCFR
;
808 #if FFMPEG_OPT_VSYNC_DROP
809 if (*vsync_method
== VSYNC_DROP
)
817 static int new_stream_audio(Muxer
*mux
, const OptionsContext
*o
,
820 MuxStream
*ms
= ms_from_ost(ost
);
821 AVFormatContext
*oc
= mux
->fc
;
822 AVStream
*st
= ost
->st
;
825 AVCodecContext
*audio_enc
= ost
->enc
->enc_ctx
;
827 const char *layout
= NULL
;
828 const char *sample_fmt
= NULL
;
830 opt_match_per_stream_int(ost
, &o
->audio_channels
, oc
, st
, &channels
);
832 audio_enc
->ch_layout
.order
= AV_CHANNEL_ORDER_UNSPEC
;
833 audio_enc
->ch_layout
.nb_channels
= channels
;
836 opt_match_per_stream_str(ost
, &o
->audio_ch_layouts
, oc
, st
, &layout
);
837 if (layout
&& av_channel_layout_from_string(&audio_enc
->ch_layout
, layout
) < 0) {
838 av_log(ost
, AV_LOG_FATAL
, "Unknown channel layout: %s\n", layout
);
839 return AVERROR(EINVAL
);
842 opt_match_per_stream_str(ost
, &o
->sample_fmts
, oc
, st
, &sample_fmt
);
844 (audio_enc
->sample_fmt
= av_get_sample_fmt(sample_fmt
)) == AV_SAMPLE_FMT_NONE
) {
845 av_log(ost
, AV_LOG_FATAL
, "Invalid sample format '%s'\n", sample_fmt
);
846 return AVERROR(EINVAL
);
849 opt_match_per_stream_int(ost
, &o
->audio_sample_rate
, oc
, st
, &audio_enc
->sample_rate
);
850 opt_match_per_stream_str(ost
, &o
->apad
, oc
, st
, &ms
->apad
);
856 static int new_stream_subtitle(Muxer
*mux
, const OptionsContext
*o
,
864 AVCodecContext
*subtitle_enc
= ost
->enc
->enc_ctx
;
866 AVCodecDescriptor
const *input_descriptor
=
867 avcodec_descriptor_get(ost
->ist
->par
->codec_id
);
868 AVCodecDescriptor
const *output_descriptor
=
869 avcodec_descriptor_get(subtitle_enc
->codec_id
);
870 int input_props
= 0, output_props
= 0;
872 const char *frame_size
= NULL
;
874 opt_match_per_stream_str(ost
, &o
->frame_sizes
, mux
->fc
, st
, &frame_size
);
876 int ret
= av_parse_video_size(&subtitle_enc
->width
, &subtitle_enc
->height
, frame_size
);
878 av_log(ost
, AV_LOG_FATAL
, "Invalid frame size: %s.\n", frame_size
);
882 if (input_descriptor
)
883 input_props
= input_descriptor
->props
& (AV_CODEC_PROP_TEXT_SUB
| AV_CODEC_PROP_BITMAP_SUB
);
884 if (output_descriptor
)
885 output_props
= output_descriptor
->props
& (AV_CODEC_PROP_TEXT_SUB
| AV_CODEC_PROP_BITMAP_SUB
);
886 if (input_props
&& output_props
&& input_props
!= output_props
) {
887 av_log(ost
, AV_LOG_ERROR
,
888 "Subtitle encoding currently only possible from text to text "
889 "or bitmap to bitmap\n");
890 return AVERROR(EINVAL
);
898 ost_bind_filter(const Muxer
*mux
, MuxStream
*ms
, OutputFilter
*ofilter
,
899 const OptionsContext
*o
,
900 AVRational enc_tb
, enum VideoSyncMethod vsync_method
,
901 int keep_pix_fmt
, int autoscale
, int threads_manual
,
902 const ViewSpecifier
*vs
,
905 OutputStream
*ost
= &ms
->ost
;
906 AVCodecContext
*enc_ctx
= ost
->enc
->enc_ctx
;
908 char *filters
= NULL
;
911 OutputFilterOptions opts
= {
912 .enc
= enc_ctx
->codec
,
914 .format
= (ost
->type
== AVMEDIA_TYPE_VIDEO
) ?
915 enc_ctx
->pix_fmt
: enc_ctx
->sample_fmt
,
916 .width
= enc_ctx
->width
,
917 .height
= enc_ctx
->height
,
918 .color_space
= enc_ctx
->colorspace
,
919 .color_range
= enc_ctx
->color_range
,
920 .vsync_method
= vsync_method
,
921 .frame_rate
= ms
->frame_rate
,
922 .max_frame_rate
= ms
->max_frame_rate
,
923 .sample_rate
= enc_ctx
->sample_rate
,
924 .ch_layout
= enc_ctx
->ch_layout
,
925 .sws_opts
= o
->g
->sws_dict
,
926 .swr_opts
= o
->g
->swr_opts
,
928 .trim_start_us
= mux
->of
.start_time
,
929 .trim_duration_us
= mux
->of
.recording_time
,
930 .ts_offset
= mux
->of
.start_time
== AV_NOPTS_VALUE
?
931 0 : mux
->of
.start_time
,
934 .flags
= OFILTER_FLAG_DISABLE_CONVERT
* !!keep_pix_fmt
|
935 OFILTER_FLAG_AUTOSCALE
* !!autoscale
|
936 OFILTER_FLAG_AUDIO_24BIT
* !!(av_get_exact_bits_per_sample(enc_ctx
->codec_id
) == 24),
939 snprintf(name
, sizeof(name
), "#%d:%d", mux
->of
.index
, ost
->index
);
941 if (ost
->type
== AVMEDIA_TYPE_VIDEO
) {
943 ret
= avcodec_get_supported_config(enc_ctx
, NULL
,
944 AV_CODEC_CONFIG_PIX_FORMAT
, 0,
945 (const void **) &opts
.formats
, NULL
);
949 if (!ms
->force_fps
) {
950 ret
= avcodec_get_supported_config(enc_ctx
, NULL
,
951 AV_CODEC_CONFIG_FRAME_RATE
, 0,
952 (const void **) &opts
.frame_rates
, NULL
);
956 ret
= avcodec_get_supported_config(enc_ctx
, NULL
,
957 AV_CODEC_CONFIG_COLOR_SPACE
, 0,
958 (const void **) &opts
.color_spaces
, NULL
);
961 ret
= avcodec_get_supported_config(enc_ctx
, NULL
,
962 AV_CODEC_CONFIG_COLOR_RANGE
, 0,
963 (const void **) &opts
.color_ranges
, NULL
);
967 ret
= avcodec_get_supported_config(enc_ctx
, NULL
,
968 AV_CODEC_CONFIG_SAMPLE_FORMAT
, 0,
969 (const void **) &opts
.formats
, NULL
);
972 ret
= avcodec_get_supported_config(enc_ctx
, NULL
,
973 AV_CODEC_CONFIG_SAMPLE_RATE
, 0,
974 (const void **) &opts
.sample_rates
, NULL
);
977 ret
= avcodec_get_supported_config(enc_ctx
, NULL
,
978 AV_CODEC_CONFIG_CHANNEL_LAYOUT
, 0,
979 (const void **) &opts
.ch_layouts
, NULL
);
984 if (threads_manual
) {
985 ret
= av_opt_get(enc_ctx
, "threads", 0, (uint8_t**)&opts
.nb_threads
);
990 ret
= ost_get_filters(o
, mux
->fc
, ost
, &filters
);
995 av_assert0(!filters
);
996 ost
->filter
= ofilter
;
997 ret
= ofilter_bind_enc(ofilter
, ms
->sch_idx_enc
, &opts
);
999 ret
= fg_create_simple(&ost
->fg_simple
, ost
->ist
, filters
,
1000 mux
->sch
, ms
->sch_idx_enc
, &opts
);
1002 ost
->filter
= ost
->fg_simple
->outputs
[0];
1005 av_freep(&opts
.nb_threads
);
1009 *src
= SCH_ENC(ms
->sch_idx_enc
);
1014 static int streamcopy_init(const OptionsContext
*o
, const Muxer
*mux
,
1015 OutputStream
*ost
, AVDictionary
**encoder_opts
)
1017 MuxStream
*ms
= ms_from_ost(ost
);
1019 const InputStream
*ist
= ost
->ist
;
1020 const InputFile
*ifile
= ist
->file
;
1022 AVCodecParameters
*par
= ms
->par_in
;
1023 uint32_t codec_tag
= par
->codec_tag
;
1025 AVCodecContext
*codec_ctx
= NULL
;
1027 AVRational fr
= ms
->frame_rate
;
1031 const char *filters
= NULL
;
1032 #if FFMPEG_OPT_FILTER_SCRIPT
1033 const char *filters_script
= NULL
;
1035 opt_match_per_stream_str(ost
, &o
->filter_scripts
, mux
->fc
, ost
->st
, &filters_script
);
1037 opt_match_per_stream_str(ost
, &o
->filters
, mux
->fc
, ost
->st
, &filters
);
1040 #if FFMPEG_OPT_FILTER_SCRIPT
1044 av_log(ost
, AV_LOG_ERROR
,
1045 "%s '%s' was specified, but codec copy was selected. "
1046 "Filtering and streamcopy cannot be used together.\n",
1047 #if FFMPEG_OPT_FILTER_SCRIPT
1048 filters
? "Filtergraph" : "Filtergraph script",
1049 filters
? filters
: filters_script
1051 "Filtergraph", filters
1054 return AVERROR(EINVAL
);
1057 codec_ctx
= avcodec_alloc_context3(NULL
);
1059 return AVERROR(ENOMEM
);
1061 ret
= avcodec_parameters_to_context(codec_ctx
, ist
->par
);
1063 ret
= av_opt_set_dict(codec_ctx
, encoder_opts
);
1065 av_log(ost
, AV_LOG_FATAL
,
1066 "Error setting up codec context options.\n");
1070 ret
= avcodec_parameters_from_context(par
, codec_ctx
);
1072 av_log(ost
, AV_LOG_FATAL
,
1073 "Error getting reference codec parameters.\n");
1078 const struct AVCodecTag
* const *ct
= mux
->fc
->oformat
->codec_tag
;
1079 unsigned int codec_tag_tmp
;
1080 if (!ct
|| av_codec_get_id (ct
, par
->codec_tag
) == par
->codec_id
||
1081 !av_codec_get_tag2(ct
, par
->codec_id
, &codec_tag_tmp
))
1082 codec_tag
= par
->codec_tag
;
1085 par
->codec_tag
= codec_tag
;
1088 fr
= ist
->framerate
;
1091 ost
->st
->avg_frame_rate
= fr
;
1093 ost
->st
->avg_frame_rate
= ist
->st
->avg_frame_rate
;
1095 // copy timebase while removing common factors
1096 if (ost
->st
->time_base
.num
<= 0 || ost
->st
->time_base
.den
<= 0) {
1098 ost
->st
->time_base
= av_inv_q(fr
);
1100 ost
->st
->time_base
= av_add_q(ist
->st
->time_base
, (AVRational
){0, 1});
1103 if (!ms
->copy_prior_start
) {
1104 ms
->ts_copy_start
= (mux
->of
.start_time
== AV_NOPTS_VALUE
) ?
1105 0 : mux
->of
.start_time
;
1106 if (copy_ts
&& ifile
->start_time
!= AV_NOPTS_VALUE
) {
1107 ms
->ts_copy_start
= FFMAX(ms
->ts_copy_start
,
1108 ifile
->start_time
+ ifile
->ts_offset
);
1112 for (int i
= 0; i
< ist
->st
->codecpar
->nb_coded_side_data
; i
++) {
1113 const AVPacketSideData
*sd_src
= &ist
->st
->codecpar
->coded_side_data
[i
];
1114 AVPacketSideData
*sd_dst
;
1116 sd_dst
= av_packet_side_data_new(&ost
->st
->codecpar
->coded_side_data
,
1117 &ost
->st
->codecpar
->nb_coded_side_data
,
1118 sd_src
->type
, sd_src
->size
, 0);
1120 ret
= AVERROR(ENOMEM
);
1123 memcpy(sd_dst
->data
, sd_src
->data
, sd_src
->size
);
1126 switch (par
->codec_type
) {
1127 case AVMEDIA_TYPE_AUDIO
:
1128 if ((par
->block_align
== 1 || par
->block_align
== 1152 || par
->block_align
== 576) &&
1129 par
->codec_id
== AV_CODEC_ID_MP3
)
1130 par
->block_align
= 0;
1131 if (par
->codec_id
== AV_CODEC_ID_AC3
)
1132 par
->block_align
= 0;
1134 case AVMEDIA_TYPE_VIDEO
: {
1136 if (ost
->frame_aspect_ratio
.num
) { // overridden by the -aspect cli option
1138 av_mul_q(ost
->frame_aspect_ratio
,
1139 (AVRational
){ par
->height
, par
->width
});
1140 av_log(ost
, AV_LOG_WARNING
, "Overriding aspect ratio "
1141 "with stream copy may produce invalid files\n");
1143 else if (ist
->st
->sample_aspect_ratio
.num
)
1144 sar
= ist
->st
->sample_aspect_ratio
;
1146 sar
= par
->sample_aspect_ratio
;
1147 ost
->st
->sample_aspect_ratio
= par
->sample_aspect_ratio
= sar
;
1148 ost
->st
->r_frame_rate
= ist
->st
->r_frame_rate
;
1154 avcodec_free_context(&codec_ctx
);
1158 static int set_encoder_id(OutputStream
*ost
, const AVCodec
*codec
)
1160 const char *cname
= codec
->name
;
1161 uint8_t *encoder_string
;
1162 int encoder_string_len
;
1164 encoder_string_len
= sizeof(LIBAVCODEC_IDENT
) + strlen(cname
) + 2;
1165 encoder_string
= av_mallocz(encoder_string_len
);
1166 if (!encoder_string
)
1167 return AVERROR(ENOMEM
);
1169 if (!ost
->file
->bitexact
&& !ost
->bitexact
)
1170 av_strlcpy(encoder_string
, LIBAVCODEC_IDENT
" ", encoder_string_len
);
1172 av_strlcpy(encoder_string
, "Lavc ", encoder_string_len
);
1173 av_strlcat(encoder_string
, cname
, encoder_string_len
);
1174 av_dict_set(&ost
->st
->metadata
, "encoder", encoder_string
,
1175 AV_DICT_DONT_STRDUP_VAL
| AV_DICT_DONT_OVERWRITE
);
1180 static int ost_add(Muxer
*mux
, const OptionsContext
*o
, enum AVMediaType type
,
1181 InputStream
*ist
, OutputFilter
*ofilter
, const ViewSpecifier
*vs
,
1182 OutputStream
**post
)
1184 AVFormatContext
*oc
= mux
->fc
;
1189 SchedulerNode src
= { .type
= SCH_NODE_TYPE_NONE
};
1190 AVDictionary
*encoder_opts
= NULL
;
1191 int ret
= 0, keep_pix_fmt
= 0, autoscale
= 1;
1192 int threads_manual
= 0;
1193 AVRational enc_tb
= { 0, 0 };
1194 enum VideoSyncMethod vsync_method
= VSYNC_AUTO
;
1195 const char *bsfs
= NULL
, *time_base
= NULL
, *codec_tag
= NULL
;
1199 st
= avformat_new_stream(oc
, NULL
);
1201 return AVERROR(ENOMEM
);
1203 ms
= mux_stream_alloc(mux
, type
);
1205 return AVERROR(ENOMEM
);
1207 // only streams with sources (i.e. not attachments)
1208 // are handled by the scheduler
1209 if (ist
|| ofilter
) {
1210 ret
= GROW_ARRAY(mux
->sch_stream_idx
, mux
->nb_sch_stream_idx
);
1214 ret
= sch_add_mux_stream(mux
->sch
, mux
->sch_idx
);
1218 av_assert0(ret
== mux
->nb_sch_stream_idx
- 1);
1219 mux
->sch_stream_idx
[ret
] = ms
->ost
.index
;
1226 AVDictionaryEntry
*e
;
1228 snprintf(idx
, sizeof(idx
), "%d", ost
->index
);
1230 e
= av_dict_get(o
->streamid
, idx
, NULL
, 0);
1232 st
->id
= strtol(e
->value
, &p
, 0);
1233 if (!e
->value
[0] || *p
) {
1234 av_log(ost
, AV_LOG_FATAL
, "Invalid stream id: %s\n", e
->value
);
1235 return AVERROR(EINVAL
);
1240 ms
->par_in
= avcodec_parameters_alloc();
1242 return AVERROR(ENOMEM
);
1244 ms
->last_mux_dts
= AV_NOPTS_VALUE
;
1248 ost
->kf
.ref_pts
= AV_NOPTS_VALUE
;
1249 ms
->par_in
->codec_type
= type
;
1250 st
->codecpar
->codec_type
= type
;
1252 ret
= choose_encoder(o
, oc
, ms
, &enc
);
1254 av_log(ost
, AV_LOG_FATAL
, "Error selecting an encoder\n");
1259 ret
= sch_add_enc(mux
->sch
, encoder_thread
, ost
,
1260 ost
->type
== AVMEDIA_TYPE_SUBTITLE
? NULL
: enc_open
);
1263 ms
->sch_idx_enc
= ret
;
1265 ret
= enc_alloc(&ost
->enc
, enc
, mux
->sch
, ms
->sch_idx_enc
, ost
);
1269 av_strlcat(ms
->log_name
, "/", sizeof(ms
->log_name
));
1270 av_strlcat(ms
->log_name
, enc
->name
, sizeof(ms
->log_name
));
1273 av_log(ost
, AV_LOG_ERROR
,
1274 "Streamcopy requested for output stream fed "
1275 "from a complex filtergraph. Filtering and streamcopy "
1276 "cannot be used together.\n");
1277 return AVERROR(EINVAL
);
1280 av_strlcat(ms
->log_name
, "/copy", sizeof(ms
->log_name
));
1283 av_log(ost
, AV_LOG_VERBOSE
, "Created %s stream from ",
1284 av_get_media_type_string(type
));
1286 av_log(ost
, AV_LOG_VERBOSE
, "input stream %d:%d",
1287 ist
->file
->index
, ist
->index
);
1289 av_log(ost
, AV_LOG_VERBOSE
, "complex filtergraph %d:[%s]\n",
1290 ofilter
->graph
->index
, ofilter
->name
);
1291 else if (type
== AVMEDIA_TYPE_ATTACHMENT
)
1292 av_log(ost
, AV_LOG_VERBOSE
, "attached file");
1294 av_log(ost
, AV_LOG_VERBOSE
, "\n");
1296 ms
->pkt
= av_packet_alloc();
1298 return AVERROR(ENOMEM
);
1301 AVIOContext
*s
= NULL
;
1302 char *buf
= NULL
, *arg
= NULL
;
1303 const char *enc_stats_pre
= NULL
, *enc_stats_post
= NULL
, *mux_stats
= NULL
;
1304 const char *enc_time_base
= NULL
, *preset
= NULL
;
1306 ret
= filter_codec_opts(o
->g
->codec_opts
, enc
->id
,
1307 oc
, st
, enc
, &encoder_opts
,
1308 &mux
->enc_opts_used
);
1312 opt_match_per_stream_str(ost
, &o
->presets
, oc
, st
, &preset
);
1313 opt_match_per_stream_int(ost
, &o
->autoscale
, oc
, st
, &autoscale
);
1314 if (preset
&& (!(ret
= get_preset_file_2(preset
, enc
->name
, &s
)))) {
1316 av_bprint_init(&bprint
, 0, AV_BPRINT_SIZE_UNLIMITED
);
1318 av_bprint_clear(&bprint
);
1319 buf
= get_line(s
, &bprint
);
1321 ret
= AVERROR(ENOMEM
);
1325 if (!buf
[0] || buf
[0] == '#')
1327 if (!(arg
= strchr(buf
, '='))) {
1328 av_log(ost
, AV_LOG_FATAL
, "Invalid line found in the preset file.\n");
1329 ret
= AVERROR(EINVAL
);
1333 av_dict_set(&encoder_opts
, buf
, arg
, AV_DICT_DONT_OVERWRITE
);
1334 } while (!s
->eof_reached
);
1335 av_bprint_finalize(&bprint
, NULL
);
1339 av_log(ost
, AV_LOG_FATAL
,
1340 "Preset %s specified, but could not be opened.\n", preset
);
1344 opt_match_per_stream_str(ost
, &o
->enc_stats_pre
, oc
, st
, &enc_stats_pre
);
1345 if (enc_stats_pre
&&
1346 (type
== AVMEDIA_TYPE_VIDEO
|| type
== AVMEDIA_TYPE_AUDIO
)) {
1347 const char *format
= "{fidx} {sidx} {n} {t}";
1349 opt_match_per_stream_str(ost
, &o
->enc_stats_pre_fmt
, oc
, st
, &format
);
1351 ret
= enc_stats_init(ost
, &ost
->enc_stats_pre
, 1, enc_stats_pre
, format
);
1356 opt_match_per_stream_str(ost
, &o
->enc_stats_post
, oc
, st
, &enc_stats_post
);
1357 if (enc_stats_post
&&
1358 (type
== AVMEDIA_TYPE_VIDEO
|| type
== AVMEDIA_TYPE_AUDIO
)) {
1359 const char *format
= "{fidx} {sidx} {n} {t}";
1361 opt_match_per_stream_str(ost
, &o
->enc_stats_post_fmt
, oc
, st
, &format
);
1363 ret
= enc_stats_init(ost
, &ost
->enc_stats_post
, 0, enc_stats_post
, format
);
1368 opt_match_per_stream_str(ost
, &o
->mux_stats
, oc
, st
, &mux_stats
);
1370 (type
== AVMEDIA_TYPE_VIDEO
|| type
== AVMEDIA_TYPE_AUDIO
)) {
1371 const char *format
= "{fidx} {sidx} {n} {t}";
1373 opt_match_per_stream_str(ost
, &o
->mux_stats_fmt
, oc
, st
, &format
);
1375 ret
= enc_stats_init(ost
, &ms
->stats
, 0, mux_stats
, format
);
1380 opt_match_per_stream_str(ost
, &o
->enc_time_bases
, oc
, st
, &enc_time_base
);
1381 if (enc_time_base
&& type
== AVMEDIA_TYPE_SUBTITLE
)
1382 av_log(ost
, AV_LOG_WARNING
,
1383 "-enc_time_base not supported for subtitles, ignoring\n");
1384 else if (enc_time_base
) {
1387 if (!strcmp(enc_time_base
, "demux")) {
1388 q
= (AVRational
){ ENC_TIME_BASE_DEMUX
, 0 };
1389 } else if (!strcmp(enc_time_base
, "filter")) {
1390 q
= (AVRational
){ ENC_TIME_BASE_FILTER
, 0 };
1392 ret
= av_parse_ratio(&q
, enc_time_base
, INT_MAX
, 0, NULL
);
1393 if (ret
< 0 || q
.den
<= 0
1394 #if !FFMPEG_OPT_ENC_TIME_BASE_NUM
1398 av_log(ost
, AV_LOG_FATAL
, "Invalid time base: %s\n", enc_time_base
);
1399 ret
= ret
< 0 ? ret
: AVERROR(EINVAL
);
1402 #if FFMPEG_OPT_ENC_TIME_BASE_NUM
1404 av_log(ost
, AV_LOG_WARNING
, "-enc_time_base -1 is deprecated,"
1405 " use -enc_time_base demux\n");
1412 threads_manual
= !!av_dict_get(encoder_opts
, "threads", NULL
, 0);
1414 ret
= av_opt_set_dict2(ost
->enc
->enc_ctx
, &encoder_opts
, AV_OPT_SEARCH_CHILDREN
);
1416 av_log(ost
, AV_LOG_ERROR
, "Error applying encoder options: %s\n",
1421 ret
= check_avoptions(encoder_opts
);
1425 // default to automatic thread count
1426 if (!threads_manual
)
1427 ost
->enc
->enc_ctx
->thread_count
= 0;
1429 ret
= filter_codec_opts(o
->g
->codec_opts
, AV_CODEC_ID_NONE
, oc
, st
,
1430 NULL
, &encoder_opts
,
1431 &mux
->enc_opts_used
);
1439 } else if (ost
->enc
) {
1440 ost
->bitexact
= !!(ost
->enc
->enc_ctx
->flags
& AV_CODEC_FLAG_BITEXACT
);
1444 ret
= set_encoder_id(ost
, enc
);
1449 opt_match_per_stream_str(ost
, &o
->time_bases
, oc
, st
, &time_base
);
1452 if (av_parse_ratio(&q
, time_base
, INT_MAX
, 0, NULL
) < 0 ||
1453 q
.num
<= 0 || q
.den
<= 0) {
1454 av_log(ost
, AV_LOG_FATAL
, "Invalid time base: %s\n", time_base
);
1455 ret
= AVERROR(EINVAL
);
1461 ms
->max_frames
= INT64_MAX
;
1462 opt_match_per_stream_int64(ost
, &o
->max_frames
, oc
, st
, &ms
->max_frames
);
1463 for (int i
= 0; i
< o
->max_frames
.nb_opt
; i
++) {
1464 char *p
= o
->max_frames
.opt
[i
].specifier
;
1465 if (!*p
&& type
!= AVMEDIA_TYPE_VIDEO
) {
1466 av_log(ost
, AV_LOG_WARNING
, "Applying unspecific -frames to non video streams, maybe you meant -vframes ?\n");
1471 ms
->copy_prior_start
= -1;
1472 opt_match_per_stream_int(ost
, &o
->copy_prior_start
, oc
, st
, &ms
->copy_prior_start
);
1473 opt_match_per_stream_str(ost
, &o
->bitstream_filters
, oc
, st
, &bsfs
);
1474 if (bsfs
&& *bsfs
) {
1475 ret
= av_bsf_list_parse_str(bsfs
, &ms
->bsf_ctx
);
1477 av_log(ost
, AV_LOG_ERROR
, "Error parsing bitstream filter sequence '%s': %s\n", bsfs
, av_err2str(ret
));
1482 opt_match_per_stream_str(ost
, &o
->codec_tags
, oc
, st
, &codec_tag
);
1484 uint32_t tag
= strtol(codec_tag
, &next
, 0);
1486 uint8_t buf
[4] = { 0 };
1487 memcpy(buf
, codec_tag
, FFMIN(sizeof(buf
), strlen(codec_tag
)));
1490 ost
->st
->codecpar
->codec_tag
= tag
;
1491 ms
->par_in
->codec_tag
= tag
;
1493 ost
->enc
->enc_ctx
->codec_tag
= tag
;
1496 opt_match_per_stream_dbl(ost
, &o
->qscale
, oc
, st
, &qscale
);
1497 if (ost
->enc
&& qscale
>= 0) {
1498 ost
->enc
->enc_ctx
->flags
|= AV_CODEC_FLAG_QSCALE
;
1499 ost
->enc
->enc_ctx
->global_quality
= FF_QP2LAMBDA
* qscale
;
1502 if (ms
->sch_idx
>= 0) {
1503 int max_muxing_queue_size
= 128;
1504 int muxing_queue_data_threshold
= 50 * 1024 * 1024;
1506 opt_match_per_stream_int(ost
, &o
->max_muxing_queue_size
, oc
, st
,
1507 &max_muxing_queue_size
);
1508 opt_match_per_stream_int(ost
, &o
->muxing_queue_data_threshold
,
1509 oc
, st
, &muxing_queue_data_threshold
);
1511 sch_mux_stream_buffering(mux
->sch
, mux
->sch_idx
, ms
->sch_idx
,
1512 max_muxing_queue_size
, muxing_queue_data_threshold
);
1515 opt_match_per_stream_int(ost
, &o
->bits_per_raw_sample
, oc
, st
,
1516 &ost
->bits_per_raw_sample
);
1518 opt_match_per_stream_int(ost
, &o
->fix_sub_duration_heartbeat
,
1519 oc
, st
, &ost
->fix_sub_duration_heartbeat
);
1521 if (oc
->oformat
->flags
& AVFMT_GLOBALHEADER
&& ost
->enc
)
1522 ost
->enc
->enc_ctx
->flags
|= AV_CODEC_FLAG_GLOBAL_HEADER
;
1524 opt_match_per_stream_int(ost
, &o
->copy_initial_nonkeyframes
,
1525 oc
, st
, &ms
->copy_initial_nonkeyframes
);
1527 case AVMEDIA_TYPE_VIDEO
: ret
= new_stream_video (mux
, o
, ost
, &keep_pix_fmt
, &vsync_method
); break;
1528 case AVMEDIA_TYPE_AUDIO
: ret
= new_stream_audio (mux
, o
, ost
); break;
1529 case AVMEDIA_TYPE_SUBTITLE
: ret
= new_stream_subtitle (mux
, o
, ost
); break;
1535 (type
== AVMEDIA_TYPE_VIDEO
|| type
== AVMEDIA_TYPE_AUDIO
)) {
1536 ret
= ost_bind_filter(mux
, ms
, ofilter
, o
, enc_tb
, vsync_method
,
1537 keep_pix_fmt
, autoscale
, threads_manual
, vs
, &src
);
1540 } else if (ost
->ist
) {
1541 ret
= ist_use(ost
->ist
, !!ost
->enc
, NULL
, &src
);
1543 av_log(ost
, AV_LOG_ERROR
,
1544 "Error binding an input stream\n");
1547 ms
->sch_idx_src
= src
.idx
;
1549 // src refers to a decoder for transcoding, demux stream otherwise
1551 ret
= sch_connect(mux
->sch
,
1552 src
, SCH_ENC(ms
->sch_idx_enc
));
1555 src
= SCH_ENC(ms
->sch_idx_enc
);
1559 if (src
.type
!= SCH_NODE_TYPE_NONE
) {
1560 ret
= sch_connect(mux
->sch
,
1561 src
, SCH_MSTREAM(mux
->sch_idx
, ms
->sch_idx
));
1565 // only attachment streams don't have a source
1566 av_assert0(type
== AVMEDIA_TYPE_ATTACHMENT
&& ms
->sch_idx
< 0);
1569 if (ost
->ist
&& !ost
->enc
) {
1570 ret
= streamcopy_init(o
, mux
, ost
, &encoder_opts
);
1575 // copy estimated duration as a hint to the muxer
1576 if (ost
->ist
&& ost
->ist
->st
->duration
> 0) {
1577 ms
->stream_duration
= ist
->st
->duration
;
1578 ms
->stream_duration_tb
= ist
->st
->time_base
;
1587 av_dict_free(&encoder_opts
);
1592 static int map_auto_video(Muxer
*mux
, const OptionsContext
*o
)
1594 AVFormatContext
*oc
= mux
->fc
;
1595 InputStream
*best_ist
= NULL
;
1599 /* video: highest resolution */
1600 if (av_guess_codec(oc
->oformat
, NULL
, oc
->url
, NULL
, AVMEDIA_TYPE_VIDEO
) == AV_CODEC_ID_NONE
)
1603 qcr
= avformat_query_codec(oc
->oformat
, oc
->oformat
->video_codec
, 0);
1604 for (int j
= 0; j
< nb_input_files
; j
++) {
1605 InputFile
*ifile
= input_files
[j
];
1606 InputStream
*file_best_ist
= NULL
;
1607 int file_best_score
= 0;
1608 for (int i
= 0; i
< ifile
->nb_streams
; i
++) {
1609 InputStream
*ist
= ifile
->streams
[i
];
1612 if (ist
->user_set_discard
== AVDISCARD_ALL
||
1613 ist
->st
->codecpar
->codec_type
!= AVMEDIA_TYPE_VIDEO
)
1616 score
= ist
->st
->codecpar
->width
* ist
->st
->codecpar
->height
1617 + 100000000 * !!(ist
->st
->event_flags
& AVSTREAM_EVENT_FLAG_NEW_PACKETS
)
1618 + 5000000*!!(ist
->st
->disposition
& AV_DISPOSITION_DEFAULT
);
1619 if((qcr
!=MKTAG('A', 'P', 'I', 'C')) && (ist
->st
->disposition
& AV_DISPOSITION_ATTACHED_PIC
))
1622 if (score
> file_best_score
) {
1623 if((qcr
==MKTAG('A', 'P', 'I', 'C')) && !(ist
->st
->disposition
& AV_DISPOSITION_ATTACHED_PIC
))
1625 file_best_score
= score
;
1626 file_best_ist
= ist
;
1629 if (file_best_ist
) {
1630 if((qcr
== MKTAG('A', 'P', 'I', 'C')) ||
1631 !(file_best_ist
->st
->disposition
& AV_DISPOSITION_ATTACHED_PIC
))
1632 file_best_score
-= 5000000*!!(file_best_ist
->st
->disposition
& AV_DISPOSITION_DEFAULT
);
1633 if (file_best_score
> best_score
) {
1634 best_score
= file_best_score
;
1635 best_ist
= file_best_ist
;
1640 return ost_add(mux
, o
, AVMEDIA_TYPE_VIDEO
, best_ist
, NULL
, NULL
, NULL
);
1645 static int map_auto_audio(Muxer
*mux
, const OptionsContext
*o
)
1647 AVFormatContext
*oc
= mux
->fc
;
1648 InputStream
*best_ist
= NULL
;
1651 /* audio: most channels */
1652 if (av_guess_codec(oc
->oformat
, NULL
, oc
->url
, NULL
, AVMEDIA_TYPE_AUDIO
) == AV_CODEC_ID_NONE
)
1655 for (int j
= 0; j
< nb_input_files
; j
++) {
1656 InputFile
*ifile
= input_files
[j
];
1657 InputStream
*file_best_ist
= NULL
;
1658 int file_best_score
= 0;
1659 for (int i
= 0; i
< ifile
->nb_streams
; i
++) {
1660 InputStream
*ist
= ifile
->streams
[i
];
1663 if (ist
->user_set_discard
== AVDISCARD_ALL
||
1664 ist
->st
->codecpar
->codec_type
!= AVMEDIA_TYPE_AUDIO
)
1667 score
= ist
->st
->codecpar
->ch_layout
.nb_channels
1668 + 100000000 * !!(ist
->st
->event_flags
& AVSTREAM_EVENT_FLAG_NEW_PACKETS
)
1669 + 5000000*!!(ist
->st
->disposition
& AV_DISPOSITION_DEFAULT
);
1670 if (score
> file_best_score
) {
1671 file_best_score
= score
;
1672 file_best_ist
= ist
;
1675 if (file_best_ist
) {
1676 file_best_score
-= 5000000*!!(file_best_ist
->st
->disposition
& AV_DISPOSITION_DEFAULT
);
1677 if (file_best_score
> best_score
) {
1678 best_score
= file_best_score
;
1679 best_ist
= file_best_ist
;
1684 return ost_add(mux
, o
, AVMEDIA_TYPE_AUDIO
, best_ist
, NULL
, NULL
, NULL
);
1689 static int map_auto_subtitle(Muxer
*mux
, const OptionsContext
*o
)
1691 AVFormatContext
*oc
= mux
->fc
;
1692 const char *subtitle_codec_name
= NULL
;
1694 /* subtitles: pick first */
1695 subtitle_codec_name
= opt_match_per_type_str(&o
->codec_names
, 's');
1696 if (!avcodec_find_encoder(oc
->oformat
->subtitle_codec
) && !subtitle_codec_name
)
1699 for (InputStream
*ist
= ist_iter(NULL
); ist
; ist
= ist_iter(ist
))
1700 if (ist
->st
->codecpar
->codec_type
== AVMEDIA_TYPE_SUBTITLE
) {
1701 AVCodecDescriptor
const *input_descriptor
=
1702 avcodec_descriptor_get(ist
->st
->codecpar
->codec_id
);
1703 AVCodecDescriptor
const *output_descriptor
= NULL
;
1704 AVCodec
const *output_codec
=
1705 avcodec_find_encoder(oc
->oformat
->subtitle_codec
);
1706 int input_props
= 0, output_props
= 0;
1707 if (ist
->user_set_discard
== AVDISCARD_ALL
)
1710 output_descriptor
= avcodec_descriptor_get(output_codec
->id
);
1711 if (input_descriptor
)
1712 input_props
= input_descriptor
->props
& (AV_CODEC_PROP_TEXT_SUB
| AV_CODEC_PROP_BITMAP_SUB
);
1713 if (output_descriptor
)
1714 output_props
= output_descriptor
->props
& (AV_CODEC_PROP_TEXT_SUB
| AV_CODEC_PROP_BITMAP_SUB
);
1715 if (subtitle_codec_name
||
1716 input_props
& output_props
||
1717 // Map dvb teletext which has neither property to any output subtitle encoder
1718 input_descriptor
&& output_descriptor
&&
1719 (!input_descriptor
->props
||
1720 !output_descriptor
->props
)) {
1721 return ost_add(mux
, o
, AVMEDIA_TYPE_SUBTITLE
, ist
, NULL
, NULL
, NULL
);
1728 static int map_auto_data(Muxer
*mux
, const OptionsContext
*o
)
1730 AVFormatContext
*oc
= mux
->fc
;
1731 /* Data only if codec id match */
1732 enum AVCodecID codec_id
= av_guess_codec(oc
->oformat
, NULL
, oc
->url
, NULL
, AVMEDIA_TYPE_DATA
);
1734 if (codec_id
== AV_CODEC_ID_NONE
)
1737 for (InputStream
*ist
= ist_iter(NULL
); ist
; ist
= ist_iter(ist
)) {
1738 if (ist
->user_set_discard
== AVDISCARD_ALL
)
1740 if (ist
->st
->codecpar
->codec_type
== AVMEDIA_TYPE_DATA
&&
1741 ist
->st
->codecpar
->codec_id
== codec_id
) {
1742 int ret
= ost_add(mux
, o
, AVMEDIA_TYPE_DATA
, ist
, NULL
, NULL
, NULL
);
1751 static int map_manual(Muxer
*mux
, const OptionsContext
*o
, const StreamMap
*map
)
1759 if (map
->linklabel
) {
1761 OutputFilter
*ofilter
= NULL
;
1764 for (j
= 0; j
< nb_filtergraphs
; j
++) {
1765 fg
= filtergraphs
[j
];
1766 for (k
= 0; k
< fg
->nb_outputs
; k
++) {
1767 const char *linklabel
= fg
->outputs
[k
]->linklabel
;
1768 if (linklabel
&& !strcmp(linklabel
, map
->linklabel
)) {
1769 ofilter
= fg
->outputs
[k
];
1776 av_log(mux
, AV_LOG_FATAL
, "Output with label '%s' does not exist "
1777 "in any defined filter graph, or was already used elsewhere.\n", map
->linklabel
);
1778 return AVERROR(EINVAL
);
1781 av_log(mux
, AV_LOG_VERBOSE
, "Creating output stream from an explicitly "
1782 "mapped complex filtergraph %d, output [%s]\n", fg
->index
, map
->linklabel
);
1784 ret
= ost_add(mux
, o
, ofilter
->type
, NULL
, ofilter
, NULL
, NULL
);
1788 const ViewSpecifier
*vs
= map
->vs
.type
== VIEW_SPECIFIER_TYPE_NONE
?
1791 ist
= input_files
[map
->file_index
]->streams
[map
->stream_index
];
1792 if (ist
->user_set_discard
== AVDISCARD_ALL
) {
1793 av_log(mux
, AV_LOG_FATAL
, "Stream #%d:%d is disabled and cannot be mapped.\n",
1794 map
->file_index
, map
->stream_index
);
1795 return AVERROR(EINVAL
);
1797 if(o
->subtitle_disable
&& ist
->st
->codecpar
->codec_type
== AVMEDIA_TYPE_SUBTITLE
)
1799 if(o
-> audio_disable
&& ist
->st
->codecpar
->codec_type
== AVMEDIA_TYPE_AUDIO
)
1801 if(o
-> video_disable
&& ist
->st
->codecpar
->codec_type
== AVMEDIA_TYPE_VIDEO
)
1803 if(o
-> data_disable
&& ist
->st
->codecpar
->codec_type
== AVMEDIA_TYPE_DATA
)
1806 if (ist
->st
->codecpar
->codec_type
== AVMEDIA_TYPE_UNKNOWN
&&
1807 !copy_unknown_streams
) {
1808 av_log(mux
, ignore_unknown_streams
? AV_LOG_WARNING
: AV_LOG_FATAL
,
1809 "Cannot map stream #%d:%d - unsupported type.\n",
1810 map
->file_index
, map
->stream_index
);
1811 if (!ignore_unknown_streams
) {
1812 av_log(mux
, AV_LOG_FATAL
,
1813 "If you want unsupported types ignored instead "
1814 "of failing, please use the -ignore_unknown option\n"
1815 "If you want them copied, please use -copy_unknown\n");
1816 return AVERROR(EINVAL
);
1821 if (vs
&& ist
->st
->codecpar
->codec_type
!= AVMEDIA_TYPE_VIDEO
) {
1822 av_log(mux
, AV_LOG_ERROR
,
1823 "View specifier given for mapping a %s input stream\n",
1824 av_get_media_type_string(ist
->st
->codecpar
->codec_type
));
1825 return AVERROR(EINVAL
);
1828 ret
= ost_add(mux
, o
, ist
->st
->codecpar
->codec_type
, ist
, NULL
, vs
, NULL
);
1836 static int of_add_attachments(Muxer
*mux
, const OptionsContext
*o
)
1842 for (int i
= 0; i
< o
->nb_attachments
; i
++) {
1844 uint8_t *attachment
;
1845 char *attachment_filename
;
1849 if ((err
= avio_open2(&pb
, o
->attachments
[i
], AVIO_FLAG_READ
, &int_cb
, NULL
)) < 0) {
1850 av_log(mux
, AV_LOG_FATAL
, "Could not open attachment file %s.\n",
1854 if ((len
= avio_size(pb
)) <= 0) {
1855 av_log(mux
, AV_LOG_FATAL
, "Could not get size of the attachment %s.\n",
1857 err
= len
? len
: AVERROR_INVALIDDATA
;
1860 if (len
> INT_MAX
- AV_INPUT_BUFFER_PADDING_SIZE
) {
1861 av_log(mux
, AV_LOG_FATAL
, "Attachment %s too large.\n",
1863 err
= AVERROR(ERANGE
);
1867 attachment
= av_malloc(len
+ AV_INPUT_BUFFER_PADDING_SIZE
);
1869 err
= AVERROR(ENOMEM
);
1873 err
= avio_read(pb
, attachment
, len
);
1875 av_log(mux
, AV_LOG_FATAL
, "Error reading attachment file %s: %s\n",
1876 o
->attachments
[i
], av_err2str(err
));
1877 else if (err
!= len
) {
1878 av_log(mux
, AV_LOG_FATAL
, "Could not read all %"PRId64
" bytes for "
1879 "attachment file %s\n", len
, o
->attachments
[i
]);
1888 memset(attachment
+ len
, 0, AV_INPUT_BUFFER_PADDING_SIZE
);
1890 av_log(mux
, AV_LOG_VERBOSE
, "Creating attachment stream from file %s\n",
1893 attachment_filename
= av_strdup(o
->attachments
[i
]);
1894 if (!attachment_filename
) {
1895 av_free(attachment
);
1896 return AVERROR(ENOMEM
);
1899 err
= ost_add(mux
, o
, AVMEDIA_TYPE_ATTACHMENT
, NULL
, NULL
, NULL
, &ost
);
1901 av_free(attachment_filename
);
1902 av_freep(&attachment
);
1906 ms
= ms_from_ost(ost
);
1908 ost
->attachment_filename
= attachment_filename
;
1909 ms
->par_in
->extradata
= attachment
;
1910 ms
->par_in
->extradata_size
= len
;
1912 p
= strrchr(o
->attachments
[i
], '/');
1913 av_dict_set(&ost
->st
->metadata
, "filename", (p
&& *p
) ? p
+ 1 : o
->attachments
[i
], AV_DICT_DONT_OVERWRITE
);
1919 static int create_streams(Muxer
*mux
, const OptionsContext
*o
)
1921 static int (* const map_func
[])(Muxer
*mux
, const OptionsContext
*o
) = {
1922 [AVMEDIA_TYPE_VIDEO
] = map_auto_video
,
1923 [AVMEDIA_TYPE_AUDIO
] = map_auto_audio
,
1924 [AVMEDIA_TYPE_SUBTITLE
] = map_auto_subtitle
,
1925 [AVMEDIA_TYPE_DATA
] = map_auto_data
,
1928 AVFormatContext
*oc
= mux
->fc
;
1931 o
->video_disable
* (1 << AVMEDIA_TYPE_VIDEO
) |
1932 o
->audio_disable
* (1 << AVMEDIA_TYPE_AUDIO
) |
1933 o
->subtitle_disable
* (1 << AVMEDIA_TYPE_SUBTITLE
) |
1934 o
->data_disable
* (1 << AVMEDIA_TYPE_DATA
);
1938 /* create streams for all unlabeled output pads */
1939 for (int i
= 0; i
< nb_filtergraphs
; i
++) {
1940 FilterGraph
*fg
= filtergraphs
[i
];
1941 for (int j
= 0; j
< fg
->nb_outputs
; j
++) {
1942 OutputFilter
*ofilter
= fg
->outputs
[j
];
1944 if (ofilter
->linklabel
|| ofilter
->bound
)
1947 auto_disable
|= 1 << ofilter
->type
;
1949 av_log(mux
, AV_LOG_VERBOSE
, "Creating output stream from unlabeled "
1950 "output of complex filtergraph %d.", fg
->index
);
1951 if (!o
->nb_stream_maps
)
1952 av_log(mux
, AV_LOG_VERBOSE
, " This overrides automatic %s mapping.",
1953 av_get_media_type_string(ofilter
->type
));
1954 av_log(mux
, AV_LOG_VERBOSE
, "\n");
1956 ret
= ost_add(mux
, o
, ofilter
->type
, NULL
, ofilter
, NULL
, NULL
);
1962 if (!o
->nb_stream_maps
) {
1963 av_log(mux
, AV_LOG_VERBOSE
, "No explicit maps, mapping streams automatically...\n");
1965 /* pick the "best" stream of each type */
1966 for (int i
= 0; i
< FF_ARRAY_ELEMS(map_func
); i
++) {
1967 if (!map_func
[i
] || auto_disable
& (1 << i
))
1969 ret
= map_func
[i
](mux
, o
);
1974 av_log(mux
, AV_LOG_VERBOSE
, "Adding streams from explicit maps...\n");
1976 for (int i
= 0; i
< o
->nb_stream_maps
; i
++) {
1977 ret
= map_manual(mux
, o
, &o
->stream_maps
[i
]);
1983 ret
= of_add_attachments(mux
, o
);
1987 // setup fix_sub_duration_heartbeat mappings
1988 for (unsigned i
= 0; i
< oc
->nb_streams
; i
++) {
1989 MuxStream
*src
= ms_from_ost(mux
->of
.streams
[i
]);
1991 if (!src
->ost
.fix_sub_duration_heartbeat
)
1994 for (unsigned j
= 0; j
< oc
->nb_streams
; j
++) {
1995 MuxStream
*dst
= ms_from_ost(mux
->of
.streams
[j
]);
1997 if (src
== dst
|| dst
->ost
.type
!= AVMEDIA_TYPE_SUBTITLE
||
1998 !dst
->ost
.enc
|| !dst
->ost
.ist
|| !dst
->ost
.ist
->fix_sub_duration
)
2001 ret
= sch_mux_sub_heartbeat_add(mux
->sch
, mux
->sch_idx
, src
->sch_idx
,
2011 for (unsigned i
= 0; i
< mux
->of
.nb_streams
; i
++)
2012 if (mux
->of
.streams
[i
]->type
== AVMEDIA_TYPE_VIDEO
) {
2017 for (unsigned i
= 0; have_video
&& i
< mux
->of
.nb_streams
; i
++) {
2018 MuxStream
*ms
= ms_from_ost(mux
->of
.streams
[i
]);
2019 OutputFilter
*ofilter
= ms
->ost
.filter
;
2021 if (ms
->ost
.type
!= AVMEDIA_TYPE_AUDIO
|| !ms
->apad
|| !ofilter
)
2024 ofilter
->apad
= av_strdup(ms
->apad
);
2026 return AVERROR(ENOMEM
);
2029 for (unsigned i
= 0; i
< mux
->of
.nb_streams
; i
++) {
2030 MuxStream
*ms
= ms_from_ost(mux
->of
.streams
[i
]);
2034 if (!oc
->nb_streams
&& !(oc
->oformat
->flags
& AVFMT_NOSTREAMS
)) {
2035 av_dump_format(oc
, nb_output_files
- 1, oc
->url
, 1);
2036 av_log(mux
, AV_LOG_ERROR
, "Output file does not contain any stream\n");
2037 return AVERROR(EINVAL
);
2043 static int setup_sync_queues(Muxer
*mux
, AVFormatContext
*oc
,
2044 int64_t buf_size_us
, int shortest
)
2046 OutputFile
*of
= &mux
->of
;
2047 int nb_av_enc
= 0, nb_audio_fs
= 0, nb_interleaved
= 0;
2048 int limit_frames
= 0, limit_frames_av_enc
= 0;
2050 #define IS_AV_ENC(ost, type) \
2051 (ost->enc && (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO))
2052 #define IS_INTERLEAVED(type) (type != AVMEDIA_TYPE_ATTACHMENT)
2054 for (int i
= 0; i
< oc
->nb_streams
; i
++) {
2055 OutputStream
*ost
= of
->streams
[i
];
2056 MuxStream
*ms
= ms_from_ost(ost
);
2057 enum AVMediaType type
= ost
->type
;
2059 ms
->sq_idx_mux
= -1;
2061 nb_interleaved
+= IS_INTERLEAVED(type
);
2062 nb_av_enc
+= IS_AV_ENC(ost
, type
);
2063 nb_audio_fs
+= (ost
->enc
&& type
== AVMEDIA_TYPE_AUDIO
&&
2064 !(ost
->enc
->enc_ctx
->codec
->capabilities
& AV_CODEC_CAP_VARIABLE_FRAME_SIZE
));
2066 limit_frames
|= ms
->max_frames
< INT64_MAX
;
2067 limit_frames_av_enc
|= (ms
->max_frames
< INT64_MAX
) && IS_AV_ENC(ost
, type
);
2070 if (!((nb_interleaved
> 1 && shortest
) ||
2071 (nb_interleaved
> 0 && limit_frames
) ||
2075 /* we use a sync queue before encoding when:
2076 * - 'shortest' is in effect and we have two or more encoded audio/video
2078 * - at least one encoded audio/video stream is frame-limited, since
2079 * that has similar semantics to 'shortest'
2080 * - at least one audio encoder requires constant frame sizes
2082 * Note that encoding sync queues are handled in the scheduler, because
2083 * different encoders run in different threads and need external
2084 * synchronization, while muxer sync queues can be handled inside the muxer
2086 if ((shortest
&& nb_av_enc
> 1) || limit_frames_av_enc
|| nb_audio_fs
) {
2089 sq_idx
= sch_add_sq_enc(mux
->sch
, buf_size_us
, mux
);
2093 for (int i
= 0; i
< oc
->nb_streams
; i
++) {
2094 OutputStream
*ost
= of
->streams
[i
];
2095 MuxStream
*ms
= ms_from_ost(ost
);
2096 enum AVMediaType type
= ost
->type
;
2098 if (!IS_AV_ENC(ost
, type
))
2101 ret
= sch_sq_add_enc(mux
->sch
, sq_idx
, ms
->sch_idx_enc
,
2102 shortest
|| ms
->max_frames
< INT64_MAX
,
2109 /* if there are any additional interleaved streams, then ALL the streams
2110 * are also synchronized before sending them to the muxer */
2111 if (nb_interleaved
> nb_av_enc
) {
2112 mux
->sq_mux
= sq_alloc(SYNC_QUEUE_PACKETS
, buf_size_us
, mux
);
2114 return AVERROR(ENOMEM
);
2116 mux
->sq_pkt
= av_packet_alloc();
2118 return AVERROR(ENOMEM
);
2120 for (int i
= 0; i
< oc
->nb_streams
; i
++) {
2121 OutputStream
*ost
= of
->streams
[i
];
2122 MuxStream
*ms
= ms_from_ost(ost
);
2123 enum AVMediaType type
= ost
->type
;
2125 if (!IS_INTERLEAVED(type
))
2128 ms
->sq_idx_mux
= sq_add_stream(mux
->sq_mux
,
2129 shortest
|| ms
->max_frames
< INT64_MAX
);
2130 if (ms
->sq_idx_mux
< 0)
2131 return ms
->sq_idx_mux
;
2133 if (ms
->max_frames
!= INT64_MAX
)
2134 sq_limit_frames(mux
->sq_mux
, ms
->sq_idx_mux
, ms
->max_frames
);
2139 #undef IS_INTERLEAVED
2144 static int of_parse_iamf_audio_element_layers(Muxer
*mux
, AVStreamGroup
*stg
, char *ptr
)
2146 AVIAMFAudioElement
*audio_element
= stg
->params
.iamf_audio_element
;
2147 AVDictionary
*dict
= NULL
;
2151 audio_element
->demixing_info
=
2152 av_iamf_param_definition_alloc(AV_IAMF_PARAMETER_DEFINITION_DEMIXING
, 1, NULL
);
2153 audio_element
->recon_gain_info
=
2154 av_iamf_param_definition_alloc(AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN
, 1, NULL
);
2156 if (!audio_element
->demixing_info
||
2157 !audio_element
->recon_gain_info
)
2158 return AVERROR(ENOMEM
);
2160 /* process manually set layers and parameters */
2161 token
= av_strtok(NULL
, ",", &ptr
);
2163 const AVDictionaryEntry
*e
;
2164 int demixing
= 0, recon_gain
= 0;
2168 ptr
+= strspn(ptr
, " \n\t\r");
2169 if (av_strstart(token
, "layer=", &token
))
2171 else if (av_strstart(token
, "demixing=", &token
))
2173 else if (av_strstart(token
, "recon_gain=", &token
))
2176 av_dict_free(&dict
);
2177 ret
= av_dict_parse_string(&dict
, token
, "=", ":", 0);
2179 av_log(mux
, AV_LOG_ERROR
, "Error parsing audio element specification %s\n", token
);
2184 AVIAMFLayer
*audio_layer
= av_iamf_audio_element_add_layer(audio_element
);
2186 av_log(mux
, AV_LOG_ERROR
, "Error adding layer to stream group %d\n", stg
->index
);
2187 ret
= AVERROR(ENOMEM
);
2190 av_opt_set_dict(audio_layer
, &dict
);
2191 } else if (demixing
|| recon_gain
) {
2192 AVIAMFParamDefinition
*param
= demixing
? audio_element
->demixing_info
2193 : audio_element
->recon_gain_info
;
2194 void *subblock
= av_iamf_param_definition_get_subblock(param
, 0);
2196 av_opt_set_dict(param
, &dict
);
2197 av_opt_set_dict(subblock
, &dict
);
2200 // make sure that no entries are left in the dict
2202 if (e
= av_dict_iterate(dict
, e
)) {
2203 av_log(mux
, AV_LOG_FATAL
, "Unknown layer key %s.\n", e
->key
);
2204 ret
= AVERROR(EINVAL
);
2207 token
= av_strtok(NULL
, ",", &ptr
);
2211 av_dict_free(&dict
);
2212 if (!ret
&& !audio_element
->nb_layers
) {
2213 av_log(mux
, AV_LOG_ERROR
, "No layer in audio element specification\n");
2214 ret
= AVERROR(EINVAL
);
2220 static int of_parse_iamf_submixes(Muxer
*mux
, AVStreamGroup
*stg
, char *ptr
)
2222 AVFormatContext
*oc
= mux
->fc
;
2223 AVIAMFMixPresentation
*mix
= stg
->params
.iamf_mix_presentation
;
2224 AVDictionary
*dict
= NULL
;
2226 char *submix_str
= NULL
;
2229 /* process manually set submixes */
2230 token
= av_strtok(NULL
, ",", &ptr
);
2232 AVIAMFSubmix
*submix
= NULL
;
2233 const char *subtoken
;
2234 char *subptr
= NULL
;
2237 ptr
+= strspn(ptr
, " \n\t\r");
2238 if (!av_strstart(token
, "submix=", &token
)) {
2239 av_log(mux
, AV_LOG_ERROR
, "No submix in mix presentation specification \"%s\"\n", token
);
2243 submix_str
= av_strdup(token
);
2247 submix
= av_iamf_mix_presentation_add_submix(mix
);
2249 av_log(mux
, AV_LOG_ERROR
, "Error adding submix to stream group %d\n", stg
->index
);
2250 ret
= AVERROR(ENOMEM
);
2253 submix
->output_mix_config
=
2254 av_iamf_param_definition_alloc(AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN
, 0, NULL
);
2255 if (!submix
->output_mix_config
) {
2256 ret
= AVERROR(ENOMEM
);
2261 subtoken
= av_strtok(submix_str
, "|", &subptr
);
2263 const AVDictionaryEntry
*e
;
2264 int element
= 0, layout
= 0;
2267 subptr
+= strspn(subptr
, " \n\t\r");
2268 if (av_strstart(subtoken
, "element=", &subtoken
))
2270 else if (av_strstart(subtoken
, "layout=", &subtoken
))
2273 av_dict_free(&dict
);
2274 ret
= av_dict_parse_string(&dict
, subtoken
, "=", ":", 0);
2276 av_log(mux
, AV_LOG_ERROR
, "Error parsing submix specification \"%s\"\n", subtoken
);
2281 AVIAMFSubmixElement
*submix_element
;
2282 char *endptr
= NULL
;
2285 if (e
= av_dict_get(dict
, "stg", NULL
, 0))
2286 idx
= strtoll(e
->value
, &endptr
, 0);
2287 if (!endptr
|| *endptr
|| idx
< 0 || idx
>= oc
->nb_stream_groups
- 1 ||
2288 oc
->stream_groups
[idx
]->type
!= AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT
) {
2289 av_log(mux
, AV_LOG_ERROR
, "Invalid or missing stream group index in "
2290 "submix element specification \"%s\"\n", subtoken
);
2291 ret
= AVERROR(EINVAL
);
2294 submix_element
= av_iamf_submix_add_element(submix
);
2295 if (!submix_element
) {
2296 av_log(mux
, AV_LOG_ERROR
, "Error adding element to submix\n");
2297 ret
= AVERROR(ENOMEM
);
2301 submix_element
->audio_element_id
= oc
->stream_groups
[idx
]->id
;
2303 submix_element
->element_mix_config
=
2304 av_iamf_param_definition_alloc(AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN
, 0, NULL
);
2305 if (!submix_element
->element_mix_config
)
2306 ret
= AVERROR(ENOMEM
);
2307 av_dict_set(&dict
, "stg", NULL
, 0);
2308 av_opt_set_dict2(submix_element
, &dict
, AV_OPT_SEARCH_CHILDREN
);
2309 } else if (layout
) {
2310 AVIAMFSubmixLayout
*submix_layout
= av_iamf_submix_add_layout(submix
);
2311 if (!submix_layout
) {
2312 av_log(mux
, AV_LOG_ERROR
, "Error adding layout to submix\n");
2313 ret
= AVERROR(ENOMEM
);
2316 av_opt_set_dict(submix_layout
, &dict
);
2318 av_opt_set_dict2(submix
, &dict
, AV_OPT_SEARCH_CHILDREN
);
2324 // make sure that no entries are left in the dict
2326 while (e
= av_dict_iterate(dict
, e
)) {
2327 av_log(mux
, AV_LOG_FATAL
, "Unknown submix key %s.\n", e
->key
);
2328 ret
= AVERROR(EINVAL
);
2331 subtoken
= av_strtok(NULL
, "|", &subptr
);
2333 av_freep(&submix_str
);
2335 if (!submix
->nb_elements
) {
2336 av_log(mux
, AV_LOG_ERROR
, "No audio elements in submix specification \"%s\"\n", token
);
2337 ret
= AVERROR(EINVAL
);
2339 token
= av_strtok(NULL
, ",", &ptr
);
2343 av_dict_free(&dict
);
2344 av_free(submix_str
);
2349 static int of_serialize_options(Muxer
*mux
, void *obj
, AVBPrint
*bp
)
2354 ret
= av_opt_serialize(obj
, 0, AV_OPT_SERIALIZE_SKIP_DEFAULTS
| AV_OPT_SERIALIZE_SEARCH_CHILDREN
,
2357 av_log(mux
, AV_LOG_ERROR
, "Failed to serialize group\n");
2361 av_bprintf(bp
, "%s", ptr
);
2368 #define SERIALIZE(parent, child) do { \
2369 ret = of_serialize_options(mux, parent->child, bp); \
2374 #define SERIALIZE_LOOP_SUBBLOCK(obj) do { \
2375 for (int k = 0; k < obj->nb_subblocks; k++) { \
2376 ret = of_serialize_options(mux, \
2377 av_iamf_param_definition_get_subblock(obj, k), bp); \
2383 #define SERIALIZE_LOOP(parent, child, suffix, separator) do { \
2384 for (int j = 0; j < parent->nb_## child ## suffix; j++) { \
2385 av_bprintf(bp, separator#child "="); \
2386 SERIALIZE(parent, child ## suffix[j]); \
2390 static int64_t get_stream_group_index_from_id(Muxer
*mux
, int64_t id
)
2392 AVFormatContext
*oc
= mux
->fc
;
2394 for (unsigned i
= 0; i
< oc
->nb_stream_groups
; i
++)
2395 if (oc
->stream_groups
[i
]->id
== id
)
2396 return oc
->stream_groups
[i
]->index
;
2398 return AVERROR(EINVAL
);
2401 static int of_map_group(Muxer
*mux
, AVDictionary
**dict
, AVBPrint
*bp
, const char *map
)
2404 int ret
, file_idx
, stream_idx
;
2407 file_idx
= strtol(map
, &ptr
, 0);
2408 if (file_idx
>= nb_input_files
|| file_idx
< 0 || map
== ptr
) {
2409 av_log(mux
, AV_LOG_ERROR
, "Invalid input file index: %d.\n", file_idx
);
2410 return AVERROR(EINVAL
);
2413 stream_idx
= strtol(*ptr
== '=' ? ptr
+ 1 : ptr
, &ptr
, 0);
2414 if (*ptr
|| stream_idx
>= input_files
[file_idx
]->ctx
->nb_stream_groups
|| stream_idx
< 0) {
2415 av_log(mux
, AV_LOG_ERROR
, "Invalid input stream group index: %d.\n", stream_idx
);
2416 return AVERROR(EINVAL
);
2419 stg
= input_files
[file_idx
]->ctx
->stream_groups
[stream_idx
];
2420 ret
= of_serialize_options(mux
, stg
, bp
);
2424 ret
= av_dict_parse_string(dict
, bp
->str
, "=", ":", 0);
2426 av_log(mux
, AV_LOG_ERROR
, "Error parsing mapped group specification %s\n", ptr
);
2427 av_dict_set_int(dict
, "type", stg
->type
, 0);
2429 av_bprint_clear(bp
);
2431 case AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT
: {
2432 AVIAMFAudioElement
*audio_element
= stg
->params
.iamf_audio_element
;
2434 if (audio_element
->demixing_info
) {
2435 AVIAMFParamDefinition
*demixing_info
= audio_element
->demixing_info
;
2436 av_bprintf(bp
, ",demixing=");
2437 SERIALIZE(audio_element
, demixing_info
);
2438 if (ret
&& demixing_info
->nb_subblocks
)
2439 av_bprintf(bp
, ":");
2440 SERIALIZE_LOOP_SUBBLOCK(demixing_info
);
2442 if (audio_element
->recon_gain_info
) {
2443 AVIAMFParamDefinition
*recon_gain_info
= audio_element
->recon_gain_info
;
2444 av_bprintf(bp
, ",recon_gain=");
2445 SERIALIZE(audio_element
, recon_gain_info
);
2446 if (ret
&& recon_gain_info
->nb_subblocks
)
2447 av_bprintf(bp
, ":");
2448 SERIALIZE_LOOP_SUBBLOCK(recon_gain_info
);
2450 SERIALIZE_LOOP(audio_element
, layer
, s
, ",");
2453 case AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION
: {
2454 AVIAMFMixPresentation
*mix
= stg
->params
.iamf_mix_presentation
;
2456 for (int i
= 0; i
< mix
->nb_submixes
; i
++) {
2457 AVIAMFSubmix
*submix
= mix
->submixes
[i
];
2458 AVIAMFParamDefinition
*output_mix_config
= submix
->output_mix_config
;
2460 av_bprintf(bp
, ",submix=");
2461 SERIALIZE(mix
, submixes
[i
]);
2462 if (ret
&& output_mix_config
->nb_subblocks
)
2463 av_bprintf(bp
, ":");
2464 SERIALIZE_LOOP_SUBBLOCK(output_mix_config
);
2465 for (int j
= 0; j
< submix
->nb_elements
; j
++) {
2466 AVIAMFSubmixElement
*element
= submix
->elements
[j
];
2467 AVIAMFParamDefinition
*element_mix_config
= element
->element_mix_config
;
2468 int64_t id
= get_stream_group_index_from_id(mux
, element
->audio_element_id
);
2471 av_log(mux
, AV_LOG_ERROR
, "Invalid or missing stream group index in"
2476 av_bprintf(bp
, "|element=");
2477 SERIALIZE(submix
, elements
[j
]);
2478 if (ret
&& element_mix_config
->nb_subblocks
)
2479 av_bprintf(bp
, ":");
2480 SERIALIZE_LOOP_SUBBLOCK(element_mix_config
);
2482 av_bprintf(bp
, ":");
2483 av_bprintf(bp
, "stg=%"PRId64
, id
);
2485 SERIALIZE_LOOP(submix
, layout
, s
, "|");
2490 av_log(mux
, AV_LOG_ERROR
, "Unsupported mapped group type %d.\n", stg
->type
);
2491 ret
= AVERROR(EINVAL
);
2497 static int of_parse_group_token(Muxer
*mux
, const char *token
, char *ptr
)
2499 AVFormatContext
*oc
= mux
->fc
;
2501 AVDictionary
*dict
= NULL
, *tmp
= NULL
;
2502 char *mapped_string
= NULL
;
2503 const AVDictionaryEntry
*e
;
2504 const AVOption opts
[] = {
2505 { "type", "Set group type", offsetof(AVStreamGroup
, type
), AV_OPT_TYPE_INT
,
2506 { .i64
= 0 }, 0, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, .unit
= "type" },
2507 { "iamf_audio_element", NULL
, 0, AV_OPT_TYPE_CONST
,
2508 { .i64
= AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT
}, .unit
= "type" },
2509 { "iamf_mix_presentation", NULL
, 0, AV_OPT_TYPE_CONST
,
2510 { .i64
= AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION
}, .unit
= "type" },
2513 const AVClass
class = {
2514 .class_name
= "StreamGroupType",
2515 .item_name
= av_default_item_name
,
2517 .version
= LIBAVUTIL_VERSION_INT
,
2519 const AVClass
*pclass
= &class;
2522 ret
= av_dict_parse_string(&dict
, token
, "=", ":", AV_DICT_MULTIKEY
);
2524 av_log(mux
, AV_LOG_ERROR
, "Error parsing group specification %s\n", token
);
2528 av_dict_copy(&tmp
, dict
, 0);
2529 e
= av_dict_get(dict
, "map", NULL
, 0);
2534 av_log(mux
, AV_LOG_ERROR
, "Unexpected extra parameters when mapping a"
2536 ret
= AVERROR(EINVAL
);
2540 av_bprint_init(&bp
, 0, AV_BPRINT_SIZE_AUTOMATIC
);
2541 ret
= of_map_group(mux
, &tmp
, &bp
, e
->value
);
2543 av_bprint_finalize(&bp
, NULL
);
2547 av_bprint_finalize(&bp
, &mapped_string
);
2548 ptr
= mapped_string
;
2551 // "type" is not a user settable AVOption in AVStreamGroup, so handle it here
2552 e
= av_dict_get(tmp
, "type", NULL
, 0);
2554 av_log(mux
, AV_LOG_ERROR
, "No type specified for Stream Group in \"%s\"\n", token
);
2555 ret
= AVERROR(EINVAL
);
2559 ret
= av_opt_eval_int(&pclass
, opts
, e
->value
, &type
);
2560 if (!ret
&& type
== AV_STREAM_GROUP_PARAMS_NONE
)
2561 ret
= AVERROR(EINVAL
);
2563 av_log(mux
, AV_LOG_ERROR
, "Invalid group type \"%s\"\n", e
->value
);
2567 stg
= avformat_stream_group_create(oc
, type
, &tmp
);
2569 ret
= AVERROR(ENOMEM
);
2574 while (e
= av_dict_get(dict
, "st", e
, 0)) {
2576 int64_t idx
= strtoll(e
->value
, &endptr
, 0);
2577 if (*endptr
|| idx
< 0 || idx
>= oc
->nb_streams
) {
2578 av_log(mux
, AV_LOG_ERROR
, "Invalid stream index %"PRId64
"\n", idx
);
2579 ret
= AVERROR(EINVAL
);
2582 ret
= avformat_stream_group_add_stream(stg
, oc
->streams
[idx
]);
2586 while (e
= av_dict_get(dict
, "stg", e
, 0)) {
2588 int64_t idx
= strtoll(e
->value
, &endptr
, 0);
2589 if (*endptr
|| idx
< 0 || idx
>= oc
->nb_stream_groups
- 1) {
2590 av_log(mux
, AV_LOG_ERROR
, "Invalid stream group index %"PRId64
"\n", idx
);
2591 ret
= AVERROR(EINVAL
);
2594 for (unsigned i
= 0; i
< oc
->stream_groups
[idx
]->nb_streams
; i
++) {
2595 ret
= avformat_stream_group_add_stream(stg
, oc
->stream_groups
[idx
]->streams
[i
]);
2602 case AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT
:
2603 ret
= of_parse_iamf_audio_element_layers(mux
, stg
, ptr
);
2605 case AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION
:
2606 ret
= of_parse_iamf_submixes(mux
, stg
, ptr
);
2609 av_log(mux
, AV_LOG_FATAL
, "Unknown group type %d.\n", type
);
2610 ret
= AVERROR(EINVAL
);
2617 // make sure that nothing but "st" and "stg" entries are left in the dict
2619 av_dict_set(&tmp
, "map", NULL
, 0);
2620 av_dict_set(&tmp
, "type", NULL
, 0);
2621 while (e
= av_dict_iterate(tmp
, e
)) {
2622 if (!strcmp(e
->key
, "st") || !strcmp(e
->key
, "stg"))
2625 av_log(mux
, AV_LOG_FATAL
, "Unknown group key %s.\n", e
->key
);
2626 ret
= AVERROR(EINVAL
);
2632 av_free(mapped_string
);
2633 av_dict_free(&dict
);
2639 static int of_add_groups(Muxer
*mux
, const OptionsContext
*o
)
2641 /* process manually set groups */
2642 for (int i
= 0; i
< o
->stream_groups
.nb_opt
; i
++) {
2644 char *str
, *ptr
= NULL
;
2647 str
= av_strdup(o
->stream_groups
.opt
[i
].u
.str
);
2651 token
= av_strtok(str
, ",", &ptr
);
2654 ptr
+= strspn(ptr
, " \n\t\r");
2655 ret
= of_parse_group_token(mux
, token
, ptr
);
2666 static int of_add_programs(Muxer
*mux
, const OptionsContext
*o
)
2668 AVFormatContext
*oc
= mux
->fc
;
2669 /* process manually set programs */
2670 for (int i
= 0; i
< o
->program
.nb_opt
; i
++) {
2671 AVDictionary
*dict
= NULL
;
2672 const AVDictionaryEntry
*e
;
2674 int ret
, progid
= i
+ 1;
2676 ret
= av_dict_parse_string(&dict
, o
->program
.opt
[i
].u
.str
, "=", ":",
2679 av_log(mux
, AV_LOG_ERROR
, "Error parsing program specification %s\n",
2680 o
->program
.opt
[i
].u
.str
);
2684 e
= av_dict_get(dict
, "program_num", NULL
, 0);
2686 progid
= strtol(e
->value
, NULL
, 0);
2687 av_dict_set(&dict
, e
->key
, NULL
, 0);
2690 program
= av_new_program(oc
, progid
);
2692 ret
= AVERROR(ENOMEM
);
2696 e
= av_dict_get(dict
, "title", NULL
, 0);
2698 av_dict_set(&program
->metadata
, e
->key
, e
->value
, 0);
2699 av_dict_set(&dict
, e
->key
, NULL
, 0);
2703 while (e
= av_dict_get(dict
, "st", e
, 0)) {
2704 int st_num
= strtol(e
->value
, NULL
, 0);
2705 av_program_add_stream_index(oc
, progid
, st_num
);
2708 // make sure that nothing but "st" entries are left in the dict
2710 while (e
= av_dict_iterate(dict
, e
)) {
2711 if (!strcmp(e
->key
, "st"))
2714 av_log(mux
, AV_LOG_FATAL
, "Unknown program key %s.\n", e
->key
);
2715 ret
= AVERROR(EINVAL
);
2720 av_dict_free(&dict
);
2729 * Parse a metadata specifier passed as 'arg' parameter.
2730 * @param arg metadata string to parse
2731 * @param type metadata type is written here -- g(lobal)/s(tream)/c(hapter)/p(rogram)
2732 * @param index for type c/p, chapter/program index is written here
2733 * @param stream_spec for type s, the stream specifier is written here
2735 static int parse_meta_type(void *logctx
, const char *arg
,
2736 char *type
, int *index
, const char **stream_spec
)
2744 if (*(++arg
) && *arg
!= ':') {
2745 av_log(logctx
, AV_LOG_FATAL
, "Invalid metadata specifier %s.\n", arg
);
2746 return AVERROR(EINVAL
);
2748 *stream_spec
= *arg
== ':' ? arg
+ 1 : "";
2752 if (*(++arg
) == ':')
2753 *index
= strtol(++arg
, NULL
, 0);
2756 av_log(logctx
, AV_LOG_FATAL
, "Invalid metadata type %c.\n", *arg
);
2757 return AVERROR(EINVAL
);
2765 static int of_add_metadata(OutputFile
*of
, AVFormatContext
*oc
,
2766 const OptionsContext
*o
)
2768 for (int i
= 0; i
< o
->metadata
.nb_opt
; i
++) {
2771 const char *stream_spec
;
2772 int index
= 0, ret
= 0;
2774 val
= strchr(o
->metadata
.opt
[i
].u
.str
, '=');
2776 av_log(of
, AV_LOG_FATAL
, "No '=' character in metadata string %s.\n",
2777 o
->metadata
.opt
[i
].u
.str
);
2778 return AVERROR(EINVAL
);
2782 ret
= parse_meta_type(of
, o
->metadata
.opt
[i
].specifier
, &type
, &index
, &stream_spec
);
2787 for (int j
= 0; j
< oc
->nb_streams
; j
++) {
2788 if ((ret
= check_stream_specifier(oc
, oc
->streams
[j
], stream_spec
)) > 0) {
2789 av_dict_set(&oc
->streams
[j
]->metadata
, o
->metadata
.opt
[i
].u
.str
, *val
? val
: NULL
, 0);
2799 if (index
< 0 || index
>= oc
->nb_chapters
) {
2800 av_log(of
, AV_LOG_FATAL
, "Invalid chapter index %d in metadata specifier.\n", index
);
2801 return AVERROR(EINVAL
);
2803 m
= &oc
->chapters
[index
]->metadata
;
2806 if (index
< 0 || index
>= oc
->nb_programs
) {
2807 av_log(of
, AV_LOG_FATAL
, "Invalid program index %d in metadata specifier.\n", index
);
2808 return AVERROR(EINVAL
);
2810 m
= &oc
->programs
[index
]->metadata
;
2813 av_log(of
, AV_LOG_FATAL
, "Invalid metadata specifier %s.\n", o
->metadata
.opt
[i
].specifier
);
2814 return AVERROR(EINVAL
);
2816 av_dict_set(m
, o
->metadata
.opt
[i
].u
.str
, *val
? val
: NULL
, 0);
2823 static int copy_chapters(InputFile
*ifile
, OutputFile
*ofile
, AVFormatContext
*os
,
2826 AVFormatContext
*is
= ifile
->ctx
;
2829 tmp
= av_realloc_f(os
->chapters
, is
->nb_chapters
+ os
->nb_chapters
, sizeof(*os
->chapters
));
2831 return AVERROR(ENOMEM
);
2834 for (int i
= 0; i
< is
->nb_chapters
; i
++) {
2835 AVChapter
*in_ch
= is
->chapters
[i
], *out_ch
;
2836 int64_t start_time
= (ofile
->start_time
== AV_NOPTS_VALUE
) ? 0 : ofile
->start_time
;
2837 int64_t ts_off
= av_rescale_q(start_time
- ifile
->ts_offset
,
2838 AV_TIME_BASE_Q
, in_ch
->time_base
);
2839 int64_t rt
= (ofile
->recording_time
== INT64_MAX
) ? INT64_MAX
:
2840 av_rescale_q(ofile
->recording_time
, AV_TIME_BASE_Q
, in_ch
->time_base
);
2843 if (in_ch
->end
< ts_off
)
2845 if (rt
!= INT64_MAX
&& in_ch
->start
> rt
+ ts_off
)
2848 out_ch
= av_mallocz(sizeof(AVChapter
));
2850 return AVERROR(ENOMEM
);
2852 out_ch
->id
= in_ch
->id
;
2853 out_ch
->time_base
= in_ch
->time_base
;
2854 out_ch
->start
= FFMAX(0, in_ch
->start
- ts_off
);
2855 out_ch
->end
= FFMIN(rt
, in_ch
->end
- ts_off
);
2858 av_dict_copy(&out_ch
->metadata
, in_ch
->metadata
, 0);
2860 os
->chapters
[os
->nb_chapters
++] = out_ch
;
2865 static int copy_metadata(Muxer
*mux
, AVFormatContext
*ic
,
2866 const char *outspec
, const char *inspec
,
2867 int *metadata_global_manual
, int *metadata_streams_manual
,
2868 int *metadata_chapters_manual
)
2870 AVFormatContext
*oc
= mux
->fc
;
2871 AVDictionary
**meta_in
= NULL
;
2872 AVDictionary
**meta_out
= NULL
;
2874 char type_in
, type_out
;
2875 const char *istream_spec
= NULL
, *ostream_spec
= NULL
;
2876 int idx_in
= 0, idx_out
= 0;
2878 ret
= parse_meta_type(mux
, inspec
, &type_in
, &idx_in
, &istream_spec
);
2880 ret
= parse_meta_type(mux
, outspec
, &type_out
, &idx_out
, &ostream_spec
);
2884 if (type_in
== 'g' || type_out
== 'g' || (!*outspec
&& !ic
))
2885 *metadata_global_manual
= 1;
2886 if (type_in
== 's' || type_out
== 's' || (!*outspec
&& !ic
))
2887 *metadata_streams_manual
= 1;
2888 if (type_in
== 'c' || type_out
== 'c' || (!*outspec
&& !ic
))
2889 *metadata_chapters_manual
= 1;
2891 /* ic is NULL when just disabling automatic mappings */
2895 #define METADATA_CHECK_INDEX(index, nb_elems, desc)\
2896 if ((index) < 0 || (index) >= (nb_elems)) {\
2897 av_log(mux, AV_LOG_FATAL, "Invalid %s index %d while processing metadata maps.\n",\
2899 return AVERROR(EINVAL);\
2902 #define SET_DICT(type, meta, context, index)\
2905 meta = &context->metadata;\
2908 METADATA_CHECK_INDEX(index, context->nb_chapters, "chapter")\
2909 meta = &context->chapters[index]->metadata;\
2912 METADATA_CHECK_INDEX(index, context->nb_programs, "program")\
2913 meta = &context->programs[index]->metadata;\
2916 break; /* handled separately below */ \
2917 default: av_assert0(0);\
2920 SET_DICT(type_in, meta_in, ic, idx_in);
2921 SET_DICT(type_out
, meta_out
, oc
, idx_out
);
2923 /* for input streams choose first matching stream */
2924 if (type_in
== 's') {
2925 for (i
= 0; i
< ic
->nb_streams
; i
++) {
2926 if ((ret
= check_stream_specifier(ic
, ic
->streams
[i
], istream_spec
)) > 0) {
2927 meta_in
= &ic
->streams
[i
]->metadata
;
2933 av_log(mux
, AV_LOG_FATAL
, "Stream specifier %s does not match any streams.\n", istream_spec
);
2934 return AVERROR(EINVAL
);
2938 if (type_out
== 's') {
2939 for (i
= 0; i
< oc
->nb_streams
; i
++) {
2940 if ((ret
= check_stream_specifier(oc
, oc
->streams
[i
], ostream_spec
)) > 0) {
2941 meta_out
= &oc
->streams
[i
]->metadata
;
2942 av_dict_copy(meta_out
, *meta_in
, AV_DICT_DONT_OVERWRITE
);
2947 av_dict_copy(meta_out
, *meta_in
, AV_DICT_DONT_OVERWRITE
);
2952 static int copy_meta(Muxer
*mux
, const OptionsContext
*o
)
2954 OutputFile
*of
= &mux
->of
;
2955 AVFormatContext
*oc
= mux
->fc
;
2956 int chapters_input_file
= o
->chapters_input_file
;
2957 int metadata_global_manual
= 0;
2958 int metadata_streams_manual
= 0;
2959 int metadata_chapters_manual
= 0;
2963 for (int i
= 0; i
< o
->metadata_map
.nb_opt
; i
++) {
2965 int in_file_index
= strtol(o
->metadata_map
.opt
[i
].u
.str
, &p
, 0);
2967 if (in_file_index
>= nb_input_files
) {
2968 av_log(mux
, AV_LOG_FATAL
, "Invalid input file index %d while "
2969 "processing metadata maps\n", in_file_index
);
2970 return AVERROR(EINVAL
);
2972 ret
= copy_metadata(mux
,
2973 in_file_index
>= 0 ? input_files
[in_file_index
]->ctx
: NULL
,
2974 o
->metadata_map
.opt
[i
].specifier
, *p
? p
+ 1 : p
,
2975 &metadata_global_manual
, &metadata_streams_manual
,
2976 &metadata_chapters_manual
);
2982 if (chapters_input_file
>= nb_input_files
) {
2983 if (chapters_input_file
== INT_MAX
) {
2984 /* copy chapters from the first input file that has them*/
2985 chapters_input_file
= -1;
2986 for (int i
= 0; i
< nb_input_files
; i
++)
2987 if (input_files
[i
]->ctx
->nb_chapters
) {
2988 chapters_input_file
= i
;
2992 av_log(mux
, AV_LOG_FATAL
, "Invalid input file index %d in chapter mapping.\n",
2993 chapters_input_file
);
2994 return AVERROR(EINVAL
);
2997 if (chapters_input_file
>= 0)
2998 copy_chapters(input_files
[chapters_input_file
], of
, oc
,
2999 !metadata_chapters_manual
);
3001 /* copy global metadata by default */
3002 if (!metadata_global_manual
&& nb_input_files
){
3003 av_dict_copy(&oc
->metadata
, input_files
[0]->ctx
->metadata
,
3004 AV_DICT_DONT_OVERWRITE
);
3005 if (of
->recording_time
!= INT64_MAX
)
3006 av_dict_set(&oc
->metadata
, "duration", NULL
, 0);
3007 av_dict_set(&oc
->metadata
, "creation_time", NULL
, 0);
3008 av_dict_set(&oc
->metadata
, "company_name", NULL
, 0);
3009 av_dict_set(&oc
->metadata
, "product_name", NULL
, 0);
3010 av_dict_set(&oc
->metadata
, "product_version", NULL
, 0);
3012 if (!metadata_streams_manual
)
3013 for (int i
= 0; i
< of
->nb_streams
; i
++) {
3014 OutputStream
*ost
= of
->streams
[i
];
3016 if (!ost
->ist
) /* this is true e.g. for attached files */
3018 av_dict_copy(&ost
->st
->metadata
, ost
->ist
->st
->metadata
, AV_DICT_DONT_OVERWRITE
);
3024 static int set_dispositions(Muxer
*mux
, const OptionsContext
*o
)
3026 OutputFile
*of
= &mux
->of
;
3027 AVFormatContext
*ctx
= mux
->fc
;
3029 // indexed by type+1, because AVMEDIA_TYPE_UNKNOWN=-1
3030 int nb_streams
[AVMEDIA_TYPE_NB
+ 1] = { 0 };
3031 int have_default
[AVMEDIA_TYPE_NB
+ 1] = { 0 };
3032 int have_manual
= 0;
3035 const char **dispositions
;
3037 dispositions
= av_calloc(ctx
->nb_streams
, sizeof(*dispositions
));
3039 return AVERROR(ENOMEM
);
3041 // first, copy the input dispositions
3042 for (int i
= 0; i
< ctx
->nb_streams
; i
++) {
3043 OutputStream
*ost
= of
->streams
[i
];
3045 nb_streams
[ost
->type
+ 1]++;
3047 opt_match_per_stream_str(ost
, &o
->disposition
, ctx
, ost
->st
, &dispositions
[i
]);
3049 have_manual
|= !!dispositions
[i
];
3052 ost
->st
->disposition
= ost
->ist
->st
->disposition
;
3054 if (ost
->st
->disposition
& AV_DISPOSITION_DEFAULT
)
3055 have_default
[ost
->type
+ 1] = 1;
3060 // process manually set dispositions - they override the above copy
3061 for (int i
= 0; i
< ctx
->nb_streams
; i
++) {
3062 OutputStream
*ost
= of
->streams
[i
];
3063 const char *disp
= dispositions
[i
];
3068 ret
= av_opt_set(ost
->st
, "disposition", disp
, 0);
3073 // For each media type with more than one stream, find a suitable stream to
3074 // mark as default, unless one is already marked default.
3075 // "Suitable" means the first of that type, skipping attached pictures.
3076 for (int i
= 0; i
< ctx
->nb_streams
; i
++) {
3077 OutputStream
*ost
= of
->streams
[i
];
3078 enum AVMediaType type
= ost
->type
;
3080 if (nb_streams
[type
+ 1] < 2 || have_default
[type
+ 1] ||
3081 ost
->st
->disposition
& AV_DISPOSITION_ATTACHED_PIC
)
3084 ost
->st
->disposition
|= AV_DISPOSITION_DEFAULT
;
3085 have_default
[type
+ 1] = 1;
3090 av_freep(&dispositions
);
3095 static const char *const forced_keyframes_const_names
[] = {
3104 static int compare_int64(const void *a
, const void *b
)
3106 return FFDIFFSIGN(*(const int64_t *)a
, *(const int64_t *)b
);
3109 static int parse_forced_key_frames(void *log
, KeyframeForceCtx
*kf
,
3110 const Muxer
*mux
, const char *spec
)
3113 int n
= 1, i
, ret
, size
, index
= 0;
3116 for (p
= spec
; *p
; p
++)
3120 pts
= av_malloc_array(size
, sizeof(*pts
));
3122 return AVERROR(ENOMEM
);
3125 for (i
= 0; i
< n
; i
++) {
3126 char *next
= strchr(p
, ',');
3131 if (strstr(p
, "chapters") == p
) {
3132 AVChapter
* const *ch
= mux
->fc
->chapters
;
3133 unsigned int nb_ch
= mux
->fc
->nb_chapters
;
3136 if (nb_ch
> INT_MAX
- size
) {
3137 ret
= AVERROR(ERANGE
);
3141 pts
= av_realloc_f(pts
, size
, sizeof(*pts
));
3143 return AVERROR(ENOMEM
);
3146 ret
= av_parse_time(&t
, p
+ 8, 1);
3148 av_log(log
, AV_LOG_ERROR
,
3149 "Invalid chapter time offset: %s\n", p
+ 8);
3155 for (j
= 0; j
< nb_ch
; j
++) {
3156 const AVChapter
*c
= ch
[j
];
3157 av_assert1(index
< size
);
3158 pts
[index
++] = av_rescale_q(c
->start
, c
->time_base
,
3159 AV_TIME_BASE_Q
) + t
;
3163 av_assert1(index
< size
);
3164 ret
= av_parse_time(&t
, p
, 1);
3166 av_log(log
, AV_LOG_ERROR
, "Invalid keyframe time: %s\n", p
);
3176 av_assert0(index
== size
);
3177 qsort(pts
, size
, sizeof(*pts
), compare_int64
);
3187 static int process_forced_keyframes(Muxer
*mux
, const OptionsContext
*o
)
3189 for (int i
= 0; i
< mux
->of
.nb_streams
; i
++) {
3190 OutputStream
*ost
= mux
->of
.streams
[i
];
3191 const char *forced_keyframes
= NULL
;
3193 opt_match_per_stream_str(ost
, &o
->forced_key_frames
,
3194 mux
->fc
, ost
->st
, &forced_keyframes
);
3196 if (!(ost
->type
== AVMEDIA_TYPE_VIDEO
&&
3197 ost
->enc
&& forced_keyframes
))
3200 if (!strncmp(forced_keyframes
, "expr:", 5)) {
3201 int ret
= av_expr_parse(&ost
->kf
.pexpr
, forced_keyframes
+ 5,
3202 forced_keyframes_const_names
, NULL
, NULL
, NULL
, NULL
, 0, NULL
);
3204 av_log(ost
, AV_LOG_ERROR
,
3205 "Invalid force_key_frames expression '%s'\n", forced_keyframes
+ 5);
3208 ost
->kf
.expr_const_values
[FKF_N
] = 0;
3209 ost
->kf
.expr_const_values
[FKF_N_FORCED
] = 0;
3210 ost
->kf
.expr_const_values
[FKF_PREV_FORCED_N
] = NAN
;
3211 ost
->kf
.expr_const_values
[FKF_PREV_FORCED_T
] = NAN
;
3213 // Don't parse the 'forced_keyframes' in case of 'keep-source-keyframes',
3214 // parse it only for static kf timings
3215 } else if (!strcmp(forced_keyframes
, "source")) {
3216 ost
->kf
.type
= KF_FORCE_SOURCE
;
3217 #if FFMPEG_OPT_FORCE_KF_SOURCE_NO_DROP
3218 } else if (!strcmp(forced_keyframes
, "source_no_drop")) {
3219 av_log(ost
, AV_LOG_WARNING
, "The 'source_no_drop' value for "
3220 "-force_key_frames is deprecated, use just 'source'\n");
3221 ost
->kf
.type
= KF_FORCE_SOURCE
;
3224 int ret
= parse_forced_key_frames(ost
, &ost
->kf
, mux
, forced_keyframes
);
3233 static const char *output_file_item_name(void *obj
)
3235 const Muxer
*mux
= obj
;
3237 return mux
->log_name
;
3240 static const AVClass output_file_class
= {
3241 .class_name
= "OutputFile",
3242 .version
= LIBAVUTIL_VERSION_INT
,
3243 .item_name
= output_file_item_name
,
3244 .category
= AV_CLASS_CATEGORY_MUXER
,
3247 static Muxer
*mux_alloc(void)
3249 Muxer
*mux
= allocate_array_elem(&output_files
, sizeof(*mux
), &nb_output_files
);
3254 mux
->of
.class = &output_file_class
;
3255 mux
->of
.index
= nb_output_files
- 1;
3257 snprintf(mux
->log_name
, sizeof(mux
->log_name
), "out#%d", mux
->of
.index
);
3262 int of_open(const OptionsContext
*o
, const char *filename
, Scheduler
*sch
)
3265 AVFormatContext
*oc
;
3269 int64_t recording_time
= o
->recording_time
;
3270 int64_t stop_time
= o
->stop_time
;
3274 return AVERROR(ENOMEM
);
3278 if (stop_time
!= INT64_MAX
&& recording_time
!= INT64_MAX
) {
3279 stop_time
= INT64_MAX
;
3280 av_log(mux
, AV_LOG_WARNING
, "-t and -to cannot be used together; using -t.\n");
3283 if (stop_time
!= INT64_MAX
&& recording_time
== INT64_MAX
) {
3284 int64_t start_time
= o
->start_time
== AV_NOPTS_VALUE
? 0 : o
->start_time
;
3285 if (stop_time
<= start_time
) {
3286 av_log(mux
, AV_LOG_ERROR
, "-to value smaller than -ss; aborting.\n");
3287 return AVERROR(EINVAL
);
3289 recording_time
= stop_time
- start_time
;
3293 of
->recording_time
= recording_time
;
3294 of
->start_time
= o
->start_time
;
3296 mux
->limit_filesize
= o
->limit_filesize
;
3297 av_dict_copy(&mux
->opts
, o
->g
->format_opts
, 0);
3299 if (!strcmp(filename
, "-"))
3302 err
= avformat_alloc_output_context2(&oc
, NULL
, o
->format
, filename
);
3304 av_log(mux
, AV_LOG_FATAL
, "Error initializing the muxer for %s: %s\n",
3305 filename
, av_err2str(err
));
3310 av_strlcat(mux
->log_name
, "/", sizeof(mux
->log_name
));
3311 av_strlcat(mux
->log_name
, oc
->oformat
->name
, sizeof(mux
->log_name
));
3314 if (recording_time
!= INT64_MAX
)
3315 oc
->duration
= recording_time
;
3317 oc
->interrupt_callback
= int_cb
;
3320 oc
->flags
|= AVFMT_FLAG_BITEXACT
;
3323 of
->bitexact
= check_opt_bitexact(oc
, mux
->opts
, "fflags",
3324 AVFMT_FLAG_BITEXACT
);
3327 err
= sch_add_mux(sch
, muxer_thread
, mux_check_init
, mux
,
3328 !strcmp(oc
->oformat
->name
, "rtp"), o
->thread_queue_size
);
3334 /* create all output streams for this file */
3335 err
= create_streams(mux
, o
);
3339 /* check if all codec options have been used */
3340 err
= check_avoptions_used(o
->g
->codec_opts
, mux
->enc_opts_used
, mux
, 0);
3341 av_dict_free(&mux
->enc_opts_used
);
3345 /* check filename in case of an image number is expected */
3346 if (oc
->oformat
->flags
& AVFMT_NEEDNUMBER
&& !av_filename_number_test(oc
->url
)) {
3347 av_log(mux
, AV_LOG_FATAL
,
3348 "Output filename '%s' does not contain a numeric pattern like "
3349 "'%%d', which is required by output format '%s'.\n",
3350 oc
->url
, oc
->oformat
->name
);
3351 return AVERROR(EINVAL
);
3354 if (!(oc
->oformat
->flags
& AVFMT_NOFILE
)) {
3355 /* test if it already exists to avoid losing precious files */
3356 err
= assert_file_overwrite(filename
);
3361 if ((err
= avio_open2(&oc
->pb
, filename
, AVIO_FLAG_WRITE
,
3362 &oc
->interrupt_callback
,
3364 av_log(mux
, AV_LOG_FATAL
, "Error opening output %s: %s\n",
3365 filename
, av_err2str(err
));
3368 } else if (strcmp(oc
->oformat
->name
, "image2")==0 && !av_filename_number_test(filename
)) {
3369 err
= assert_file_overwrite(filename
);
3374 if (o
->mux_preload
) {
3375 av_dict_set_int(&mux
->opts
, "preload", o
->mux_preload
*AV_TIME_BASE
, 0);
3377 oc
->max_delay
= (int)(o
->mux_max_delay
* AV_TIME_BASE
);
3379 /* copy metadata and chapters from input files */
3380 err
= copy_meta(mux
, o
);
3384 err
= of_add_groups(mux
, o
);
3388 err
= of_add_programs(mux
, o
);
3392 err
= of_add_metadata(of
, oc
, o
);
3396 err
= set_dispositions(mux
, o
);
3398 av_log(mux
, AV_LOG_FATAL
, "Error setting output stream dispositions\n");
3402 // parse forced keyframe specifications;
3403 // must be done after chapters are created
3404 err
= process_forced_keyframes(mux
, o
);
3406 av_log(mux
, AV_LOG_FATAL
, "Error processing forced keyframes\n");
3410 err
= setup_sync_queues(mux
, oc
, o
->shortest_buf_duration
* AV_TIME_BASE
,
3413 av_log(mux
, AV_LOG_FATAL
, "Error setting up output sync queues\n");
3419 /* initialize streamcopy streams. */
3420 for (int i
= 0; i
< of
->nb_streams
; i
++) {
3421 OutputStream
*ost
= of
->streams
[i
];
3424 err
= of_stream_init(of
, ost
, NULL
);