FFmpeg
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
d3d12va_hevc.c
Go to the documentation of this file.
1 /*
2  * Direct3D 12 HEVC HW acceleration
3  *
4  * copyright (c) 2022-2023 Wu Jianhua <toqsxw@outlook.com>
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 #include "config_components.h"
24 
25 #include "libavutil/avassert.h"
27 #include "hevc/data.h"
28 #include "hevc/hevcdec.h"
29 #include "dxva2_internal.h"
30 #include "d3d12va_decode.h"
31 #include <dxva.h>
32 
33 #define MAX_SLICES 256
34 
35 typedef struct HEVCDecodePictureContext {
36  DXVA_PicParams_HEVC pp;
37  DXVA_Qmatrix_HEVC qm;
38  unsigned slice_count;
39  DXVA_Slice_HEVC_Short slice_short[MAX_SLICES];
40  const uint8_t *bitstream;
41  unsigned bitstream_size;
43 
44 static void fill_slice_short(DXVA_Slice_HEVC_Short *slice, unsigned position, unsigned size)
45 {
46  memset(slice, 0, sizeof(*slice));
47  slice->BSNALunitDataLocation = position;
48  slice->SliceBytesInBuffer = size;
49  slice->wBadSliceChopping = 0;
50 }
51 
53  av_unused const AVBufferRef *buffer_ref,
54  av_unused const uint8_t *buffer,
55  av_unused uint32_t size)
56 {
57  const HEVCContext *h = avctx->priv_data;
59  HEVCDecodePictureContext *ctx_pic = h->cur_frame->hwaccel_picture_private;
60 
61  if (!ctx)
62  return -1;
63 
64  av_assert0(ctx_pic);
65 
66  ctx->used_mask = 0;
67 
69 
71 
72  ctx_pic->slice_count = 0;
73  ctx_pic->bitstream_size = 0;
74  ctx_pic->bitstream = NULL;
75 
76  return 0;
77 }
78 
79 static int d3d12va_hevc_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
80 {
81  const HEVCContext *h = avctx->priv_data;
82  const HEVCFrame *current_picture = h->cur_frame;
83  HEVCDecodePictureContext *ctx_pic = current_picture->hwaccel_picture_private;
84  unsigned position;
85 
86  if (ctx_pic->slice_count >= MAX_SLICES)
87  return AVERROR(ERANGE);
88 
89  if (!ctx_pic->bitstream)
90  ctx_pic->bitstream = buffer;
91  ctx_pic->bitstream_size += size;
92 
93  position = buffer - ctx_pic->bitstream;
94  fill_slice_short(&ctx_pic->slice_short[ctx_pic->slice_count], position, size);
95  ctx_pic->slice_count++;
96 
97  return 0;
98 }
99 
100 #define START_CODE 65536
101 #define START_CODE_SIZE 3
102 static int update_input_arguments(AVCodecContext *avctx, D3D12_VIDEO_DECODE_INPUT_STREAM_ARGUMENTS *input_args, ID3D12Resource *buffer)
103 {
104  const HEVCContext *h = avctx->priv_data;
105  const HEVCFrame *current_picture = h->cur_frame;
106  HEVCDecodePictureContext *ctx_pic = current_picture->hwaccel_picture_private;
107 
108  int i;
109  uint8_t *mapped_data, *mapped_ptr;
110  DXVA_Slice_HEVC_Short *slice;
111  D3D12_VIDEO_DECODE_FRAME_ARGUMENT *args;
112 
113  if (FAILED(ID3D12Resource_Map(buffer, 0, NULL, (void **)&mapped_data))) {
114  av_log(avctx, AV_LOG_ERROR, "Failed to map D3D12 Buffer resource!\n");
115  return AVERROR(EINVAL);
116  }
117 
118  mapped_ptr = mapped_data;
119  for (i = 0; i < ctx_pic->slice_count; i++) {
120  UINT position, size;
121  slice = &ctx_pic->slice_short[i];
122 
123  position = slice->BSNALunitDataLocation;
124  size = slice->SliceBytesInBuffer;
125 
126  slice->SliceBytesInBuffer += START_CODE_SIZE;
127  slice->BSNALunitDataLocation = mapped_ptr - mapped_data;
128 
129  *(uint32_t *)mapped_ptr = START_CODE;
130  mapped_ptr += START_CODE_SIZE;
131 
132  memcpy(mapped_ptr, &ctx_pic->bitstream[position], size);
133  mapped_ptr += size;
134  }
135 
136  ID3D12Resource_Unmap(buffer, 0, NULL);
137 
138  input_args->CompressedBitstream = (D3D12_VIDEO_DECODE_COMPRESSED_BITSTREAM){
139  .pBuffer = buffer,
140  .Offset = 0,
141  .Size = mapped_ptr - mapped_data,
142  };
143 
144  args = &input_args->FrameArguments[input_args->NumFrameArguments++];
145  args->Type = D3D12_VIDEO_DECODE_ARGUMENT_TYPE_SLICE_CONTROL;
146  args->Size = sizeof(DXVA_Slice_HEVC_Short) * ctx_pic->slice_count;
147  args->pData = ctx_pic->slice_short;
148 
149  return 0;
150 }
151 
153 {
154  HEVCContext *h = avctx->priv_data;
155  HEVCDecodePictureContext *ctx_pic = h->cur_frame->hwaccel_picture_private;
156 
157  int scale = ctx_pic->pp.dwCodingParamToolFlags & 1;
158 
159  if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0)
160  return -1;
161 
162  return ff_d3d12va_common_end_frame(avctx, h->cur_frame->f, &ctx_pic->pp, sizeof(ctx_pic->pp),
163  scale ? &ctx_pic->qm : NULL, scale ? sizeof(ctx_pic->qm) : 0, update_input_arguments);
164 }
165 
167 {
169  DXVA_PicParams_HEVC pp;
170 
171  switch (avctx->profile) {
173  ctx->cfg.DecodeProfile = D3D12_VIDEO_DECODE_PROFILE_HEVC_MAIN10;
174  break;
175 
178  ctx->cfg.DecodeProfile = D3D12_VIDEO_DECODE_PROFILE_HEVC_MAIN;
179  break;
180  } else {
181  av_log(avctx, AV_LOG_ERROR, "D3D12 doesn't support PROFILE_HEVC_MAIN_STILL_PICTURE!\n");
182  return AVERROR(EINVAL);
183  }
184 
186  default:
187  ctx->cfg.DecodeProfile = D3D12_VIDEO_DECODE_PROFILE_HEVC_MAIN;
188  break;
189  };
190 
191  ctx->max_num_ref = FF_ARRAY_ELEMS(pp.RefPicList) + 1;
192 
193  return ff_d3d12va_decode_init(avctx);
194 }
195 
196 #if CONFIG_HEVC_D3D12VA_HWACCEL
198  .p.name = "hevc_d3d12va",
199  .p.type = AVMEDIA_TYPE_VIDEO,
200  .p.id = AV_CODEC_ID_HEVC,
201  .p.pix_fmt = AV_PIX_FMT_D3D12,
202  .init = d3d12va_hevc_decode_init,
203  .uninit = ff_d3d12va_decode_uninit,
204  .start_frame = d3d12va_hevc_start_frame,
205  .decode_slice = d3d12va_hevc_decode_slice,
206  .end_frame = d3d12va_hevc_end_frame,
207  .frame_params = ff_d3d12va_common_frame_params,
208  .frame_priv_data_size = sizeof(HEVCDecodePictureContext),
209  .priv_data_size = sizeof(D3D12VADecodeContext),
210 };
211 #endif
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
HEVCDecodePictureContext::bitstream
const uint8_t * bitstream
Definition: d3d12va_hevc.c:40
ff_dxva2_hevc_fill_picture_parameters
void ff_dxva2_hevc_fill_picture_parameters(const AVCodecContext *avctx, AVDXVAContext *ctx, DXVA_PicParams_HEVC *pp)
Definition: dxva2_hevc.c:60
d3d12va_hevc_decode_slice
static int d3d12va_hevc_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
Definition: d3d12va_hevc.c:79
d3d12va_hevc_decode_init
static av_cold int d3d12va_hevc_decode_init(AVCodecContext *avctx)
Definition: d3d12va_hevc.c:166
av_unused
#define av_unused
Definition: attributes.h:131
AV_PROFILE_HEVC_MAIN
#define AV_PROFILE_HEVC_MAIN
Definition: defs.h:159
FFHWAccel::p
AVHWAccel p
The public AVHWAccel.
Definition: hwaccel_internal.h:38
HEVCFrame::hwaccel_picture_private
void * hwaccel_picture_private
RefStruct reference.
Definition: hevcdec.h:381
FFHWAccel
Definition: hwaccel_internal.h:34
MAX_SLICES
#define MAX_SLICES
Definition: d3d12va_hevc.c:33
avassert.h
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:209
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
av_cold
#define av_cold
Definition: attributes.h:90
ff_hevc_d3d12va_hwaccel
const struct FFHWAccel ff_hevc_d3d12va_hwaccel
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:40
HEVCDecodePictureContext::slice_count
unsigned slice_count
Definition: d3d12va_hevc.c:38
ctx
AVFormatContext * ctx
Definition: movenc.c:49
ff_d3d12va_common_frame_params
int ff_d3d12va_common_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx)
d3d12va common frame params
Definition: d3d12va_decode.c:271
dxva2_internal.h
update_input_arguments
static int update_input_arguments(AVCodecContext *avctx, D3D12_VIDEO_DECODE_INPUT_STREAM_ARGUMENTS *input_args, ID3D12Resource *buffer)
Definition: d3d12va_hevc.c:102
NULL
#define NULL
Definition: coverity.c:32
AV_PROFILE_HEVC_MAIN_STILL_PICTURE
#define AV_PROFILE_HEVC_MAIN_STILL_PICTURE
Definition: defs.h:161
AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH
#define AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH
Hardware acceleration should still be attempted for decoding when the codec profile does not match th...
Definition: avcodec.h:2188
ff_d3d12va_common_end_frame
int ff_d3d12va_common_end_frame(AVCodecContext *avctx, AVFrame *frame, const void *pp, unsigned pp_size, const void *qm, unsigned qm_size, int(*update_input_arguments)(AVCodecContext *, D3D12_VIDEO_DECODE_INPUT_STREAM_ARGUMENTS *, ID3D12Resource *))
d3d12va common end frame
Definition: d3d12va_decode.c:434
AV_PIX_FMT_D3D12
@ AV_PIX_FMT_D3D12
Hardware surfaces for Direct3D 12.
Definition: pixfmt.h:440
data.h
ff_dxva2_hevc_fill_scaling_lists
void ff_dxva2_hevc_fill_scaling_lists(const AVCodecContext *avctx, AVDXVAContext *ctx, DXVA_Qmatrix_HEVC *qm)
Definition: dxva2_hevc.c:205
D3D12VA_DECODE_CONTEXT
#define D3D12VA_DECODE_CONTEXT(avctx)
Definition: d3d12va_decode.h:128
AV_PROFILE_HEVC_MAIN_10
#define AV_PROFILE_HEVC_MAIN_10
Definition: defs.h:160
hevcdec.h
size
int size
Definition: twinvq_data.h:10344
AVDXVAContext
Definition: dxva2_internal.h:74
HEVCDecodePictureContext::pp
DXVA_PicParams_HEVC pp
Definition: d3d12va_hevc.c:36
START_CODE
#define START_CODE
Definition: d3d12va_hevc.c:100
AVHWAccel::name
const char * name
Name of the hardware accelerated codec.
Definition: avcodec.h:2124
fill_slice_short
static void fill_slice_short(DXVA_Slice_HEVC_Short *slice, unsigned position, unsigned size)
Definition: d3d12va_hevc.c:44
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
HEVCFrame
Definition: hevcdec.h:362
ff_d3d12va_decode_init
av_cold int ff_d3d12va_decode_init(AVCodecContext *avctx)
init D3D12VADecodeContext
Definition: d3d12va_decode.c:283
AVCodecContext::hwaccel_flags
int hwaccel_flags
Bit set of AV_HWACCEL_FLAG_* flags, which affect hardware accelerated decoding (if active).
Definition: avcodec.h:1524
AV_CODEC_ID_HEVC
@ AV_CODEC_ID_HEVC
Definition: codec_id.h:228
HEVCDecodePictureContext::qm
DXVA_Qmatrix_HEVC qm
Definition: d3d12va_hevc.c:37
START_CODE_SIZE
#define START_CODE_SIZE
Definition: d3d12va_hevc.c:101
AVCodecContext
main external API structure.
Definition: avcodec.h:451
buffer
the frame and frame reference mechanism is intended to as much as expensive copies of that data while still allowing the filters to produce correct results The data is stored in buffers represented by AVFrame structures Several references can point to the same frame buffer
Definition: filter_design.txt:49
HEVCContext
Definition: hevcdec.h:492
AVCodecContext::profile
int profile
profile
Definition: avcodec.h:1658
d3d12va_hevc_start_frame
static int d3d12va_hevc_start_frame(AVCodecContext *avctx, av_unused const AVBufferRef *buffer_ref, av_unused const uint8_t *buffer, av_unused uint32_t size)
Definition: d3d12va_hevc.c:52
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
HEVCDecodePictureContext::slice_short
DXVA_Slice_HEVC_Short slice_short[MAX_SLICES]
Definition: d3d12va_hevc.c:39
scale
static void scale(int *out, const int *in, const int w, const int h, const int shift)
Definition: intra.c:291
D3D12VADecodeContext
This structure is used to provide the necessary configurations and data to the FFmpeg Direct3D 12 HWA...
Definition: d3d12va_decode.h:37
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:478
ff_d3d12va_decode_uninit
av_cold int ff_d3d12va_decode_uninit(AVCodecContext *avctx)
uninit D3D12VADecodeContext
Definition: d3d12va_decode.c:373
d3d12va_hevc_end_frame
static int d3d12va_hevc_end_frame(AVCodecContext *avctx)
Definition: d3d12va_hevc.c:152
HEVCDecodePictureContext::bitstream_size
unsigned bitstream_size
Definition: d3d12va_hevc.c:41
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
h
h
Definition: vp9dsp_template.c:2070
HEVCDecodePictureContext
Definition: d3d12va_hevc.c:35
hwcontext_d3d12va_internal.h
d3d12va_decode.h