From b8e6802023a5e687c40b6565745a225f8e069657 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 2 Apr 2024 13:58:59 +0200 Subject: [PATCH] fftools/ffmpeg_filter: pass sws/swr opts through OutputFilterOptions Do not read them from OutputStream directly. Will allow decoupling filtering from encoding in future commits. --- fftools/ffmpeg.h | 7 +++++-- fftools/ffmpeg_filter.c | 27 ++++++++++++++++++++++----- fftools/ffmpeg_mux.c | 3 --- fftools/ffmpeg_mux_init.c | 11 ++++------- 4 files changed, 31 insertions(+), 17 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 786f925bc6..c61a670103 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -265,6 +265,8 @@ typedef struct InputFilterOptions { enum OFilterFlags { OFILTER_FLAG_DISABLE_CONVERT = (1 << 0), + // produce 24-bit audio + OFILTER_FLAG_AUDIO_24BIT = (1 << 1), }; typedef struct OutputFilterOptions { @@ -283,6 +285,9 @@ typedef struct OutputFilterOptions { */ AVRational output_tb; + AVDictionary *sws_opts; + AVDictionary *swr_opts; + // A combination of OFilterFlags. unsigned flags; @@ -574,8 +579,6 @@ typedef struct OutputStream { OutputFilter *filter; AVDictionary *encoder_opts; - AVDictionary *sws_dict; - AVDictionary *swr_opts; char *apad; char *attachment_filename; diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index d2fd26af7e..8aa4053716 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -210,6 +210,9 @@ typedef struct OutputFilterPriv { AVRational sample_aspect_ratio; + AVDictionary *sws_opts; + AVDictionary *swr_opts; + // those are only set if no format is specified and the encoder gives us multiple options // They point directly to the relevant lists of the encoder. const int *formats; @@ -813,6 +816,17 @@ int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost, if (!ofp->name) return AVERROR(EINVAL); + ret = av_dict_copy(&ofp->sws_opts, opts->sws_opts, 0); + if (ret < 0) + return ret; + + ret = av_dict_copy(&ofp->swr_opts, opts->swr_opts, 0); + if (ret < 0) + return ret; + + if (opts->flags & OFILTER_FLAG_AUDIO_24BIT) + av_dict_set(&ofp->swr_opts, "output_sample_bits", "24", 0); + if (fgp->is_simple) { // for simple filtergraph there is just one output, // so use only graph-level information for logging @@ -945,6 +959,8 @@ void fg_free(FilterGraph **pfg) OutputFilterPriv *ofp = ofp_from_ofilter(ofilter); av_frame_free(&ofp->fps.last_frame); + av_dict_free(&ofp->sws_opts); + av_dict_free(&ofp->swr_opts); av_freep(&ofilter->linklabel); av_freep(&ofilter->name); @@ -1358,7 +1374,7 @@ static int configure_output_video_filter(FilterGraph *fg, AVFilterGraph *graph, snprintf(args, sizeof(args), "%d:%d", ofp->width, ofp->height); - while ((e = av_dict_iterate(ost->sws_dict, e))) { + while ((e = av_dict_iterate(ofp->sws_opts, e))) { av_strlcatf(args, sizeof(args), ":%s=%s", e->key, e->value); } @@ -1725,6 +1741,7 @@ static int configure_filtergraph(FilterGraph *fg, FilterGraphThread *fgt) return AVERROR(ENOMEM); if (simple) { + OutputFilterPriv *ofp = ofp_from_ofilter(fg->outputs[0]); OutputStream *ost = fg->outputs[0]->ost; if (filter_nbthreads) { @@ -1738,17 +1755,17 @@ static int configure_filtergraph(FilterGraph *fg, FilterGraphThread *fgt) av_opt_set(fgt->graph, "threads", e->value, 0); } - if (av_dict_count(ost->sws_dict)) { - ret = av_dict_get_string(ost->sws_dict, + if (av_dict_count(ofp->sws_opts)) { + ret = av_dict_get_string(ofp->sws_opts, &fgt->graph->scale_sws_opts, '=', ':'); if (ret < 0) goto fail; } - if (av_dict_count(ost->swr_opts)) { + if (av_dict_count(ofp->swr_opts)) { char *args; - ret = av_dict_get_string(ost->swr_opts, &args, '=', ':'); + ret = av_dict_get_string(ofp->swr_opts, &args, '=', ':'); if (ret < 0) goto fail; av_opt_set(fgt->graph, "aresample_swr_opts", args, 0); diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 253c2e58d4..557f08b3a5 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -819,9 +819,6 @@ static void ost_free(OutputStream **post) av_freep(&ost->attachment_filename); - av_dict_free(&ost->sws_dict); - av_dict_free(&ost->swr_opts); - if (ost->enc_ctx) av_freep(&ost->enc_ctx->stats_in); avcodec_free_context(&ost->enc_ctx); diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 219be5f965..8f4b73f8a7 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1356,12 +1356,6 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type, 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); - MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, ms->copy_initial_nonkeyframes, oc, st); @@ -1392,10 +1386,13 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type, .vsync_method = vsync_method, .sample_rate = ost->enc_ctx->sample_rate, .ch_layout = ost->enc_ctx->ch_layout, + .sws_opts = o->g->sws_dict, + .swr_opts = o->g->swr_opts, .output_tb = enc_tb, .ts_offset = mux->of.start_time == AV_NOPTS_VALUE ? 0 : mux->of.start_time, - .flags = OFILTER_FLAG_DISABLE_CONVERT * !!keep_pix_fmt, + .flags = OFILTER_FLAG_DISABLE_CONVERT * !!keep_pix_fmt | + OFILTER_FLAG_AUDIO_24BIT * !!(av_get_exact_bits_per_sample(ost->enc_ctx->codec_id) == 24), }; snprintf(name, sizeof(name), "#%d:%d", mux->of.index, ost->index);