[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]