PR #24055 opened by Edison Ling (edisonling)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24055
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24055.patch

# Summary of changes

This replaces the hardcoded lookahead maximum `#define MAX_LOOKAHEAD_DEPTH 41`
with a runtime query, and sizes `async_depth` from the value AMF actually
applied rather than the raw option value. The second is what keeps the first
safe, so they ship together. The runtime query has to work around an ABI bug
in the unfixed AMF SDK headers, where the C bindings do not match the
shipped runtime. That handling is transitional and comes out once the
minimum AMF version carries the fix.

## Runtime maximum instead of the macro

Replace the hardcoded `MAX_LOOKAHEAD_DEPTH 41` bound on
`pa_lookahead_buffer_depth` and `async_depth` with the maximum AMF reports
at runtime, so the bound tracks what the runtime accepts instead of a
constant duplicated in FFmpeg. Values above that maximum are clamped with
a warning instead of being rejected by the option parser.

`async_depth` is now sized from the lookahead depth read back from the
encoder rather than the raw option value. The read-back is the value AMF
actually applied, which fixes a latent under-size that could stall the
encoder: adaptive mini-GOP forces a lookahead the raw option value does not
reflect, leaving `async_depth` at 1 against a lookahead of 1.

The two changes cannot be split: raising the option ceiling makes a value
like 1000 parse successfully, and without the read-back that would size
`async_depth` to 1001, replacing a hard parse error with a throttle that
never engages.

`async_depth` is no longer bounded by the option parser. The old ceiling
capped it at MAX_LOOKAHEAD_DEPTH + 1 at parse time, even with preanalysis
off where no lookahead is running. The cap now happens at encoder init, and
the maximum is only queryable when preanalysis is on, so with preanalysis
off nothing caps it. This is fine because `async_depth` only limits how many
frames can be in flight and sizes no allocation. The AMF runtime also
applies its own input backpressure by returning AMF_INPUT_FULL, which FFmpeg
handles by draining output and retrying.

## Workaround for the AMF SDK header bug

The maximum comes from `GetPropertyInfo`. With unfixed AMF SDK headers
its C mapping only matches the runtime on non-MSVC ABIs, so the correct
call is target-dependent. `configure` probes for the `reserved` field in
`AMFPropertyInfo` to detect headers where this is already corrected, and
the getter selects one of three arms at compile time:

- fixed headers: call `GetPropertyInfo` directly, on every target
- unfixed headers on Windows: the MSVC-built AMF runtime places the
  by-name overload in the by-index slot, so it is called through
  `GetPropertyInfoAt`. Gated on `_WIN32` rather than the compiler,
  because the runtime's layout is what matters. MinGW builds need this
  too, since the AMF runtime is still MSVC-built.
- unfixed headers elsewhere: declaration order already matches, so the
  direct call is correct

Unfixed headers also shift `AMFPropertyInfo` in the C mapping. The C++ type
has a virtual destructor, so its objects start with a vtable pointer that
the C definition leaves out, and every field is offset by the size of one
pointer. The getter skips past it before reading. Unlike the call selection
above, this is gated on the probe alone and not `_WIN32`, because that
vtable pointer is present under both Linux and Windows ABIs. The type check
after the skip validates the arithmetic.

## Removing the workaround

The ABI handling is transitional. Once the minimum AMF version includes the
header fix, all of the following can be deleted in a single commit:

- the `configure` probe and its `TYPES_LIST` entry
- the `#elif defined(_WIN32)` and `#else` arms of the getter
- the `#if !HAVE_AMFPROPERTYINFO_RESERVED` realign and its type check
- comments in this commit related to unfixed/fixed headers

After removing the workaround, only a single direct `GetPropertyInfo` call
should remain. The clamp and async_depth helpers are unaffected; they are
not part of the workaround.

# Testing

Tested on Radeon RX 9070 (Navi 48) and RX 7700 XT / 7800 XT (Navi 32),
covering RDNA4 and RDNA3. Both `configure` probe states were built and
exercised on every platform: `HAVE_AMFPROPERTYINFO_RESERVED` at 0 (unfixed
headers, workaround arms) and at 1 (fixed headers, direct call).

| Platform | Toolchain | Backend |
|---|---|---|
| Linux | GCC | Vulkan |
| Windows | MSVC | D3D11 |
| Windows | MinGW GCC | D3D11 |

Headers and runtime were also mismatched during testing, since users
typically build against the public 1.5.2 SDK while running whatever runtime
their driver ships. A `--disable-amf` build was checked to confirm the new
probe is skipped cleanly.

All cases used the same base command, varying the preanalysis and async
options:

`ffmpeg -i input.mp4 -vf format=nv12 -frames:v 60 -an -c:v h264_amf 
-preanalysis 1 -pa_lookahead_buffer_depth 10 -async_depth 4 -f null -`

On each platform, I ran a test matrix (~200 tests) over `h264_amf`,
`hevc_amf` and `av1_amf`. The query returned 41 on every GPU and runtime
tested, confirming it reports the same bound the removed macro hardcoded.
Within the previously accepted range the only behavioural change is in how
`async_depth` is sized. Relevant subset of test results (`h264_amf`,
max = 41):

| Options | Result |
|---|---|
| `-pa_lookahead_buffer_depth 40 -async_depth 1` | async 1 -> 41 |
| `-pa_lookahead_buffer_depth 41 -async_depth 1` | async 1 -> 42 |
| `-pa_lookahead_buffer_depth 42 -async_depth 1` | lookahead 42 -> 41, async 1 
-> 42 |
| `-pa_lookahead_buffer_depth 1000 -async_depth 16` | lookahead 1000 -> 41, 
async 16 -> 42 |
| `-pa_lookahead_buffer_depth 2147483647` | lookahead -> 41, async 16 -> 42 |
| `-pa_lookahead_buffer_depth 16 -async_depth 16` | async 16 -> 17 |
| `-pa_lookahead_buffer_depth 10 -async_depth 42` | unchanged |
| `-pa_lookahead_buffer_depth 10 -async_depth 43` | async 43 -> 42 |
| `-pa_lookahead_buffer_depth 10 -async_depth 1000` | async 1000 -> 42 |
| `-pa_adaptive_mini_gop 1 -async_depth 1` | async 1 -> 2 |
| `-pa_lookahead_buffer_depth 20 -async_depth 4` (PA off) | unchanged |
| `-async_depth 1000` (PA off) | unchanged, no cap |
| `-pa_lookahead_buffer_depth -2` | rejected at parse |
| `-async_depth 0` | rejected at parse |

`hevc_amf` and `av1_amf` match `h264_amf` above except for adaptive
mini-GOP: `hevc_amf` has no such option, and `av1_amf`'s effective lookahead
is unchanged there, so no bump applies.

Upstream and patched builds were also compared directly on the same hardware
and toolchain. For all six of my cases within the previously accepted range,
including those where `async_depth` now differs, the encoded bitstreams were
byte-identical, so the change does not affect encoding decisions.

Output equivalence: each container case was hashed with `-c copy -f md5`.
Each configuration produces the same bitstream across both header states,
and on Windows across both toolchains. Confirmed with synthetic input and
with a real 1080p H.264 clip.

_Note: I was unable to properly test on the RX 9060 XT. Preanalysis encodes
produced no output frames for me. It doesn't appear related to this change
since an unpatched master build fails the same way from the same command
line._

`ffmpeg -f lavfi -i testsrc2=size=1280x720:rate=30 -vf format=nv12 -frames:v 60 
-an -c:v h264_amf -preanalysis 1 -f null -`

_The encode reports frame=0 and produces no output. The exit code can still
be 0, so the frame count is the important part._


>From fb21753a9fc8f2c5dd7c084cdb07e046c1f79419 Mon Sep 17 00:00:00 2001
From: "Ling, Edison" <[email protected]>
Date: Fri, 7 Aug 2026 14:53:46 -0400
Subject: [PATCH] avcodec/amfenc: Replace hardcoded lookahead maximum with
 runtime query

Replace the hardcoded `MAX_LOOKAHEAD_DEPTH 41` bound on
`pa_lookahead_buffer_depth` and `async_depth` with the maximum AMF reports
at runtime, so the bound tracks what the runtime accepts instead of a
constant duplicated in FFmpeg. Values above that maximum are clamped with
a warning instead of being rejected by the option parser.

`async_depth` is now sized from the lookahead depth read back from the
encoder rather than the raw option value. The read-back is the value AMF
actually applied, which fixes a latent under-size when adaptive mini-GOP
raises the effective lookahead. The two changes cannot be split: raising
the option ceiling makes a value like 1000 parse successfully, and without
the read-back that would size `async_depth` to 1001, replacing a hard
parse error with a silent oversized allocation.

The maximum comes from `GetPropertyInfo`. With unfixed AMF SDK headers
its C mapping only matches the runtime on non-MSVC ABIs, so the correct
call is target-dependent. `configure` probes for the `reserved` field in
`AMFPropertyInfo` to detect headers where this is already corrected, and
the getter selects one of three calls at compile time:

 - fixed headers: call `GetPropertyInfo` directly, on every target
 - unfixed headers on Windows: the MSVC-built AMF runtime places the
   by-name overload in the by-index slot, so it is called through
   `GetPropertyInfoAt`. Gated on `_WIN32` rather than the compiler,
   because the runtime's layout is what matters -- MinGW builds need this
   too
 - unfixed headers elsewhere: declaration order already matches, so the
   direct call is correct

Unfixed headers also shift `AMFPropertyInfo` by one pointer in the C
mapping. That realign is unconditional and the type check after it
validates the arithmetic, so both are scoped to that branch only.
---
 configure                |   4 +-
 libavcodec/amfenc.c      | 108 +++++++++++++++++++++++++++++++++++----
 libavcodec/amfenc.h      |  24 ++++++++-
 libavcodec/amfenc_av1.c  |  11 ++--
 libavcodec/amfenc_h264.c |  11 ++--
 libavcodec/amfenc_hevc.c |  11 ++--
 6 files changed, 142 insertions(+), 27 deletions(-)

diff --git a/configure b/configure
index e09bbd7f04..0f645503c8 100755
--- a/configure
+++ b/configure
@@ -2679,6 +2679,7 @@ TYPES_LIST="
     kCVImageBufferTransferFunction_ITU_R_2020
     kCVImageBufferTransferFunction_SMPTE_ST_428_1
     kVTQPModulationLevel_Default
+    AMFPropertyInfo_reserved
     SecPkgContext_KeyingMaterialInfo
     socklen_t
     struct_addrinfo
@@ -7927,7 +7928,8 @@ fi
 
 enabled amf &&
     check_cpp_condition amf "AMF/core/Version.h" \
-        "(AMF_VERSION_MAJOR << 48 | AMF_VERSION_MINOR << 32 | 
AMF_VERSION_RELEASE << 16 | AMF_VERSION_BUILD_NUM) >= 0x1000500020000"
+        "(AMF_VERSION_MAJOR << 48 | AMF_VERSION_MINOR << 32 | 
AMF_VERSION_RELEASE << 16 | AMF_VERSION_BUILD_NUM) >= 0x1000500020000" &&
+    check_struct "AMF/core/PropertyStorageEx.h" "AMFPropertyInfo" reserved
 
 # Funny iconv installations are not unusual, so check it after all flags have 
been set
 if enabled libc_iconv; then
diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c
index 3ffca750d8..4c052b47a2 100644
--- a/libavcodec/amfenc.c
+++ b/libavcodec/amfenc.c
@@ -36,6 +36,8 @@
 #include "amfenc.h"
 #include "encode.h"
 
+#include <AMF/components/PreAnalysis.h>
+
 #define AMF_AV_FRAME_REF    L"av_frame_ref"
 #define PTS_PROP            L"PtsProp"
 
@@ -166,6 +168,103 @@ int av_cold ff_amf_encode_close(AVCodecContext *avctx)
     return 0;
 }
 
+int ff_amf_get_lookahead_depth_max(AVCodecContext *avctx, AMFComponent 
*encoder, amf_int64 *out_max)
+{
+    // Query the maximum accepted value of AMF_PA_LOOKAHEAD_BUFFER_DEPTH.
+    // With unfixed AMF SDK headers the C vtable mapping only matches the 
runtime on
+    // non-MSVC ABIs, so the correct call is target-dependent (see each arm 
below).
+    // HAVE_AMFPROPERTYINFO_RESERVED detects whether the header fix is present.
+    // TODO: once the minimum AMF version includes the fix, the configure 
probe and
+    // legacy branches can be dropped entirely.
+    const wchar_t *name = AMF_PA_LOOKAHEAD_BUFFER_DEPTH;
+    const AMFPropertyInfo *prop_info = NULL;
+    AMF_RESULT res;
+
+    if (!encoder || !out_max)
+        return AVERROR(EINVAL);
+
+#if HAVE_AMFPROPERTYINFO_RESERVED
+    // Fixed SDK ABI: the C *Vtbl declaration order matches the runtime on 
every
+    // target (Win-MSVC, Win-MinGW, Linux), so pVtbl->GetPropertyInfo is the
+    // by-name overload. Call it directly.
+    res = encoder->pVtbl->GetPropertyInfo(encoder, name, &prop_info);
+    av_log(avctx, AV_LOG_DEBUG, "GetPropertyInfo() returned %d\n", res);
+#elif defined(_WIN32)
+    // Unfixed SDK ABI on Windows: amfrt64.dll is MSVC-built, and MSVC lays 
overloaded
+    // virtuals in reverse declaration order, so the by-name GetPropertyInfo 
sits in
+    // the by-index GetPropertyInfoAt slot. Gated on _WIN32, not the compiler: 
the
+    // runtime's layout is what matters, so MinGW builds need this too.
+    typedef AMF_RESULT (AMF_STD_CALL *GetPropInfoByNameFn)(AMFComponent *, 
const wchar_t *, const AMFPropertyInfo **);
+    GetPropInfoByNameFn get_by_name = (GetPropInfoByNameFn)(void 
*)encoder->pVtbl->GetPropertyInfoAt;
+    res = get_by_name(encoder, name, &prop_info);
+    av_log(avctx, AV_LOG_DEBUG, "GetPropertyInfoAt() returned %d\n", res);
+#else
+    // Unfixed SDK ABI, non-MSVC runtime (GCC/Clang on Linux; Itanium C++ ABI):
+    // overloaded virtuals keep declaration order, so the declared 
GetPropertyInfo
+    // slot is already by-name. Call it directly; swapping would hit by-index.
+    res = encoder->pVtbl->GetPropertyInfo(encoder, name, &prop_info);
+    av_log(avctx, AV_LOG_DEBUG, "GetPropertyInfo() returned %d\n", res);
+#endif
+    if (res != AMF_OK || !prop_info)
+        return AVERROR_EXTERNAL;
+
+#if !HAVE_AMFPROPERTYINFO_RESERVED
+    // Unfixed SDK ABI: AMFPropertyInfo starts with an extra pointer the C 
mapping
+    // omits (the C++ destructor's vtable pointer), so skip it to realign 
before reading.
+    prop_info = (const AMFPropertyInfo *)((const uint8_t *)prop_info + 
sizeof(void *));
+    if (prop_info->type != AMF_VARIANT_INT64)
+        return AVERROR_EXTERNAL;
+#endif
+
+    *out_max = prop_info->maxValue.int64Value;
+    return 0;
+}
+
+void ff_amf_clamp_lookahead_depth(AVCodecContext *avctx, AMFEncoderContext 
*ctx)
+{
+    amf_int64 hw_max;
+    AMF_RESULT res;
+
+    if (ff_amf_get_lookahead_depth_max(avctx, ctx->encoder, &hw_max) == 0 &&
+        ctx->pa_lookahead_buffer_depth > hw_max) {
+        av_log(avctx, AV_LOG_WARNING,
+            "pa_lookahead_buffer_depth %d exceeds supported maximum %lld, 
clamping\n",
+            ctx->pa_lookahead_buffer_depth, (long long)hw_max);
+        ctx->pa_lookahead_buffer_depth = (int)hw_max;
+    }
+
+    AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, 
AMF_PA_LOOKAHEAD_BUFFER_DEPTH, ctx->pa_lookahead_buffer_depth);
+    if (res != AMF_OK)
+        av_log(avctx, AV_LOG_WARNING, "Setting lookahead buffer depth failed 
with error %d\n", res);
+}
+
+void ff_amf_fit_async_depth(AVCodecContext *avctx, AMFEncoderContext *ctx)
+{
+    // Size async_depth to the lookahead window in two independent steps:
+    //   - bump: widen async_depth to fit the lookahead depth read back from 
the
+    //     encoder (the applied value; only present when preanalysis is 
enabled).
+    //   - cap: limit async_depth to the reported maximum + 1 when it can be 
queried.
+    amf_int64 hw_max;
+    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);
+    }
+
+    if (ff_amf_get_lookahead_depth_max(avctx, ctx->encoder, &hw_max) == 0 &&
+        ctx->hwsurfaces_in_queue_max > hw_max + 1) {
+        av_log(avctx, AV_LOG_WARNING,
+            "async_depth %d exceeds supported range, clamping to %lld\n",
+            ctx->hwsurfaces_in_queue_max, (long long)(hw_max + 1));
+        ctx->hwsurfaces_in_queue_max = (int)(hw_max + 1);
+    }
+}
+
 static int amf_copy_surface(AVCodecContext *avctx, const AVFrame *frame,
     AMFSurface* surface)
 {
@@ -326,15 +425,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 1571541b9b..e68f039fdf 100644
--- a/libavcodec/amfenc.h
+++ b/libavcodec/amfenc.h
@@ -31,8 +31,6 @@
 #include "avcodec.h"
 #include "hwconfig.h"
 
-#define  MAX_LOOKAHEAD_DEPTH 41
-
 /**
 * AMF encoder context
 */
@@ -158,6 +156,28 @@ int ff_amf_encode_close(AVCodecContext *avctx);
 */
 int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt);
 
+/**
+* Query the maximum PA lookahead buffer depth (AMF_PA_LOOKAHEAD_BUFFER_DEPTH).
+* Only available once preanalysis is enabled on the encoder.
+* @return 0 and sets *out_max on success; a negative AVERROR on failure.
+*/
+int ff_amf_get_lookahead_depth_max(AVCodecContext *avctx, AMFComponent 
*encoder, amf_int64 *out_max);
+
+/**
+* Clamp pa_lookahead_buffer_depth to the AMF-reported maximum and assign it to
+* the encoder. Call from within the preanalysis configuration block, before
+* encoder Init().
+*/
+void ff_amf_clamp_lookahead_depth(AVCodecContext *avctx, AMFEncoderContext 
*ctx);
+
+/**
+* Size async_depth (hwsurfaces_in_queue_max) around the lookahead window: widen
+* it to hold the lookahead depth read back from the encoder, then cap it at the
+* AMF-reported lookahead maximum + 1. Call before encoder Init(), after all
+* lookahead/B-frame properties have been set.
+*/
+void ff_amf_fit_async_depth(AVCodecContext *avctx, AMFEncoderContext *ctx);
+
 /**
 * Supported formats
 */
diff --git a/libavcodec/amfenc_av1.c b/libavcodec/amfenc_av1.c
index af20b5d04d..00966c23a8 100644
--- a/libavcodec/amfenc_av1.c
+++ b/libavcodec/amfenc_av1.c
@@ -101,7 +101,7 @@ static const AVOption options[] = {
     { "gop",                    "", 0, AV_OPT_TYPE_CONST, {.i64 = 
AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE_GOP_ALIGNED       }, 0, 0, VE, 
.unit = "hdrmode" },
     { "frame",                  "", 0, AV_OPT_TYPE_CONST, {.i64 = 
AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE_KEY_FRAME_ALIGNED }, 0, 0, VE, 
.unit = "hdrmode" },
 
-    { "async_depth",            "Set maximum encoding parallelism. Higher 
values increase output latency.", OFFSET(hwsurfaces_in_queue_max), 
AV_OPT_TYPE_INT, {.i64 = 16 }, 1, MAX_LOOKAHEAD_DEPTH + 1, VE },
+    { "async_depth",            "Set maximum encoding parallelism. Higher 
values increase output latency.", OFFSET(hwsurfaces_in_queue_max), 
AV_OPT_TYPE_INT, {.i64 = 16 }, 1, INT_MAX, VE },
 
     { "preencode",              "Enable preencode",     OFFSET(preencode),     
 AV_OPT_TYPE_BOOL, {.i64 = -1  }, -1, 1, VE},
     { "enforce_hrd",            "Enforce HRD",          OFFSET(enforce_hrd),   
 AV_OPT_TYPE_BOOL, {.i64 = -1  }, -1, 1, VE},
@@ -169,7 +169,7 @@ static const AVOption options[] = {
 
     { "pa_frame_sad_enable",                    "Enable Frame SAD algorithm",  
                                 OFFSET(pa_frame_sad),                          
 AV_OPT_TYPE_BOOL,   {.i64 = -1 }, -1, 1, VE },
     { "pa_ltr_enable",                          "Enable long term reference 
frame management",                  OFFSET(pa_ltr),                             
    AV_OPT_TYPE_BOOL,   {.i64 = -1 }, -1, 1, VE },
-    { "pa_lookahead_buffer_depth",              "Sets the PA lookahead buffer 
size",                            OFFSET(pa_lookahead_buffer_depth),            
  AV_OPT_TYPE_INT,    {.i64 = -1 }, -1, MAX_LOOKAHEAD_DEPTH, VE },
+    { "pa_lookahead_buffer_depth",              "Sets the PA lookahead buffer 
size",                            OFFSET(pa_lookahead_buffer_depth),            
  AV_OPT_TYPE_INT,    {.i64 = -1 }, -1, INT_MAX, VE },
 
     { "pa_paq_mode",                            "Sets the perceptual adaptive 
quantization mode",               OFFSET(pa_paq_mode),                          
  AV_OPT_TYPE_INT,    {.i64 = -1 }, -1, AMF_PA_PAQ_MODE_CAQ, VE , .unit = 
"paq_mode" },
     { "none",                                   "no perceptual adaptive 
quantization",  0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_PAQ_MODE_NONE }, 0, 0, VE, 
.unit = "paq_mode" },
@@ -504,9 +504,8 @@ static av_cold int amf_encode_init_av1(AVCodecContext* 
avctx)
         if (ctx->pa_ltr != -1) {
             AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_LTR_ENABLE, 
((ctx->pa_ltr == 0) ? false : true));
         }
-        if (ctx->pa_lookahead_buffer_depth != -1) {
-            AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, 
AMF_PA_LOOKAHEAD_BUFFER_DEPTH, ctx->pa_lookahead_buffer_depth);
-        }
+        if (ctx->pa_lookahead_buffer_depth != -1)
+            ff_amf_clamp_lookahead_depth(avctx, ctx);
         if (ctx->pa_high_motion_quality_boost_mode != -1) {
             AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, 
AMF_PA_HIGH_MOTION_QUALITY_BOOST_MODE, ctx->pa_high_motion_quality_boost_mode);
         }
@@ -573,6 +572,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 650a9bc7e9..994d1ec25f 100644
--- a/libavcodec/amfenc_h264.c
+++ b/libavcodec/amfenc_h264.c
@@ -114,7 +114,7 @@ static const AVOption options[] = {
     { "header_spacing", "Header Insertion Spacing",             
OFFSET(header_spacing),     AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1000, VE },
 
     /// Maximum queued frames
-    { "async_depth",    "Set maximum encoding parallelism. Higher values 
increase output latency.", OFFSET(hwsurfaces_in_queue_max), AV_OPT_TYPE_INT, 
{.i64 = 16 }, 1, MAX_LOOKAHEAD_DEPTH + 1, VE },
+    { "async_depth",    "Set maximum encoding parallelism. Higher values 
increase output latency.", OFFSET(hwsurfaces_in_queue_max), AV_OPT_TYPE_INT, 
{.i64 = 16 }, 1, INT_MAX, VE },
 
     /// B-Frames
     // BPicturesPattern=bf
@@ -175,7 +175,7 @@ static const AVOption options[] = {
 
     { "pa_frame_sad_enable",                    "Enable Frame SAD algorithm",  
                                 OFFSET(pa_frame_sad),                          
 AV_OPT_TYPE_BOOL,   {.i64 = -1 }, -1, 1, VE },
     { "pa_ltr_enable",                          "Enable long term reference 
frame management",                  OFFSET(pa_ltr),                             
    AV_OPT_TYPE_BOOL,   {.i64 = -1 }, -1, 1, VE },
-    { "pa_lookahead_buffer_depth",              "Sets the PA lookahead buffer 
size",                            OFFSET(pa_lookahead_buffer_depth),            
  AV_OPT_TYPE_INT,    {.i64 = -1 }, -1, MAX_LOOKAHEAD_DEPTH, VE },
+    { "pa_lookahead_buffer_depth",              "Sets the PA lookahead buffer 
size",                            OFFSET(pa_lookahead_buffer_depth),            
  AV_OPT_TYPE_INT,    {.i64 = -1 }, -1, INT_MAX, VE },
 
     { "pa_paq_mode",                            "Sets the perceptual adaptive 
quantization mode",               OFFSET(pa_paq_mode),                          
  AV_OPT_TYPE_INT,    {.i64 = -1 }, -1, AMF_PA_PAQ_MODE_CAQ, VE , .unit = 
"paq_mode" },
     { "none",                                   "no perceptual adaptive 
quantization",  0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_PAQ_MODE_NONE }, 0, 0, VE, 
.unit = "paq_mode" },
@@ -465,9 +465,8 @@ static av_cold int amf_encode_init_h264(AVCodecContext 
*avctx)
         if (ctx->pa_ltr != -1) {
             AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_LTR_ENABLE, 
((ctx->pa_ltr == 0) ? false : true));
         }
-        if (ctx->pa_lookahead_buffer_depth != -1) {
-            AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, 
AMF_PA_LOOKAHEAD_BUFFER_DEPTH, ctx->pa_lookahead_buffer_depth);
-        }
+        if (ctx->pa_lookahead_buffer_depth != -1)
+            ff_amf_clamp_lookahead_depth(avctx, ctx);
         if (ctx->pa_high_motion_quality_boost_mode != -1) {
             AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, 
AMF_PA_HIGH_MOTION_QUALITY_BOOST_MODE, ctx->pa_high_motion_quality_boost_mode);
         }
@@ -551,6 +550,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 6fa20d172e..e66ba3f7a8 100644
--- a/libavcodec/amfenc_hevc.c
+++ b/libavcodec/amfenc_hevc.c
@@ -91,7 +91,7 @@ static const AVOption options[] = {
     { "gop",            "", 0, AV_OPT_TYPE_CONST, { .i64 = 
AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_GOP_ALIGNED }, 0, 0, VE, .unit = 
"hdrmode" },
     { "idr",            "", 0, AV_OPT_TYPE_CONST, { .i64 = 
AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_IDR_ALIGNED }, 0, 0, VE, .unit = 
"hdrmode" },
 
-    { "async_depth",    "Set maximum encoding parallelism. Higher values 
increase output latency.",             OFFSET(hwsurfaces_in_queue_max), 
AV_OPT_TYPE_INT, {.i64 = 16 }, 1, MAX_LOOKAHEAD_DEPTH + 1, VE },
+    { "async_depth",    "Set maximum encoding parallelism. Higher values 
increase output latency.",             OFFSET(hwsurfaces_in_queue_max), 
AV_OPT_TYPE_INT, {.i64 = 16 }, 1, INT_MAX, VE },
 
     { "high_motion_quality_boost_enable",   "Enable High motion quality boost 
mode",  OFFSET(hw_high_motion_quality_boost), AV_OPT_TYPE_BOOL,   {.i64 = -1 }, 
-1, 1, VE },
     { "gops_per_idr",   "GOPs per IDR 0-no IDR will be inserted",   
OFFSET(gops_per_idr),  AV_OPT_TYPE_INT,  { .i64 = 1  },  0, INT_MAX, VE },
@@ -146,7 +146,7 @@ static const AVOption options[] = {
 
     { "pa_frame_sad_enable",                    "Enable Frame SAD algorithm",  
                                 OFFSET(pa_frame_sad),                          
 AV_OPT_TYPE_BOOL,   {.i64 = -1 }, -1, 1, VE },
     { "pa_ltr_enable",                          "Enable long term reference 
frame management",                  OFFSET(pa_ltr),                             
    AV_OPT_TYPE_BOOL,   {.i64 = -1 }, -1, 1, VE },
-    { "pa_lookahead_buffer_depth",              "Sets the PA lookahead buffer 
size",                            OFFSET(pa_lookahead_buffer_depth),            
  AV_OPT_TYPE_INT,    {.i64 = -1 }, -1, MAX_LOOKAHEAD_DEPTH, VE },
+    { "pa_lookahead_buffer_depth",              "Sets the PA lookahead buffer 
size",                            OFFSET(pa_lookahead_buffer_depth),            
  AV_OPT_TYPE_INT,    {.i64 = -1 }, -1, INT_MAX, VE },
 
     { "pa_paq_mode",                            "Sets the perceptual adaptive 
quantization mode",               OFFSET(pa_paq_mode),                          
  AV_OPT_TYPE_INT,    {.i64 = -1 }, -1, AMF_PA_PAQ_MODE_CAQ, VE , .unit = 
"paq_mode" },
     { "none",                                   "no perceptual adaptive 
quantization",  0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_PAQ_MODE_NONE }, 0, 0, VE, 
.unit = "paq_mode" },
@@ -470,9 +470,8 @@ static av_cold int amf_encode_init_hevc(AVCodecContext 
*avctx)
         if (ctx->pa_ltr != -1) {
             AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_LTR_ENABLE, 
((ctx->pa_ltr == 0) ? false : true));
         }
-        if (ctx->pa_lookahead_buffer_depth != -1) {
-            AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, 
AMF_PA_LOOKAHEAD_BUFFER_DEPTH, ctx->pa_lookahead_buffer_depth);
-        }
+        if (ctx->pa_lookahead_buffer_depth != -1)
+            ff_amf_clamp_lookahead_depth(avctx, ctx);
         if (ctx->pa_high_motion_quality_boost_mode != -1) {
             AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, 
AMF_PA_HIGH_MOTION_QUALITY_BOOST_MODE, ctx->pa_high_motion_quality_boost_mode);
         }
@@ -483,6 +482,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.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to