PR #25166 opened by Edison Ling (edisonling) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25166 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25166.patch
Previously the queue limit was raised from pa_lookahead_buffer_depth inside ff_amf_encode_init(), before per-codec setup. Adaptive mini-GOP can force AMF_PA_LOOKAHEAD_BUFFER_DEPTH to 1 when that option is -1 or 0, so async_depth stayed at 1. The receive path can then refuse further input and the encoder can stall. Fix this by reading the applied depth back after lookahead and B-frame properties are final and widening async_depth to that value plus one, before Init(). Option ranges stay at MAX_LOOKAHEAD_DEPTH. This is the read-back part of #24055; runtime maximum and option-ceiling changes are planned as a follow-up PR. ## Testing AMD Radeon RX 9070 XT, driver 32.0.31041.1004, MSVC `--enable-amf`. Patched vs unpatched at the same upstream commit; 2 s `testsrc2` 1280x720. Unpatched ffmpeg on an RX 9070 (#24055) could hang with `h264_amf`, `-preanalysis 1 -pa_adaptive_mini_gop 1 -async_depth 1`. On my 9070 XT both builds finish; only the patched build logs widening async_depth after read-back. Default `h264_amf`: no change vs unpatched. Same preanalysis/adaptive mini-GOP/`async_depth 1` on `h264_amf` and `av1_amf`: patched widens async_depth when needed; output matches unpatched. `-pa_lookahead_buffer_depth 20 -async_depth 4`: with preanalysis off, unpatched still bumps async_depth from the option alone; patched does not, with unchanged output vs a normal encode. With preanalysis on, both bump; outputs match. >From a0515a10c6a9524a11b842870476f033f28ac10b Mon Sep 17 00:00:00 2001 From: Edison Ling <[email protected]> Date: Sat, 17 Oct 2026 21:23:12 -0400 Subject: [PATCH] avcodec/amfenc: fix async_depth sizing from applied lookahead Previously the queue limit was raised from pa_lookahead_buffer_depth inside ff_amf_encode_init(), before per-codec setup. Adaptive mini-GOP can force AMF_PA_LOOKAHEAD_BUFFER_DEPTH to 1 when that option is -1 or 0, so async_depth stayed at 1. The receive path can then refuse further input and the encoder can stall. Fix this by reading the applied depth back after lookahead and B-frame properties are final and widening async_depth to that value plus one, before Init(). Option ranges stay at MAX_LOOKAHEAD_DEPTH. Signed-off-by: Edison Ling <[email protected]> --- libavcodec/amfenc.c | 25 ++++++++++++++++--------- libavcodec/amfenc.h | 7 +++++++ libavcodec/amfenc_av1.c | 2 ++ libavcodec/amfenc_h264.c | 2 ++ libavcodec/amfenc_hevc.c | 2 ++ 5 files changed, 29 insertions(+), 9 deletions(-) diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c index 20bc22d98c..f78d7ba39e 100644 --- a/libavcodec/amfenc.c +++ b/libavcodec/amfenc.c @@ -33,6 +33,8 @@ #include "libavutil/pixdesc.h" #include "libavutil/time.h" +#include <AMF/components/PreAnalysis.h> + #include "amfenc.h" #include "encode.h" @@ -278,6 +280,20 @@ static int amf_copy_buffer(AVCodecContext *avctx, AVPacket *pkt, AMFBuffer *buff return 0; } +void ff_amf_fit_async_depth(AVCodecContext *avctx, AMFEncoderContext *ctx) +{ + AMFVariantStruct var = { 0 }; + AMF_RESULT res; + + res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_PA_LOOKAHEAD_BUFFER_DEPTH, &var); + if (res == AMF_OK && var.int64Value >= ctx->hwsurfaces_in_queue_max) { + av_log(avctx, AV_LOG_WARNING, + "async_depth (%d) too small for lookahead (%lld), increasing to (%lld)\n", + ctx->hwsurfaces_in_queue_max, (long long)var.int64Value, (long long)(var.int64Value + 1)); + ctx->hwsurfaces_in_queue_max = (int)(var.int64Value + 1); + } +} + // amfenc API implementation int ff_amf_encode_init(AVCodecContext *avctx) { @@ -326,15 +342,6 @@ int ff_amf_encode_init(AVCodecContext *avctx) AMF_RETURN_IF_FALSE(ctx, ret == 0, ret, "Failed to create hardware device context (AMF) : %s\n", av_err2str(ret)); } - if (ctx->pa_lookahead_buffer_depth >= ctx->hwsurfaces_in_queue_max) { - av_log(avctx, AV_LOG_WARNING, - "async_depth (%d) too small for lookahead (%d), increasing to (%d)\n", - ctx->hwsurfaces_in_queue_max, - ctx->pa_lookahead_buffer_depth, - ctx->pa_lookahead_buffer_depth + 1); - ctx->hwsurfaces_in_queue_max = ctx->pa_lookahead_buffer_depth + 1; - } - if ((ret = amf_init_encoder(avctx)) == 0) { return 0; } diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h index 6a380208d1..03320fecd7 100644 --- a/libavcodec/amfenc.h +++ b/libavcodec/amfenc.h @@ -154,6 +154,13 @@ int ff_amf_encode_init(AVCodecContext *avctx); */ int ff_amf_encode_close(AVCodecContext *avctx); +/** + * Widen async_depth (hwsurfaces_in_queue_max) to the lookahead depth AMF + * has applied, plus one. Call before encoder Init(), after lookahead and + * B-frame properties are final. + */ +void ff_amf_fit_async_depth(AVCodecContext *avctx, AMFEncoderContext *ctx); + /** * Ecoding one frame - common function for all AMF encoders */ diff --git a/libavcodec/amfenc_av1.c b/libavcodec/amfenc_av1.c index a572d439a7..896899806c 100644 --- a/libavcodec/amfenc_av1.c +++ b/libavcodec/amfenc_av1.c @@ -574,6 +574,8 @@ static av_cold int amf_encode_init_av1(AVCodecContext* avctx) res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_AV1_QUERY_TIMEOUT, &var); ctx->query_timeout_supported = res == AMF_OK && var.int64Value; + ff_amf_fit_async_depth(avctx, ctx); + // init encoder res = ctx->encoder->pVtbl->Init(ctx->encoder, ctx->format, avctx->width, avctx->height); AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "encoder->Init() failed with error %d\n", res); diff --git a/libavcodec/amfenc_h264.c b/libavcodec/amfenc_h264.c index 214fac6909..04a74c25df 100644 --- a/libavcodec/amfenc_h264.c +++ b/libavcodec/amfenc_h264.c @@ -552,6 +552,8 @@ static av_cold int amf_encode_init_h264(AVCodecContext *avctx) res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_QUERY_TIMEOUT, &var); ctx->query_timeout_supported = res == AMF_OK && var.int64Value; + ff_amf_fit_async_depth(avctx, ctx); + // Initialize Encoder res = ctx->encoder->pVtbl->Init(ctx->encoder, ctx->format, avctx->width, avctx->height); AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "encoder->Init() failed with error %d\n", res); diff --git a/libavcodec/amfenc_hevc.c b/libavcodec/amfenc_hevc.c index 4e280fcf15..290b64f73d 100644 --- a/libavcodec/amfenc_hevc.c +++ b/libavcodec/amfenc_hevc.c @@ -484,6 +484,8 @@ static av_cold int amf_encode_init_hevc(AVCodecContext *avctx) res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QUERY_TIMEOUT, &var); ctx->query_timeout_supported = res == AMF_OK && var.int64Value; + ff_amf_fit_async_depth(avctx, ctx); + // init encoder res = ctx->encoder->pVtbl->Init(ctx->encoder, ctx->format, avctx->width, avctx->height); AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "encoder->Init() failed with error %d\n", res); -- 2.54.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
