From patchwork Thu Apr 13 14:11:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 41147 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4645:b0:e3:3194:9d20 with SMTP id eb5csp1286742pzb; Thu, 13 Apr 2023 07:16:18 -0700 (PDT) X-Google-Smtp-Source: AKy350YgbftyyeRHVRaVvrMJ+nHcsh1zg5jIgoY5zHWby0aT7OMzQTt9bL0fRbS43qvLYa6oIYsV X-Received: by 2002:a17:907:7892:b0:933:4c24:101b with SMTP id ku18-20020a170907789200b009334c24101bmr6280105ejc.7.1681395377932; Thu, 13 Apr 2023 07:16:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1681395377; cv=none; d=google.com; s=arc-20160816; b=oMWy/FWYbFb98ZLoFHxTvM1G5FTZIBm+m1cc5OHkvkHUnuaBDjGCbvH+iNBK3zuZdF jTEReH6upCkM4bySU+aUGHK+vvk1MW4Es9dKFndeR4lXzjlP/i1UkDzYHWT5EdmWjEgK p/872NgMNc/OLDZjApUN4PFdU1fKP88TR4BSAuZO/OVT3lDj4ZVOQgxTN/3G7bj9CO5Z fRSB1KzXqx3fySEA6dqzWTbggCfTrGNv9mxwQIB6XnfHJ/ctCr0yM+iMSWGoKLWmZz4P Exq6p84wzLP8I/UnaTbUBuimpGqsOd2Nr8qUQxDLHe504JDt6xyJjVYabGlELCHSrxK0 AMLQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:message-id:date:to:from :delivered-to; bh=grwWd6N7Oc3CdKjPbfqNSx8KesSGf7MZhlPGmeRzziI=; b=iHI+zbIBvolOLwRrskO1vhoO/qf0Moipi2Cb/qiBeaFaAuvM6kbqpSQVRtMpMA1Hi6 H4P9OT9sI7E34eVu+0OYDR648gVUopWnfNqaDK8SUUWq5LrcZzTpvsoQn2H/RAwFOm1y 6rfssYnmAjoZNwCEjt7PfU7hytUJTobxFP+hsaa3XP7kuu4tgaxRHimcbHFQLGI+C9Nt OqUxLfQ07kMg/aRbItXKlhV5Q/e+RoeccGfQZcjSmtB940WhgBG0nM79WTi5bll8xP6I qSHSDxZgaPzbIhZECOPy62JbiUhh6atTeWeVBfJwN6edZl1hXR0sEDUQVyxxIFL7gzWZ UNAg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id kb17-20020a170907925100b0094a671c2297si1899688ejb.296.2023.04.13.07.16.17; Thu, 13 Apr 2023 07:16:17 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 86DD468BE03; Thu, 13 Apr 2023 17:16:02 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail0.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 73F6C680A2D for ; Thu, 13 Apr 2023 17:15:54 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id 3F6C2240D20 for ; Thu, 13 Apr 2023 16:15:54 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id aOML-fuiGW5C for ; Thu, 13 Apr 2023 16:15:53 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail0.khirnov.net (Postfix) with ESMTPS id 117272404EC for ; Thu, 13 Apr 2023 16:15:53 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id C5D263A038E for ; Thu, 13 Apr 2023 16:15:52 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Thu, 13 Apr 2023 16:11:59 +0200 Message-Id: <20230413141223.17245-1-anton@khirnov.net> X-Mailer: git-send-email 2.39.1 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 01/25] fftools/ffmpeg_mux_init: move new_output_stream() lower in the file X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: BgyAII3DqBzq Reduces the diff in the following commit. Temporarily add a forward declaration for new_output_stream(), it will be removed in the next commit. --- fftools/ffmpeg_mux_init.c | 481 +++++++++++++++++++------------------- 1 file changed, 242 insertions(+), 239 deletions(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 62e5643a04..69c1532b9e 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -419,245 +419,7 @@ static MuxStream *mux_stream_alloc(Muxer *mux, enum AVMediaType type) } static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, - enum AVMediaType type, InputStream *ist) -{ - AVFormatContext *oc = mux->fc; - MuxStream *ms; - OutputStream *ost; - const AVCodec *enc; - AVStream *st = avformat_new_stream(oc, NULL); - int ret = 0; - const char *bsfs = NULL, *time_base = NULL; - char *next, *codec_tag = NULL; - double qscale = -1; - int i; - - if (!st) - report_and_exit(AVERROR(ENOMEM)); - - if (oc->nb_streams - 1 < o->nb_streamid_map) - st->id = o->streamid_map[oc->nb_streams - 1]; - - ms = mux_stream_alloc(mux, type); - ost = &ms->ost; - - ms->muxing_queue = av_fifo_alloc2(8, sizeof(AVPacket*), 0); - if (!ms->muxing_queue) - report_and_exit(AVERROR(ENOMEM)); - ms->last_mux_dts = AV_NOPTS_VALUE; - - ost->st = st; - ost->ist = ist; - ost->kf.ref_pts = AV_NOPTS_VALUE; - st->codecpar->codec_type = type; - - ret = choose_encoder(o, oc, ost, &enc); - if (ret < 0) { - av_log(ost, AV_LOG_FATAL, "Error selecting an encoder\n"); - exit_program(1); - } - - if (enc) { - ost->enc_ctx = avcodec_alloc_context3(enc); - if (!ost->enc_ctx) - report_and_exit(AVERROR(ENOMEM)); - - ret = enc_alloc(&ost->enc, enc); - if (ret < 0) - report_and_exit(ret); - - av_strlcat(ms->log_name, "/", sizeof(ms->log_name)); - av_strlcat(ms->log_name, enc->name, sizeof(ms->log_name)); - } else { - av_strlcat(ms->log_name, "/copy", sizeof(ms->log_name)); - } - - ost->filtered_frame = av_frame_alloc(); - if (!ost->filtered_frame) - report_and_exit(AVERROR(ENOMEM)); - - ost->pkt = av_packet_alloc(); - if (!ost->pkt) - report_and_exit(AVERROR(ENOMEM)); - - if (ost->enc_ctx) { - AVCodecContext *enc = ost->enc_ctx; - AVIOContext *s = NULL; - char *buf = NULL, *arg = NULL, *preset = NULL; - const char *enc_stats_pre = NULL, *enc_stats_post = NULL, *mux_stats = NULL; - - ost->encoder_opts = filter_codec_opts(o->g->codec_opts, enc->codec_id, - oc, st, enc->codec); - - MATCH_PER_STREAM_OPT(presets, str, preset, oc, st); - ost->autoscale = 1; - MATCH_PER_STREAM_OPT(autoscale, i, ost->autoscale, oc, st); - if (preset && (!(ret = get_preset_file_2(preset, enc->codec->name, &s)))) { - AVBPrint bprint; - av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED); - do { - av_bprint_clear(&bprint); - buf = get_line(s, &bprint); - if (!buf[0] || buf[0] == '#') - continue; - if (!(arg = strchr(buf, '='))) { - av_log(ost, AV_LOG_FATAL, "Invalid line found in the preset file.\n"); - exit_program(1); - } - *arg++ = 0; - av_dict_set(&ost->encoder_opts, buf, arg, AV_DICT_DONT_OVERWRITE); - } while (!s->eof_reached); - av_bprint_finalize(&bprint, NULL); - avio_closep(&s); - } - if (ret) { - av_log(ost, AV_LOG_FATAL, - "Preset %s specified, but could not be opened.\n", preset); - exit_program(1); - } - - MATCH_PER_STREAM_OPT(enc_stats_pre, str, enc_stats_pre, oc, st); - if (enc_stats_pre && - (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) { - const char *format = "{fidx} {sidx} {n} {t}"; - - MATCH_PER_STREAM_OPT(enc_stats_pre_fmt, str, format, oc, st); - - ret = enc_stats_init(ost, &ost->enc_stats_pre, 1, enc_stats_pre, format); - if (ret < 0) - exit_program(1); - } - - MATCH_PER_STREAM_OPT(enc_stats_post, str, enc_stats_post, oc, st); - if (enc_stats_post && - (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) { - const char *format = "{fidx} {sidx} {n} {t}"; - - MATCH_PER_STREAM_OPT(enc_stats_post_fmt, str, format, oc, st); - - ret = enc_stats_init(ost, &ost->enc_stats_post, 0, enc_stats_post, format); - if (ret < 0) - exit_program(1); - } - - MATCH_PER_STREAM_OPT(mux_stats, str, mux_stats, oc, st); - if (mux_stats && - (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) { - const char *format = "{fidx} {sidx} {n} {t}"; - - MATCH_PER_STREAM_OPT(mux_stats_fmt, str, format, oc, st); - - ret = enc_stats_init(ost, &ms->stats, 0, mux_stats, format); - if (ret < 0) - exit_program(1); - } - } else { - ost->encoder_opts = filter_codec_opts(o->g->codec_opts, AV_CODEC_ID_NONE, oc, st, NULL); - } - - - if (o->bitexact) { - ost->bitexact = 1; - } else if (ost->enc_ctx) { - ost->bitexact = check_opt_bitexact(ost->enc_ctx, ost->encoder_opts, "flags", - AV_CODEC_FLAG_BITEXACT); - } - - MATCH_PER_STREAM_OPT(time_bases, str, time_base, oc, st); - if (time_base) { - AVRational q; - if (av_parse_ratio(&q, time_base, INT_MAX, 0, NULL) < 0 || - q.num <= 0 || q.den <= 0) { - av_log(ost, AV_LOG_FATAL, "Invalid time base: %s\n", time_base); - exit_program(1); - } - st->time_base = q; - } - - MATCH_PER_STREAM_OPT(enc_time_bases, str, time_base, oc, st); - if (time_base) { - AVRational q; - if (av_parse_ratio(&q, time_base, INT_MAX, 0, NULL) < 0 || - q.den <= 0) { - av_log(ost, AV_LOG_FATAL, "Invalid time base: %s\n", time_base); - exit_program(1); - } - ost->enc_timebase = q; - } - - ms->max_frames = INT64_MAX; - MATCH_PER_STREAM_OPT(max_frames, i64, ms->max_frames, oc, st); - for (i = 0; inb_max_frames; i++) { - char *p = o->max_frames[i].specifier; - if (!*p && type != AVMEDIA_TYPE_VIDEO) { - av_log(ost, AV_LOG_WARNING, "Applying unspecific -frames to non video streams, maybe you meant -vframes ?\n"); - break; - } - } - - ost->copy_prior_start = -1; - MATCH_PER_STREAM_OPT(copy_prior_start, i, ost->copy_prior_start, oc ,st); - - MATCH_PER_STREAM_OPT(bitstream_filters, str, bsfs, oc, st); - if (bsfs && *bsfs) { - ret = av_bsf_list_parse_str(bsfs, &ms->bsf_ctx); - if (ret < 0) { - av_log(ost, AV_LOG_ERROR, "Error parsing bitstream filter sequence '%s': %s\n", bsfs, av_err2str(ret)); - exit_program(1); - } - } - - MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, oc, st); - if (codec_tag) { - uint32_t tag = strtol(codec_tag, &next, 0); - if (*next) - tag = AV_RL32(codec_tag); - ost->st->codecpar->codec_tag = tag; - if (ost->enc_ctx) - ost->enc_ctx->codec_tag = tag; - } - - MATCH_PER_STREAM_OPT(qscale, dbl, qscale, oc, st); - if (ost->enc_ctx && qscale >= 0) { - ost->enc_ctx->flags |= AV_CODEC_FLAG_QSCALE; - ost->enc_ctx->global_quality = FF_QP2LAMBDA * qscale; - } - - ms->max_muxing_queue_size = 128; - MATCH_PER_STREAM_OPT(max_muxing_queue_size, i, ms->max_muxing_queue_size, oc, st); - - ms->muxing_queue_data_threshold = 50*1024*1024; - MATCH_PER_STREAM_OPT(muxing_queue_data_threshold, i, ms->muxing_queue_data_threshold, oc, st); - - MATCH_PER_STREAM_OPT(bits_per_raw_sample, i, ost->bits_per_raw_sample, - oc, st); - - MATCH_PER_STREAM_OPT(fix_sub_duration_heartbeat, i, ost->fix_sub_duration_heartbeat, - oc, st); - - if (oc->oformat->flags & AVFMT_GLOBALHEADER && ost->enc_ctx) - ost->enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; - - av_dict_copy(&ost->sws_dict, o->g->sws_dict, 0); - - av_dict_copy(&ost->swr_opts, o->g->swr_opts, 0); - if (ost->enc_ctx && av_get_exact_bits_per_sample(ost->enc_ctx->codec_id) == 24) - av_dict_set(&ost->swr_opts, "output_sample_bits", "24", 0); - - if (ost->ist) { - ost->ist->discard = 0; - ost->ist->st->discard = ost->ist->user_set_discard; - - if (!(ost->enc && (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO))) - ist_output_add(ost->ist, ost); - } - ost->last_mux_dts = AV_NOPTS_VALUE; - - MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, - ost->copy_initial_nonkeyframes, oc, st); - - return ost; -} + enum AVMediaType type, InputStream *ist); static char *get_ost_filters(const OptionsContext *o, AVFormatContext *oc, OutputStream *ost) @@ -1098,6 +860,247 @@ static OutputStream *new_subtitle_stream(Muxer *mux, const OptionsContext *o, In return ost; } +static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o, + enum AVMediaType type, InputStream *ist) +{ + AVFormatContext *oc = mux->fc; + MuxStream *ms; + OutputStream *ost; + const AVCodec *enc; + AVStream *st = avformat_new_stream(oc, NULL); + int ret = 0; + const char *bsfs = NULL, *time_base = NULL; + char *next, *codec_tag = NULL; + double qscale = -1; + int i; + + if (!st) + report_and_exit(AVERROR(ENOMEM)); + + if (oc->nb_streams - 1 < o->nb_streamid_map) + st->id = o->streamid_map[oc->nb_streams - 1]; + + ms = mux_stream_alloc(mux, type); + ost = &ms->ost; + + ms->muxing_queue = av_fifo_alloc2(8, sizeof(AVPacket*), 0); + if (!ms->muxing_queue) + report_and_exit(AVERROR(ENOMEM)); + ms->last_mux_dts = AV_NOPTS_VALUE; + + ost->st = st; + ost->ist = ist; + ost->kf.ref_pts = AV_NOPTS_VALUE; + st->codecpar->codec_type = type; + + ret = choose_encoder(o, oc, ost, &enc); + if (ret < 0) { + av_log(ost, AV_LOG_FATAL, "Error selecting an encoder\n"); + exit_program(1); + } + + if (enc) { + ost->enc_ctx = avcodec_alloc_context3(enc); + if (!ost->enc_ctx) + report_and_exit(AVERROR(ENOMEM)); + + ret = enc_alloc(&ost->enc, enc); + if (ret < 0) + report_and_exit(ret); + + av_strlcat(ms->log_name, "/", sizeof(ms->log_name)); + av_strlcat(ms->log_name, enc->name, sizeof(ms->log_name)); + } else { + av_strlcat(ms->log_name, "/copy", sizeof(ms->log_name)); + } + + ost->filtered_frame = av_frame_alloc(); + if (!ost->filtered_frame) + report_and_exit(AVERROR(ENOMEM)); + + ost->pkt = av_packet_alloc(); + if (!ost->pkt) + report_and_exit(AVERROR(ENOMEM)); + + if (ost->enc_ctx) { + AVCodecContext *enc = ost->enc_ctx; + AVIOContext *s = NULL; + char *buf = NULL, *arg = NULL, *preset = NULL; + const char *enc_stats_pre = NULL, *enc_stats_post = NULL, *mux_stats = NULL; + + ost->encoder_opts = filter_codec_opts(o->g->codec_opts, enc->codec_id, + oc, st, enc->codec); + + MATCH_PER_STREAM_OPT(presets, str, preset, oc, st); + ost->autoscale = 1; + MATCH_PER_STREAM_OPT(autoscale, i, ost->autoscale, oc, st); + if (preset && (!(ret = get_preset_file_2(preset, enc->codec->name, &s)))) { + AVBPrint bprint; + av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED); + do { + av_bprint_clear(&bprint); + buf = get_line(s, &bprint); + if (!buf[0] || buf[0] == '#') + continue; + if (!(arg = strchr(buf, '='))) { + av_log(ost, AV_LOG_FATAL, "Invalid line found in the preset file.\n"); + exit_program(1); + } + *arg++ = 0; + av_dict_set(&ost->encoder_opts, buf, arg, AV_DICT_DONT_OVERWRITE); + } while (!s->eof_reached); + av_bprint_finalize(&bprint, NULL); + avio_closep(&s); + } + if (ret) { + av_log(ost, AV_LOG_FATAL, + "Preset %s specified, but could not be opened.\n", preset); + exit_program(1); + } + + MATCH_PER_STREAM_OPT(enc_stats_pre, str, enc_stats_pre, oc, st); + if (enc_stats_pre && + (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) { + const char *format = "{fidx} {sidx} {n} {t}"; + + MATCH_PER_STREAM_OPT(enc_stats_pre_fmt, str, format, oc, st); + + ret = enc_stats_init(ost, &ost->enc_stats_pre, 1, enc_stats_pre, format); + if (ret < 0) + exit_program(1); + } + + MATCH_PER_STREAM_OPT(enc_stats_post, str, enc_stats_post, oc, st); + if (enc_stats_post && + (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) { + const char *format = "{fidx} {sidx} {n} {t}"; + + MATCH_PER_STREAM_OPT(enc_stats_post_fmt, str, format, oc, st); + + ret = enc_stats_init(ost, &ost->enc_stats_post, 0, enc_stats_post, format); + if (ret < 0) + exit_program(1); + } + + MATCH_PER_STREAM_OPT(mux_stats, str, mux_stats, oc, st); + if (mux_stats && + (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) { + const char *format = "{fidx} {sidx} {n} {t}"; + + MATCH_PER_STREAM_OPT(mux_stats_fmt, str, format, oc, st); + + ret = enc_stats_init(ost, &ms->stats, 0, mux_stats, format); + if (ret < 0) + exit_program(1); + } + } else { + ost->encoder_opts = filter_codec_opts(o->g->codec_opts, AV_CODEC_ID_NONE, oc, st, NULL); + } + + + if (o->bitexact) { + ost->bitexact = 1; + } else if (ost->enc_ctx) { + ost->bitexact = check_opt_bitexact(ost->enc_ctx, ost->encoder_opts, "flags", + AV_CODEC_FLAG_BITEXACT); + } + + MATCH_PER_STREAM_OPT(time_bases, str, time_base, oc, st); + if (time_base) { + AVRational q; + if (av_parse_ratio(&q, time_base, INT_MAX, 0, NULL) < 0 || + q.num <= 0 || q.den <= 0) { + av_log(ost, AV_LOG_FATAL, "Invalid time base: %s\n", time_base); + exit_program(1); + } + st->time_base = q; + } + + MATCH_PER_STREAM_OPT(enc_time_bases, str, time_base, oc, st); + if (time_base) { + AVRational q; + if (av_parse_ratio(&q, time_base, INT_MAX, 0, NULL) < 0 || + q.den <= 0) { + av_log(ost, AV_LOG_FATAL, "Invalid time base: %s\n", time_base); + exit_program(1); + } + ost->enc_timebase = q; + } + + ms->max_frames = INT64_MAX; + MATCH_PER_STREAM_OPT(max_frames, i64, ms->max_frames, oc, st); + for (i = 0; inb_max_frames; i++) { + char *p = o->max_frames[i].specifier; + if (!*p && type != AVMEDIA_TYPE_VIDEO) { + av_log(ost, AV_LOG_WARNING, "Applying unspecific -frames to non video streams, maybe you meant -vframes ?\n"); + break; + } + } + + ost->copy_prior_start = -1; + MATCH_PER_STREAM_OPT(copy_prior_start, i, ost->copy_prior_start, oc ,st); + + MATCH_PER_STREAM_OPT(bitstream_filters, str, bsfs, oc, st); + if (bsfs && *bsfs) { + ret = av_bsf_list_parse_str(bsfs, &ms->bsf_ctx); + if (ret < 0) { + av_log(ost, AV_LOG_ERROR, "Error parsing bitstream filter sequence '%s': %s\n", bsfs, av_err2str(ret)); + exit_program(1); + } + } + + MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, oc, st); + if (codec_tag) { + uint32_t tag = strtol(codec_tag, &next, 0); + if (*next) + tag = AV_RL32(codec_tag); + ost->st->codecpar->codec_tag = tag; + if (ost->enc_ctx) + ost->enc_ctx->codec_tag = tag; + } + + MATCH_PER_STREAM_OPT(qscale, dbl, qscale, oc, st); + if (ost->enc_ctx && qscale >= 0) { + ost->enc_ctx->flags |= AV_CODEC_FLAG_QSCALE; + ost->enc_ctx->global_quality = FF_QP2LAMBDA * qscale; + } + + ms->max_muxing_queue_size = 128; + MATCH_PER_STREAM_OPT(max_muxing_queue_size, i, ms->max_muxing_queue_size, oc, st); + + ms->muxing_queue_data_threshold = 50*1024*1024; + MATCH_PER_STREAM_OPT(muxing_queue_data_threshold, i, ms->muxing_queue_data_threshold, oc, st); + + MATCH_PER_STREAM_OPT(bits_per_raw_sample, i, ost->bits_per_raw_sample, + oc, st); + + MATCH_PER_STREAM_OPT(fix_sub_duration_heartbeat, i, ost->fix_sub_duration_heartbeat, + oc, st); + + if (oc->oformat->flags & AVFMT_GLOBALHEADER && ost->enc_ctx) + ost->enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; + + av_dict_copy(&ost->sws_dict, o->g->sws_dict, 0); + + av_dict_copy(&ost->swr_opts, o->g->swr_opts, 0); + if (ost->enc_ctx && av_get_exact_bits_per_sample(ost->enc_ctx->codec_id) == 24) + av_dict_set(&ost->swr_opts, "output_sample_bits", "24", 0); + + if (ost->ist) { + ost->ist->discard = 0; + ost->ist->st->discard = ost->ist->user_set_discard; + + if (!(ost->enc && (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO))) + ist_output_add(ost->ist, ost); + } + ost->last_mux_dts = AV_NOPTS_VALUE; + + MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, + ost->copy_initial_nonkeyframes, oc, st); + + return ost; +} + static void init_output_filter(OutputFilter *ofilter, const OptionsContext *o, Muxer *mux) {