[PR] Use coded surface sizes and dynamic bitstream buffers (PR #24306)

jianhuaw via ffmpeg-devel <[email protected]>
Newsgroups gmane.comp.video.ffmpeg.devel
Message-ID <[email protected]>
PR #24306 opened by jianhuaw
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24306
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24306.patch

# Summary of changes

  ## Background

  D3D12VA needs a CPU-visible upload buffer for each picture's compressed
  bitstream. The old implementation used the decoded YUV frame size as the
  buffer capacity.

  This was based on a common case: compressed video data is usually smaller than
  the decoded picture. It also avoided recreating the D3D12 upload resource while
  decoding.

  During early testing, most samples were 1080p or 4K. At 4K, a YUV 4:2:0 frame
  is about 11 MiB, so the fixed allocation did not stand out and memory use looked
  similar to other hardware decoders.

  ## Problem

  The decoded YUV size depends on resolution, while the compressed bitstream size
  depends on the video content and encoder settings.

  At 8K, one YUV 4:2:0 frame uses more than 40 MiB. In the current 8K test, the
  largest compressed bitstream is below 10 MiB. The old code therefore allocated
  more than 40 MiB for each upload buffer even when only a small part was used.

  D3D12VA keeps upload buffers with command helpers that can be in flight at the
  same time. This repeats the unused allocation and increases both process memory
  and GPU commit. The 8K test mainly focused on decode performance, so this was
  not obvious until player preview testing showed higher memory use.

  The decoded frame size is also not a valid upper limit for compressed data.
  Lightly compressed low-resolution MPEG video can have a bitstream larger than
  the decoded picture.

  ## Testing

| Sample | Frames | Before FPS | After FPS | Before Memory | After Memory | Before GPU Commit | After GPU Commit |
  | --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: |
  | HEVC 3840x2160 | 11904 | 645.51 | 646.97 | 1024.63 MiB | 764.11 MiB | 676.05 MiB | 413.59 MiB |
  | AV1 3840x2160 | 2880 | 383.19 | 383.40 | 286.05 MiB | 204.57 MiB | 209.66 MiB | 139.25 MiB |
  | VP9 7680x4320 | 16504 | 166.14 | 165.94 | 2329.95 MiB | 1372.44 MiB | 2098.50 MiB | 1147.08 MiB |

For 1080p and 4K content, the fixed allocation is still manageable. At 8K, it adds more than 1 GiB of memory, which is not acceptable for player preview.


>From 6ae030fb1e047c9227f5774a9cff414a7da2516c Mon Sep 17 00:00:00 2001
From: Wu Jianhua <[email protected]>
Date: Thu, 27 Aug 2026 05:50:00 +0800
Subject: [PATCH 1/3] avcodec/d3d12va_decode: use coded width and height

HEVC decoders write the full coded surface before applying the conformance window, so D3D12VA must allocate coded_width and coded_height rather than the visible frame dimensions.

SPS:
pic_width_in_luma_samples  = 3840
pic_height_in_luma_samples = 2176
conformance_window_flag    = 1
conf_win_bottom_offset     = 8

For 4:2:0, the bottom offset crops 16 luma samples, yielding a 3840x2160 display frame. Allocating the visible 3840x2160 surface failed on NVIDIA D3D12VA; using 3840x2176 decoded all 744 frames on an RTX 5080 with zero decode errors.

Signed-off-by: Wu Jianhua <[email protected]>
---
 libavcodec/d3d12va_decode.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libavcodec/d3d12va_decode.c b/libavcodec/d3d12va_decode.c
index 3a461c7fe0..538d9a4f6e 100644
--- a/libavcodec/d3d12va_decode.c
+++ b/libavcodec/d3d12va_decode.c
@@ -396,8 +396,8 @@ int ff_d3d12va_common_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames
     case AV_PIX_FMT_YUV420P12: frames_ctx->sw_format = AV_PIX_FMT_P012; break;
     default:                   frames_ctx->sw_format = AV_PIX_FMT_NV12; break;
     }
-    frames_ctx->width     = avctx->width;
-    frames_ctx->height    = avctx->height;
+    frames_ctx->width     = avctx->coded_width;
+    frames_ctx->height    = avctx->coded_height;
 
     return 0;
 }
-- 
2.52.0


>From dab8598fd474a177b492d7297de2127c1662e991 Mon Sep 17 00:00:00 2001
From: Wu Jianhua <[email protected]>
Date: Thu, 27 Aug 2026 08:11:49 +0800
Subject: [PATCH 2/3] avcodec/d3d12va_av1: dynamically allocate tile group
 bitstream buffer

Signed-off-by: Wu Jianhua <[email protected]>
---
 libavcodec/d3d12va_av1.c | 22 +++++++++-------------
 1 file changed, 9 insertions(+), 13 deletions(-)

diff --git a/libavcodec/d3d12va_av1.c b/libavcodec/d3d12va_av1.c
index 83222d6770..73f77e04cf 100644
--- a/libavcodec/d3d12va_av1.c
+++ b/libavcodec/d3d12va_av1.c
@@ -33,7 +33,7 @@
 typedef struct D3D12AV1DecodeContext {
     D3D12VADecodeContext ctx;
     uint8_t *bitstream_buffer;
-    size_t bitstream_size;
+    unsigned int bitstream_size;
 } D3D12AV1DecodeContext;
 
 #define D3D12_AV1_DECODE_CONTEXT(avctx) ((D3D12AV1DecodeContext *)D3D12VA_DECODE_CONTEXT(avctx))
@@ -93,10 +93,14 @@ static int d3d12va_av1_decode_slice(AVCodecContext *avctx,
         ctx_pic->bitstream      = (uint8_t *)buffer;
         ctx_pic->bitstream_size = size;
     } else {
-        if (ctx_pic->bitstream_size + (uint64_t)size > av1_ctx->bitstream_size) {
-            av_log(avctx, AV_LOG_ERROR, "Slice bitstream size exceeds internal buffer!\n");
-            return AVERROR(EINVAL);
-        }
+        size_t new_size = ctx_pic->bitstream_size + (size_t)size;
+        uint8_t *tmp = av_fast_realloc(av1_ctx->bitstream_buffer, &av1_ctx->bitstream_size, new_size);
+        if (!tmp)
+            return AVERROR(ENOMEM);
+
+        if (ctx_pic->bitstream_size && ctx_pic->bitstream != av1_ctx->bitstream_buffer)
+            memcpy(tmp, ctx_pic->bitstream, ctx_pic->bitstream_size);
+        av1_ctx->bitstream_buffer = tmp;
         ctx_pic->bitstream = av1_ctx->bitstream_buffer;
         memcpy(ctx_pic->bitstream + ctx_pic->bitstream_size, buffer, size);
         tg_start = h->tg_start;
@@ -169,7 +173,6 @@ static int d3d12va_av1_end_frame(AVCodecContext *avctx)
 static av_cold int d3d12va_av1_decode_init(AVCodecContext *avctx)
 {
     D3D12VADecodeContext    *ctx     = D3D12VA_DECODE_CONTEXT(avctx);
-    D3D12AV1DecodeContext   *av1_ctx = D3D12_AV1_DECODE_CONTEXT(avctx);
     DXVA_PicParams_AV1 pp;
 
     int ret;
@@ -193,13 +196,6 @@ static av_cold int d3d12va_av1_decode_init(AVCodecContext *avctx)
     if (ret < 0)
         return ret;
 
-    if (!av1_ctx->bitstream_buffer) {
-        av1_ctx->bitstream_size = ff_d3d12va_get_suitable_max_bitstream_size(avctx);
-        av1_ctx->bitstream_buffer = av_malloc(av1_ctx->bitstream_size);
-        if (!av1_ctx->bitstream_buffer)
-            return AVERROR(ENOMEM);
-    }
-
     return 0;
 }
 
-- 
2.52.0


>From 3e25b65e8f52530c952889bd164c7bda04224cdf Mon Sep 17 00:00:00 2001
From: Wu Jianhua <[email protected]>
Date: Thu, 27 Aug 2026 08:35:13 +0800
Subject: [PATCH 3/3] avcodec/d3d12va_decode: dynamically allocate bitstream
 upload buffers

                     Frames  Before FPS  After FPS  Before Memory  After Memory  Before GPU Commit  After GPU Commit
HEVC 3840x2160       11904      645.51     646.97    1024.63 MiB   764.11 MiB     676.05 MiB        413.59 MiB
AV1  3840x2160        2880      383.19     383.40     286.05 MiB   204.57 MiB     209.66 MiB        139.25 MiB
VP9  7680x4320       16504      166.14     165.94   2329.95 MiB  1372.44 MiB    2098.50 MiB       1147.08 MiB

Signed-off-by: Wu Jianhua <[email protected]>
---
 libavcodec/d3d12va_av1.c    |  8 ++--
 libavcodec/d3d12va_decode.c | 88 +++++++++++++++++++++----------------
 libavcodec/d3d12va_decode.h | 16 +------
 libavcodec/d3d12va_h264.c   | 12 ++++-
 libavcodec/d3d12va_hevc.c   | 14 ++++--
 libavcodec/d3d12va_mpeg2.c  |  8 ++--
 libavcodec/d3d12va_vc1.c    | 22 ++++++----
 libavcodec/d3d12va_vp9.c    |  8 ++--
 8 files changed, 102 insertions(+), 74 deletions(-)

diff --git a/libavcodec/d3d12va_av1.c b/libavcodec/d3d12va_av1.c
index 73f77e04cf..4e85620f96 100644
--- a/libavcodec/d3d12va_av1.c
+++ b/libavcodec/d3d12va_av1.c
@@ -122,9 +122,9 @@ static int d3d12va_av1_decode_slice(AVCodecContext *avctx,
 
 static int update_input_arguments(AVCodecContext *avctx, D3D12_VIDEO_DECODE_INPUT_STREAM_ARGUMENTS *input_args, ID3D12Resource *buffer)
 {
-    D3D12VADecodeContext    *ctx          = D3D12VA_DECODE_CONTEXT(avctx);
     const AV1DecContext     *h            = avctx->priv_data;
     AV1DecodePictureContext *ctx_pic      = h->cur_frame.hwaccel_picture_private;
+    D3D12_RESOURCE_DESC desc;
     void *mapped_data;
 
     D3D12_VIDEO_DECODE_FRAME_ARGUMENT *args = &input_args->FrameArguments[input_args->NumFrameArguments++];
@@ -132,7 +132,8 @@ static int update_input_arguments(AVCodecContext *avctx, D3D12_VIDEO_DECODE_INPU
     args->Size  = sizeof(DXVA_Tile_AV1) * ctx_pic->tile_count;
     args->pData = ctx_pic->tiles;
 
-    if (ctx_pic->bitstream_size > ctx->bitstream_size) {
+    ID3D12Resource_GetDesc(buffer, &desc);
+    if (ctx_pic->bitstream_size > desc.Width) {
         av_log(avctx, AV_LOG_ERROR, "Input frame bitstream size exceeds internal buffer!\n");
         return AVERROR(EINVAL);
     }
@@ -165,7 +166,8 @@ static int d3d12va_av1_end_frame(AVCodecContext *avctx)
         return -1;
 
     ret = ff_d3d12va_common_end_frame(avctx, h->cur_frame.f, &ctx_pic->pp, sizeof(ctx_pic->pp),
-                                      NULL, 0, update_input_arguments);
+                                      NULL, 0, ctx_pic->bitstream_size,
+                                      update_input_arguments);
 
     return ret;
 }
diff --git a/libavcodec/d3d12va_decode.c b/libavcodec/d3d12va_decode.c
index 538d9a4f6e..250108c243 100644
--- a/libavcodec/d3d12va_decode.c
+++ b/libavcodec/d3d12va_decode.c
@@ -27,7 +27,6 @@
 #include "libavutil/log.h"
 #include "libavutil/mem.h"
 #include "libavutil/time.h"
-#include "libavutil/imgutils.h"
 #include "libavutil/hwcontext_d3d12va_internal.h"
 #include "libavutil/hwcontext_d3d12va.h"
 #include "avcodec.h"
@@ -147,12 +146,6 @@ static void prepare_reference_only_resources(AVCodecContext *avctx)
     }
 }
 
-int ff_d3d12va_get_suitable_max_bitstream_size(AVCodecContext *avctx)
-{
-    AVHWFramesContext *frames_ctx = D3D12VA_FRAMES_CONTEXT(avctx);
-    return av_image_get_buffer_size(frames_ctx->sw_format, avctx->coded_width, avctx->coded_height, 1);
-}
-
 unsigned ff_d3d12va_get_surface_index(const AVCodecContext *avctx,
                                       D3D12VADecodeContext *ctx, const AVFrame *frame,
                                       int curr)
@@ -190,26 +183,57 @@ fail:
     return 0;
 }
 
+static int d3d12va_resize_bitstream_buffer(AVCodecContext *avctx, ID3D12Resource **ppBuffer,
+                                           UINT64 bitstream_size)
+{
+    HRESULT hr;
+    D3D12VADecodeContext *ctx = D3D12VA_DECODE_CONTEXT(avctx);
+    D3D12_HEAP_PROPERTIES heap_props = { .Type = D3D12_HEAP_TYPE_UPLOAD };
+    ID3D12Resource *buffer = NULL;
+    D3D12_RESOURCE_DESC desc;
+
+    if (!bitstream_size)
+        return 0;
+
+    if (*ppBuffer) {
+        ID3D12Resource_GetDesc(*ppBuffer, &desc);
+        if (desc.Width >= bitstream_size)
+            return 0;
+    } else {
+        desc = (D3D12_RESOURCE_DESC) {
+            .Dimension        = D3D12_RESOURCE_DIMENSION_BUFFER,
+            .Alignment        = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT,
+            .Height           = 1,
+            .DepthOrArraySize = 1,
+            .MipLevels        = 1,
+            .Format           = DXGI_FORMAT_UNKNOWN,
+            .SampleDesc       = { .Count = 1, .Quality = 0 },
+            .Layout           = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
+            .Flags            = D3D12_RESOURCE_FLAG_NONE,
+        };
+    }
+    desc.Width = bitstream_size * 1.5;
+
+    hr = ID3D12Device_CreateCommittedResource(ctx->device_ctx->device, &heap_props, D3D12_HEAP_FLAG_NONE,
+                                              &desc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL,
+                                              &IID_ID3D12Resource, (void **)&buffer);
+    if (FAILED(hr)) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to create a new D3D12 bitstream buffer for uploading!\n");
+        return AVERROR(EINVAL);
+    }
+
+    D3D12_OBJECT_RELEASE(*ppBuffer);
+    *ppBuffer = buffer;
+
+    return 0;
+}
+
 static int d3d12va_get_valid_helper_objects(AVCodecContext *avctx, ID3D12CommandAllocator **ppAllocator,
-                                            ID3D12Resource **ppBuffer)
+                                            ID3D12Resource **ppBuffer, UINT64 bitstream_size)
 {
     HRESULT hr;
     D3D12VADecodeContext *ctx = D3D12VA_DECODE_CONTEXT(avctx);
     HelperObjects obj = { 0 };
-    D3D12_HEAP_PROPERTIES heap_props = { .Type = D3D12_HEAP_TYPE_UPLOAD };
-
-    D3D12_RESOURCE_DESC desc = {
-        .Dimension        = D3D12_RESOURCE_DIMENSION_BUFFER,
-        .Alignment        = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT,
-        .Width            = ctx->bitstream_size,
-        .Height           = 1,
-        .DepthOrArraySize = 1,
-        .MipLevels        = 1,
-        .Format           = DXGI_FORMAT_UNKNOWN,
-        .SampleDesc       = { .Count = 1, .Quality = 0 },
-        .Layout           = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
-        .Flags            = D3D12_RESOURCE_FLAG_NONE,
-    };
 
     if (av_fifo_peek(ctx->objects_queue, &obj, 1, 0) >= 0) {
         uint64_t completion = ID3D12Fence_GetCompletedValue(ctx->sync_ctx.fence);
@@ -217,7 +241,7 @@ static int d3d12va_get_valid_helper_objects(AVCodecContext *avctx, ID3D12Command
             *ppAllocator = obj.command_allocator;
             *ppBuffer    = obj.buffer;
             av_fifo_read(ctx->objects_queue, &obj, 1);
-            return 0;
+            return d3d12va_resize_bitstream_buffer(avctx, ppBuffer, bitstream_size);
         }
     }
 
@@ -228,16 +252,7 @@ static int d3d12va_get_valid_helper_objects(AVCodecContext *avctx, ID3D12Command
         return AVERROR(EINVAL);
     }
 
-    hr = ID3D12Device_CreateCommittedResource(ctx->device_ctx->device, &heap_props, D3D12_HEAP_FLAG_NONE,
-                                              &desc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL,
-                                              &IID_ID3D12Resource, (void **)ppBuffer);
-
-    if (FAILED(hr)) {
-        av_log(avctx, AV_LOG_ERROR, "Failed to create a new d3d12 buffer!\n");
-        return AVERROR(EINVAL);
-    }
-
-    return 0;
+    return d3d12va_resize_bitstream_buffer(avctx, ppBuffer, bitstream_size);
 }
 
 static int d3d12va_discard_helper_objects(AVCodecContext *avctx, ID3D12CommandAllocator *pAllocator,
@@ -438,8 +453,6 @@ av_cold int ff_d3d12va_decode_init(AVCodecContext *avctx)
     if (ret < 0)
         goto fail;
 
-    ctx->bitstream_size = ff_d3d12va_get_suitable_max_bitstream_size(avctx);
-
     ctx->ref_resources = av_calloc(ctx->max_num_ref, sizeof(*ctx->ref_resources));
     if (!ctx->ref_resources)
         return AVERROR(ENOMEM);
@@ -460,7 +473,7 @@ av_cold int ff_d3d12va_decode_init(AVCodecContext *avctx)
     if (!ctx->sync_ctx.event)
         goto fail;
 
-    ret = d3d12va_get_valid_helper_objects(avctx, &command_allocator, &buffer);
+    ret = d3d12va_get_valid_helper_objects(avctx, &command_allocator, &buffer, 0);
     if (ret < 0)
         goto fail;
 
@@ -558,6 +571,7 @@ static inline int d3d12va_update_reference_frames_state(AVCodecContext *avctx, D
 int ff_d3d12va_common_end_frame(AVCodecContext *avctx, AVFrame *frame,
                               const void *pp, unsigned pp_size,
                               const void *qm, unsigned qm_size,
+                              UINT64 bitstream_size,
                               int(*update_input_arguments)(AVCodecContext *, D3D12_VIDEO_DECODE_INPUT_STREAM_ARGUMENTS *, ID3D12Resource *))
 {
     int ret;
@@ -648,7 +662,7 @@ int ff_d3d12va_common_end_frame(AVCodecContext *avctx, AVFrame *frame,
     if (!qm)
         input_args.NumFrameArguments = 1;
 
-    ret = d3d12va_get_valid_helper_objects(avctx, &command_allocator, &buffer);
+    ret = d3d12va_get_valid_helper_objects(avctx, &command_allocator, &buffer, bitstream_size);
     if (ret < 0)
         goto fail;
 
diff --git a/libavcodec/d3d12va_decode.h b/libavcodec/d3d12va_decode.h
index c771004222..c3b021b90d 100644
--- a/libavcodec/d3d12va_decode.h
+++ b/libavcodec/d3d12va_decode.h
@@ -95,11 +95,6 @@ typedef struct D3D12VADecodeContext {
      */
     UINT used_mask;
 
-    /**
-     * Bitstream size for each frame
-     */
-    UINT bitstream_size;
-
     /**
      * The sync context used to sync command queue
      */
@@ -141,16 +136,6 @@ typedef struct D3D12VADecodeContext {
 #define D3D12VA_DECODE_CONTEXT(avctx) ((D3D12VADecodeContext *)((avctx)->internal->hwaccel_priv_data))
 #define D3D12VA_FRAMES_CONTEXT(avctx) ((AVHWFramesContext *)(avctx)->hw_frames_ctx->data)
 
-/**
- * @brief Get a suitable maximum bitstream size
- *
- * Creating and destroying a resource on d3d12 needs sync and reallocation, so use this function
- * to help allocate a big enough bitstream buffer to avoid recreating resources when decoding.
- *
- * @return the suitable size
- */
-int ff_d3d12va_get_suitable_max_bitstream_size(AVCodecContext *avctx);
-
 /**
  * @brief init D3D12VADecodeContext
  *
@@ -187,6 +172,7 @@ int ff_d3d12va_common_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames
 int ff_d3d12va_common_end_frame(AVCodecContext *avctx, AVFrame *frame,
     const void *pp, unsigned pp_size,
     const void *qm, unsigned qm_size,
+    UINT64 bitstream_size,
     int(*)(AVCodecContext *, D3D12_VIDEO_DECODE_INPUT_STREAM_ARGUMENTS *, ID3D12Resource *));
 
 #endif /* AVCODEC_D3D12VA_DEC_H */
diff --git a/libavcodec/d3d12va_h264.c b/libavcodec/d3d12va_h264.c
index 5087e480f8..3cf1801809 100644
--- a/libavcodec/d3d12va_h264.c
+++ b/libavcodec/d3d12va_h264.c
@@ -105,7 +105,6 @@ static int d3d12va_h264_decode_slice(AVCodecContext *avctx, const uint8_t *buffe
 #define START_CODE_SIZE 3
 static int update_input_arguments(AVCodecContext *avctx, D3D12_VIDEO_DECODE_INPUT_STREAM_ARGUMENTS *input_args, ID3D12Resource *buffer)
 {
-    D3D12VADecodeContext     *ctx             = D3D12VA_DECODE_CONTEXT(avctx);
     const H264Context        *h               = avctx->priv_data;
     const H264Picture        *current_picture = h->cur_pic_ptr;
     H264DecodePictureContext *ctx_pic         = current_picture->hwaccel_picture_private;
@@ -114,7 +113,11 @@ static int update_input_arguments(AVCodecContext *avctx, D3D12_VIDEO_DECODE_INPU
     uint8_t *mapped_data, *mapped_ptr;
     DXVA_Slice_H264_Short *slice;
     D3D12_VIDEO_DECODE_FRAME_ARGUMENT *args;
-    UINT bitstream_size = ctx->bitstream_size;
+    D3D12_RESOURCE_DESC desc;
+    UINT64 bitstream_size;
+
+    ID3D12Resource_GetDesc(buffer, &desc);
+    bitstream_size = desc.Width;
 
     if (FAILED(ID3D12Resource_Map(buffer, 0, NULL, (void **)&mapped_data))) {
         av_log(avctx, AV_LOG_ERROR, "Failed to map D3D12 Buffer resource!\n");
@@ -170,13 +173,18 @@ static int d3d12va_h264_end_frame(AVCodecContext *avctx)
     H264SliceContext          *sl      = &h->slice_ctx[0];
 
     int ret;
+    uint64_t bitstream_size;
 
     if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0)
         return -1;
 
+    bitstream_size = ctx_pic->bitstream_size +
+                     (uint64_t)ctx_pic->slice_count * START_CODE_SIZE;
+
     ret = ff_d3d12va_common_end_frame(avctx, h->cur_pic_ptr->f,
                                       &ctx_pic->pp, sizeof(ctx_pic->pp),
                                       &ctx_pic->qm, sizeof(ctx_pic->qm),
+                                      bitstream_size,
                                       update_input_arguments);
     if (!ret)
         ff_h264_draw_horiz_band(h, sl, 0, h->avctx->height);
diff --git a/libavcodec/d3d12va_hevc.c b/libavcodec/d3d12va_hevc.c
index 1bf1faf9cb..adb0fed4d3 100644
--- a/libavcodec/d3d12va_hevc.c
+++ b/libavcodec/d3d12va_hevc.c
@@ -101,7 +101,6 @@ static int d3d12va_hevc_decode_slice(AVCodecContext *avctx, const uint8_t *buffe
 #define START_CODE_SIZE 3
 static int update_input_arguments(AVCodecContext *avctx, D3D12_VIDEO_DECODE_INPUT_STREAM_ARGUMENTS *input_args, ID3D12Resource *buffer)
 {
-    D3D12VADecodeContext     *ctx             = D3D12VA_DECODE_CONTEXT(avctx);
     const HEVCContext        *h               = avctx->priv_data;
     const HEVCFrame          *current_picture = h->cur_frame;
     HEVCDecodePictureContext *ctx_pic         = current_picture->hwaccel_picture_private;
@@ -110,7 +109,11 @@ static int update_input_arguments(AVCodecContext *avctx, D3D12_VIDEO_DECODE_INPU
     uint8_t *mapped_data, *mapped_ptr;
     DXVA_Slice_HEVC_Short *slice;
     D3D12_VIDEO_DECODE_FRAME_ARGUMENT *args;
-    UINT bitstream_size = ctx->bitstream_size;
+    D3D12_RESOURCE_DESC desc;
+    UINT64 bitstream_size;
+
+    ID3D12Resource_GetDesc(buffer, &desc);
+    bitstream_size = desc.Width;
 
     if (FAILED(ID3D12Resource_Map(buffer, 0, NULL, (void **)&mapped_data))) {
         av_log(avctx, AV_LOG_ERROR, "Failed to map D3D12 Buffer resource!\n");
@@ -165,12 +168,17 @@ static int d3d12va_hevc_end_frame(AVCodecContext *avctx)
     HEVCDecodePictureContext *ctx_pic = h->cur_frame->hwaccel_picture_private;
 
     int scale = ctx_pic->pp.dwCodingParamToolFlags & 1;
+    uint64_t bitstream_size;
 
     if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0)
         return -1;
 
+    bitstream_size = ctx_pic->bitstream_size +
+                     (uint64_t)ctx_pic->slice_count * START_CODE_SIZE;
+
     return ff_d3d12va_common_end_frame(avctx, h->cur_frame->f, &ctx_pic->pp, sizeof(ctx_pic->pp),
-               scale ? &ctx_pic->qm : NULL, scale ? sizeof(ctx_pic->qm) : 0, update_input_arguments);
+               scale ? &ctx_pic->qm : NULL, scale ? sizeof(ctx_pic->qm) : 0,
+               bitstream_size, update_input_arguments);
 }
 
 static av_cold int d3d12va_hevc_decode_init(AVCodecContext *avctx)
diff --git a/libavcodec/d3d12va_mpeg2.c b/libavcodec/d3d12va_mpeg2.c
index de9f0c71d1..2b057c2f31 100644
--- a/libavcodec/d3d12va_mpeg2.c
+++ b/libavcodec/d3d12va_mpeg2.c
@@ -90,7 +90,6 @@ static int d3d12va_mpeg2_decode_slice(AVCodecContext *avctx, const uint8_t *buff
 
 static int update_input_arguments(AVCodecContext *avctx, D3D12_VIDEO_DECODE_INPUT_STREAM_ARGUMENTS *input_args, ID3D12Resource *buffer)
 {
-    D3D12VADecodeContext      *ctx          = D3D12VA_DECODE_CONTEXT(avctx);
     const MpegEncContext      *s            = avctx->priv_data;
     D3D12DecodePictureContext *ctx_pic      = s->cur_pic.ptr->hwaccel_picture_private;
 
@@ -105,8 +104,10 @@ static int update_input_arguments(AVCodecContext *avctx, D3D12_VIDEO_DECODE_INPU
         .Begin = 0,
         .End = ctx_pic->bitstream_size,
     };
+    D3D12_RESOURCE_DESC desc;
 
-    if (ctx_pic->bitstream_size > ctx->bitstream_size) {
+    ID3D12Resource_GetDesc(buffer, &desc);
+    if (ctx_pic->bitstream_size > desc.Width) {
         av_log(avctx, AV_LOG_ERROR, "Input frame bitstream size exceeds internal buffer!\n");
         return AVERROR(EINVAL);
     }
@@ -152,7 +153,8 @@ static int d3d12va_mpeg2_end_frame(AVCodecContext *avctx)
         return -1;
 
     ret = ff_d3d12va_common_end_frame(avctx, s->cur_pic.ptr->f, &ctx_pic->pp, sizeof(ctx_pic->pp),
-                                      &ctx_pic->qm, sizeof(ctx_pic->qm), update_input_arguments);
+                                      &ctx_pic->qm, sizeof(ctx_pic->qm), ctx_pic->bitstream_size,
+                                      update_input_arguments);
     if (!ret)
         ff_mpeg_draw_horiz_band(s, 0, avctx->height);
 
diff --git a/libavcodec/d3d12va_vc1.c b/libavcodec/d3d12va_vc1.c
index 2386d2a29b..426338b8b9 100644
--- a/libavcodec/d3d12va_vc1.c
+++ b/libavcodec/d3d12va_vc1.c
@@ -41,6 +41,8 @@ typedef struct D3D12DecodePictureContext {
     unsigned               bitstream_size;
 } D3D12DecodePictureContext;
 
+static const uint8_t vc1_start_code[] = { 0, 0, 1, 0x0d };
+
 static int d3d12va_vc1_start_frame(AVCodecContext *avctx,
                                    av_unused const AVBufferRef *buffer_ref,
                                    av_unused const uint8_t *buffer,
@@ -94,7 +96,6 @@ static int d3d12va_vc1_decode_slice(AVCodecContext *avctx, const uint8_t *buffer
 
 static int update_input_arguments(AVCodecContext *avctx, D3D12_VIDEO_DECODE_INPUT_STREAM_ARGUMENTS *input_args, ID3D12Resource *buffer)
 {
-    D3D12VADecodeContext      *ctx          = D3D12VA_DECODE_CONTEXT(avctx);
     const VC1Context *v                     = avctx->priv_data;
     const MpegEncContext      *s            = &v->s;
     D3D12DecodePictureContext *ctx_pic      = s->cur_pic.ptr->hwaccel_picture_private;
@@ -102,9 +103,11 @@ static int update_input_arguments(AVCodecContext *avctx, D3D12_VIDEO_DECODE_INPU
 
     const unsigned mb_count = s->mb_width * (s->mb_height >> v->field_mode);
     uint8_t *mapped_data, *mapped_ptr;
-    UINT bitstream_size = ctx->bitstream_size;
+    D3D12_RESOURCE_DESC desc;
+    UINT64 bitstream_size;
 
-    static const uint8_t start_code[] = { 0, 0, 1, 0x0d };
+    ID3D12Resource_GetDesc(buffer, &desc);
+    bitstream_size = desc.Width;
 
     if (FAILED(ID3D12Resource_Map(buffer, 0, NULL, (void **)&mapped_data))) {
         av_log(avctx, AV_LOG_ERROR, "Failed to map D3D12 Buffer resource!\n");
@@ -117,7 +120,7 @@ static int update_input_arguments(AVCodecContext *avctx, D3D12_VIDEO_DECODE_INPU
         unsigned position     = slice->dwSliceDataLocation;
         unsigned size         = slice->dwSliceBitsInBuffer / 8;
 
-        if ((uint64_t)size + ((avctx->codec_id == AV_CODEC_ID_VC1) ? sizeof(start_code) : 0) > bitstream_size) {
+        if ((uint64_t)size + ((avctx->codec_id == AV_CODEC_ID_VC1) ? sizeof(vc1_start_code) : 0) > bitstream_size) {
             av_log(avctx, AV_LOG_ERROR, "Input frame bitstream size exceeds internal buffer!\n");
             ID3D12Resource_Unmap(buffer, 0, NULL);
             return AVERROR(EINVAL);
@@ -130,15 +133,15 @@ static int update_input_arguments(AVCodecContext *avctx, D3D12_VIDEO_DECODE_INPU
             slice->wNumberMBsInSlice = mb_count - slice[0].wNumberMBsInSlice;
 
         if (avctx->codec_id == AV_CODEC_ID_VC1) {
-            memcpy(mapped_ptr, start_code, sizeof(start_code));
+            memcpy(mapped_ptr, vc1_start_code, sizeof(vc1_start_code));
             if (i == 0 && v->second_field)
                 mapped_ptr[3] = 0x0c;
             else if (i > 0)
                 mapped_ptr[3] = 0x0b;
 
-            mapped_ptr += sizeof(start_code);
-            bitstream_size -= sizeof(start_code);
-            slice->dwSliceBitsInBuffer += sizeof(start_code) * 8;
+            mapped_ptr += sizeof(vc1_start_code);
+            bitstream_size -= sizeof(vc1_start_code);
+            slice->dwSliceBitsInBuffer += sizeof(vc1_start_code) * 8;
         }
 
         memcpy(mapped_ptr, &ctx_pic->bitstream[position], size);
@@ -172,6 +175,9 @@ static int d3d12va_vc1_end_frame(AVCodecContext *avctx)
     return ff_d3d12va_common_end_frame(avctx, v->s.cur_pic.ptr->f,
                                        &ctx_pic->pp, sizeof(ctx_pic->pp),
                                        NULL, 0,
+                                       ctx_pic->bitstream_size +
+                                       (avctx->codec_id == AV_CODEC_ID_VC1 ?
+                                        (uint64_t)ctx_pic->slice_count * sizeof(vc1_start_code) : 0),
                                        update_input_arguments);
 }
 
diff --git a/libavcodec/d3d12va_vp9.c b/libavcodec/d3d12va_vp9.c
index f224044279..f8e2327bfd 100644
--- a/libavcodec/d3d12va_vp9.c
+++ b/libavcodec/d3d12va_vp9.c
@@ -88,14 +88,15 @@ static int d3d12va_vp9_decode_slice(AVCodecContext *avctx, const uint8_t *buffer
 
 static int update_input_arguments(AVCodecContext *avctx, D3D12_VIDEO_DECODE_INPUT_STREAM_ARGUMENTS *input_args, ID3D12Resource *buffer)
 {
-    D3D12VADecodeContext    *ctx     = D3D12VA_DECODE_CONTEXT(avctx);
     const VP9SharedContext  *h       = avctx->priv_data;
     VP9DecodePictureContext *ctx_pic = h->frames[CUR_FRAME].hwaccel_picture_private;
 
     void *mapped_data;
     D3D12_VIDEO_DECODE_FRAME_ARGUMENT *args;
+    D3D12_RESOURCE_DESC desc;
 
-    if (ctx_pic->slice.SliceBytesInBuffer > ctx->bitstream_size) {
+    ID3D12Resource_GetDesc(buffer, &desc);
+    if (ctx_pic->slice.SliceBytesInBuffer > desc.Width) {
         av_log(avctx, AV_LOG_ERROR, "Input frame bitstream size exceeds internal buffer!\n");
         return AVERROR(EINVAL);
     }
@@ -132,7 +133,8 @@ static int d3d12va_vp9_end_frame(AVCodecContext *avctx)
         return -1;
 
     return ff_d3d12va_common_end_frame(avctx, h->frames[CUR_FRAME].tf.f,
-               &ctx_pic->pp, sizeof(ctx_pic->pp), NULL, 0, update_input_arguments);
+               &ctx_pic->pp, sizeof(ctx_pic->pp), NULL, 0, ctx_pic->bitstream_size,
+               update_input_arguments);
 }
 
 static av_cold int d3d12va_vp9_decode_init(AVCodecContext *avctx)
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.