From 4f9afbb1b2039599b0571f63b2bca6645272c68b Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 27 Dec 2024 12:03:41 -0300 Subject: [PATCH] fftools/ffmpeg_filter: reinitialize the filterchain if downmix metadata changed between frames Signed-off-by: James Almer --- fftools/ffmpeg_filter.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 0fb31243f8..7992c01948 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -30,6 +30,7 @@ #include "libavutil/avstring.h" #include "libavutil/bprint.h" #include "libavutil/channel_layout.h" +#include "libavutil/downmix_info.h" #include "libavutil/mem.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" @@ -150,6 +151,9 @@ typedef struct InputFilterPriv { int displaymatrix_applied; int32_t displaymatrix[9]; + int downmixinfo_present; + AVDownmixInfo downmixinfo; + struct { AVFrame *frame; @@ -2119,6 +2123,19 @@ static int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *fr memcpy(ifp->displaymatrix, sd->data, sizeof(ifp->displaymatrix)); ifp->displaymatrix_present = !!sd; + /* Copy downmix related side data to InputFilterPriv so it may be propagated + * to the filter chain even though it's not "global", as filters like aresample + * require this information during init and not when remixing a frame */ + sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DOWNMIX_INFO); + if (sd) { + ret = av_frame_side_data_clone(&ifp->side_data, + &ifp->nb_side_data, sd, 0); + if (ret < 0) + return ret; + memcpy(&ifp->downmixinfo, sd->data, sizeof(ifp->downmixinfo)); + } + ifp->downmixinfo_present = !!sd; + return 0; } @@ -2832,7 +2849,8 @@ enum ReinitReason { VIDEO_CHANGED = (1 << 0), AUDIO_CHANGED = (1 << 1), MATRIX_CHANGED = (1 << 2), - HWACCEL_CHANGED = (1 << 3) + DOWNMIX_CHANGED = (1 << 3), + HWACCEL_CHANGED = (1 << 4) }; static const char *unknown_if_null(const char *str) @@ -2873,6 +2891,13 @@ static int send_frame(FilterGraph *fg, FilterGraphThread *fgt, } else if (ifp->displaymatrix_present) need_reinit |= MATRIX_CHANGED; + if (sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DOWNMIX_INFO)) { + if (!ifp->downmixinfo_present || + memcmp(sd->data, &ifp->downmixinfo, sizeof(ifp->downmixinfo))) + need_reinit |= DOWNMIX_CHANGED; + } else if (ifp->downmixinfo_present) + need_reinit |= DOWNMIX_CHANGED; + if (!(ifp->opts.flags & IFILTER_FLAG_REINIT) && fgt->graph) need_reinit = 0; @@ -2927,6 +2952,8 @@ static int send_frame(FilterGraph *fg, FilterGraphThread *fgt, } if (need_reinit & MATRIX_CHANGED) av_bprintf(&reason, "display matrix changed, "); + if (need_reinit & DOWNMIX_CHANGED) + av_bprintf(&reason, "downmix medatata changed, "); if (need_reinit & HWACCEL_CHANGED) av_bprintf(&reason, "hwaccel changed, "); if (reason.len > 1)