This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit 23e21331dfc21cb2ad344751fb6941e803546ca5 Author: Julius Bairaktaris <[email protected]> AuthorDate: Sun Aug 30 15:53:03 2026 +0200 Commit: ArazIusubov <[email protected]> CommitDate: Wed Sep 16 22:05:28 2026 +0000 avfilter/vf_amf_common: drain the component and tolerate AMF_REPEAT amf_filter_filter_frame() read the component output exactly once and treated anything but AMF_OK as fatal, so a component that had no output ready yet, which AMD's Video Converter programming guide documents as AMF_REPEAT, produced an error instead of simply consuming the frame. Poll until the component stops returning data, and accept AMF_REPEAT. A component that produces one output per input, which is what the scaler, the enhancer and the converter do today, behaves as before: one iteration with data, one without. Timestamps now come from the output surface, as vf_frc_amf.c already does, so a second output of the same submission does not inherit the first one's. Returning AVERROR(EAGAIN) from a filter_frame callback was wrong and is dropped. filter_frame_to_filter() latches a negative return into the link's status_out, which stalls a pull driven graph and stops EOF from crossing the filter; a frame that yields no output is simply consumed. AMF_INPUT_FULL on submission stays fatal. It means the frame was not accepted, so tolerating it would silently drop it, and the queue is already drained after every submission, so it cannot be reached by feeding the component faster than it produces. The input frame is kept until the loop ends, since its properties are copied onto every output, and freed once at the end. Tested on Windows 11, RX 9070 XT, driver 32.0.31041.1004: identical output and timestamps for every sr_amf algorithm, vpp_amf, vqe_amf and frc_amf, with software, AMF and D3D11VA input. Assisted-by: Claude Opus 5 Signed-off-by: Julius Bairaktaris <[email protected]> --- libavfilter/vf_amf_common.c | 102 ++++++++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 47 deletions(-) diff --git a/libavfilter/vf_amf_common.c b/libavfilter/vf_amf_common.c index 9b80a7cd1b..0d2a2f6257 100644 --- a/libavfilter/vf_amf_common.c +++ b/libavfilter/vf_amf_common.c @@ -99,6 +99,7 @@ int amf_filter_filter_frame(AVFilterLink *inlink, AVFrame *in) enum AVColorRange out_color_range; AVFrame *out = NULL; + int got_frame = 0; int ret = 0; if (!ctx->component) @@ -137,71 +138,78 @@ int amf_filter_filter_frame(AVFilterLink *inlink, AVFrame *in) res = ctx->component->pVtbl->SubmitInput(ctx->component, (AMFData*)surface_in); surface_in->pVtbl->Release(surface_in); // release surface after use AMF_GOTO_FAIL_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, "SubmitInput() failed with error %d\n", res); - res = ctx->component->pVtbl->QueryOutput(ctx->component, &data_out); - AMF_GOTO_FAIL_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, "QueryOutput() failed with error %d\n", res); - if (data_out) { + while (1) { AMFGuid guid = IID_AMFSurface(); + + res = ctx->component->pVtbl->QueryOutput(ctx->component, &data_out); + AMF_GOTO_FAIL_IF_FALSE(avctx, res == AMF_OK || res == AMF_REPEAT, AVERROR_UNKNOWN, "QueryOutput() failed with error %d\n", res); + if (!data_out) + break; + res = data_out->pVtbl->QueryInterface(data_out, &guid, (void**)&surface_out); // query for buffer interface data_out->pVtbl->Release(data_out); + data_out = NULL; AMF_GOTO_FAIL_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, "QueryInterface(IID_AMFSurface) failed with error %d\n", res); - } else { - ret = AVERROR(EAGAIN); - goto fail; - } - out = amf_amfsurface_to_avframe(avctx, surface_out); - AMF_GOTO_FAIL_IF_FALSE(avctx, out != NULL, AVERROR(ENOMEM), "Failed to convert AMFSurface to AVFrame\n"); + out = amf_amfsurface_to_avframe(avctx, surface_out); + AMF_GOTO_FAIL_IF_FALSE(avctx, out != NULL, AVERROR(ENOMEM), "Failed to convert AMFSurface to AVFrame\n"); - ret = av_frame_copy_props(out, in); - av_frame_unref(in); + ret = av_frame_copy_props(out, in); + if (ret < 0) + goto fail; + out->pts = surface_out->pVtbl->GetPts(surface_out); - out_colorspace = AVCOL_SPC_UNSPECIFIED; + out_colorspace = AVCOL_SPC_UNSPECIFIED; - if (ctx->color_profile != AMF_VIDEO_CONVERTER_COLOR_PROFILE_UNKNOWN) { - switch(ctx->color_profile) { - case AMF_VIDEO_CONVERTER_COLOR_PROFILE_601: - out_colorspace = AVCOL_SPC_SMPTE170M; - break; - case AMF_VIDEO_CONVERTER_COLOR_PROFILE_709: - out_colorspace = AVCOL_SPC_BT709; - break; - case AMF_VIDEO_CONVERTER_COLOR_PROFILE_2020: - out_colorspace = AVCOL_SPC_BT2020_NCL; - break; - case AMF_VIDEO_CONVERTER_COLOR_PROFILE_JPEG: - out_colorspace = AVCOL_SPC_RGB; - break; - default: - out_colorspace = AVCOL_SPC_UNSPECIFIED; - break; + if (ctx->color_profile != AMF_VIDEO_CONVERTER_COLOR_PROFILE_UNKNOWN) { + switch(ctx->color_profile) { + case AMF_VIDEO_CONVERTER_COLOR_PROFILE_601: + out_colorspace = AVCOL_SPC_SMPTE170M; + break; + case AMF_VIDEO_CONVERTER_COLOR_PROFILE_709: + out_colorspace = AVCOL_SPC_BT709; + break; + case AMF_VIDEO_CONVERTER_COLOR_PROFILE_2020: + out_colorspace = AVCOL_SPC_BT2020_NCL; + break; + case AMF_VIDEO_CONVERTER_COLOR_PROFILE_JPEG: + out_colorspace = AVCOL_SPC_RGB; + break; + default: + out_colorspace = AVCOL_SPC_UNSPECIFIED; + break; + } + out->colorspace = out_colorspace; } - out->colorspace = out_colorspace; - } - out_color_range = AVCOL_RANGE_UNSPECIFIED; - if (ctx->out_color_range == AMF_COLOR_RANGE_FULL) - out_color_range = AVCOL_RANGE_JPEG; - else if (ctx->out_color_range == AMF_COLOR_RANGE_STUDIO) - out_color_range = AVCOL_RANGE_MPEG; + out_color_range = AVCOL_RANGE_UNSPECIFIED; + if (ctx->out_color_range == AMF_COLOR_RANGE_FULL) + out_color_range = AVCOL_RANGE_JPEG; + else if (ctx->out_color_range == AMF_COLOR_RANGE_STUDIO) + out_color_range = AVCOL_RANGE_MPEG; - if (ctx->out_color_range != AMF_COLOR_RANGE_UNDEFINED) - out->color_range = out_color_range; + if (ctx->out_color_range != AMF_COLOR_RANGE_UNDEFINED) + out->color_range = out_color_range; - if (ctx->out_primaries != AMF_COLOR_PRIMARIES_UNDEFINED) - out->color_primaries = ctx->out_primaries; + if (ctx->out_primaries != AMF_COLOR_PRIMARIES_UNDEFINED) + out->color_primaries = ctx->out_primaries; - if (ctx->out_trc != AMF_COLOR_TRANSFER_CHARACTERISTIC_UNDEFINED) - out->color_trc = ctx->out_trc; + if (ctx->out_trc != AMF_COLOR_TRANSFER_CHARACTERISTIC_UNDEFINED) + out->color_trc = ctx->out_trc; - if (ctx->pre_converter) - out->colorspace = AVCOL_SPC_RGB; + if (ctx->pre_converter) + out->colorspace = AVCOL_SPC_RGB; - if (ret < 0) - goto fail; + ret = ff_filter_frame(outlink, out); + out = NULL; + if (ret < 0) + goto fail; + got_frame = 1; + } av_frame_free(&in); - return ff_filter_frame(outlink, out); + return got_frame ? ret : 0; fail: av_frame_free(&in); av_frame_free(&out); -- To stop receiving notification emails like this one, please contact [email protected]. _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
