FFmpeg
d3d12va_h264.c
Go to the documentation of this file.
1 /*
2  * Direct3D 12 h264 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 #include "libavutil/avassert.h"
25 #include "h264dec.h"
26 #include "h264data.h"
27 #include "h264_ps.h"
28 #include "mpegutils.h"
29 #include "dxva2_internal.h"
30 #include "d3d12va_decode.h"
32 #include <dxva.h>
33 
34 typedef struct H264DecodePictureContext {
35  DXVA_PicParams_H264 pp;
36  DXVA_Qmatrix_H264 qm;
37  unsigned slice_count;
38  DXVA_Slice_H264_Short slice_short[MAX_SLICES];
39  const uint8_t *bitstream;
40  unsigned bitstream_size;
42 
43 static void fill_slice_short(DXVA_Slice_H264_Short *slice,
44  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 uint8_t *buffer,
54  av_unused uint32_t size)
55 {
56  const H264Context *h = avctx->priv_data;
57  H264DecodePictureContext *ctx_pic = h->cur_pic_ptr->hwaccel_picture_private;
59 
60  if (!ctx)
61  return -1;
62 
63  av_assert0(ctx_pic);
64 
65  ctx->used_mask = 0;
66 
68 
70 
71  ctx_pic->slice_count = 0;
72  ctx_pic->bitstream_size = 0;
73  ctx_pic->bitstream = NULL;
74 
75  return 0;
76 }
77 
78 static int d3d12va_h264_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
79 {
80  unsigned position;
81  const H264Context *h = avctx->priv_data;
82  const H264SliceContext *sl = &h->slice_ctx[0];
83  const H264Picture *current_picture = h->cur_pic_ptr;
84  H264DecodePictureContext *ctx_pic = current_picture->hwaccel_picture_private;
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 
98  ctx_pic->pp.wBitFields &= ~(1 << 15); /* Set IntraPicFlag to 0 */
99 
100  return 0;
101 }
102 
103 #define START_CODE 65536
104 #define START_CODE_SIZE 3
105 static int update_input_arguments(AVCodecContext *avctx, D3D12_VIDEO_DECODE_INPUT_STREAM_ARGUMENTS *input_args, ID3D12Resource *buffer)
106 {
107  const H264Context *h = avctx->priv_data;
108  const H264Picture *current_picture = h->cur_pic_ptr;
109  H264DecodePictureContext *ctx_pic = current_picture->hwaccel_picture_private;
110 
111  int i;
112  uint8_t *mapped_data, *mapped_ptr;
113  DXVA_Slice_H264_Short *slice;
114  D3D12_VIDEO_DECODE_FRAME_ARGUMENT *args;
115 
116  if (FAILED(ID3D12Resource_Map(buffer, 0, NULL, (void **)&mapped_data))) {
117  av_log(avctx, AV_LOG_ERROR, "Failed to map D3D12 Buffer resource!\n");
118  return AVERROR(EINVAL);
119  }
120 
121  mapped_ptr = mapped_data;
122  for (i = 0; i < ctx_pic->slice_count; i++) {
123  UINT position, size;
124  slice = &ctx_pic->slice_short[i];
125 
126  position = slice->BSNALunitDataLocation;
127  size = slice->SliceBytesInBuffer;
128 
129  slice->SliceBytesInBuffer += START_CODE_SIZE;
130  slice->BSNALunitDataLocation = mapped_ptr - mapped_data;
131 
132  *(uint32_t *)mapped_ptr = START_CODE;
133  mapped_ptr += START_CODE_SIZE;
134 
135  memcpy(mapped_ptr, &ctx_pic->bitstream[position], size);
136  mapped_ptr += size;
137  }
138 
139  ID3D12Resource_Unmap(buffer, 0, NULL);
140 
141  input_args->CompressedBitstream = (D3D12_VIDEO_DECODE_COMPRESSED_BITSTREAM){
142  .pBuffer = buffer,
143  .Offset = 0,
144  .Size = mapped_ptr - mapped_data,
145  };
146 
147  args = &input_args->FrameArguments[input_args->NumFrameArguments++];
148  args->Type = D3D12_VIDEO_DECODE_ARGUMENT_TYPE_SLICE_CONTROL;
149  args->Size = sizeof(DXVA_Slice_H264_Short) * ctx_pic->slice_count;
150  args->pData = ctx_pic->slice_short;
151 
152  return 0;
153 }
154 
156 {
157  H264Context *h = avctx->priv_data;
158  H264DecodePictureContext *ctx_pic = h->cur_pic_ptr->hwaccel_picture_private;
159  H264SliceContext *sl = &h->slice_ctx[0];
160 
161  int ret;
162 
163  if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0)
164  return -1;
165 
166  ret = ff_d3d12va_common_end_frame(avctx, h->cur_pic_ptr->f,
167  &ctx_pic->pp, sizeof(ctx_pic->pp),
168  &ctx_pic->qm, sizeof(ctx_pic->qm),
170  if (!ret)
171  ff_h264_draw_horiz_band(h, sl, 0, h->avctx->height);
172 
173  return ret;
174 }
175 
177 {
179  DXVA_PicParams_H264 pp;
180 
181  ctx->cfg.DecodeProfile = D3D12_VIDEO_DECODE_PROFILE_H264;
182 
183  ctx->max_num_ref = FF_ARRAY_ELEMS(pp.RefFrameList) + 1;
184 
185  return ff_d3d12va_decode_init(avctx);
186 }
187 
188 #if CONFIG_H264_D3D12VA_HWACCEL
190  .p.name = "h264_d3d12va",
191  .p.type = AVMEDIA_TYPE_VIDEO,
192  .p.id = AV_CODEC_ID_H264,
193  .p.pix_fmt = AV_PIX_FMT_D3D12,
194  .init = d3d12va_h264_decode_init,
195  .uninit = ff_d3d12va_decode_uninit,
196  .start_frame = d3d12va_h264_start_frame,
197  .decode_slice = d3d12va_h264_decode_slice,
198  .end_frame = d3d12va_h264_end_frame,
199  .frame_params = ff_d3d12va_common_frame_params,
200  .frame_priv_data_size = sizeof(H264DecodePictureContext),
201  .priv_data_size = sizeof(D3D12VADecodeContext),
202 };
203 #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
av_unused
#define av_unused
Definition: attributes.h:131
FFHWAccel::p
AVHWAccel p
The public AVHWAccel.
Definition: hwaccel_internal.h:38
ff_dxva2_h264_fill_scaling_lists
void ff_dxva2_h264_fill_scaling_lists(const AVCodecContext *avctx, AVDXVAContext *ctx, DXVA_Qmatrix_H264 *qm)
Definition: dxva2_h264.c:168
ff_d3d12va_decode_uninit
int ff_d3d12va_decode_uninit(AVCodecContext *avctx)
uninit D3D12VADecodeContext
Definition: d3d12va_decode.c:373
mpegutils.h
d3d12va_h264_decode_init
static int d3d12va_h264_decode_init(AVCodecContext *avctx)
Definition: d3d12va_h264.c:176
H264SliceContext
Definition: h264dec.h:172
FFHWAccel
Definition: hwaccel_internal.h:34
d3d12va_h264_end_frame
static int d3d12va_h264_end_frame(AVCodecContext *avctx)
Definition: d3d12va_h264.c:155
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:180
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:40
h264data.h
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
H264SliceContext::slice_type
int slice_type
Definition: h264dec.h:178
AV_CODEC_ID_H264
@ AV_CODEC_ID_H264
Definition: codec_id.h:79
ff_h264_draw_horiz_band
void ff_h264_draw_horiz_band(const H264Context *h, H264SliceContext *sl, int y, int height)
Definition: h264dec.c:103
dxva2_internal.h
fill_slice_short
static void fill_slice_short(DXVA_Slice_H264_Short *slice, unsigned position, unsigned size)
Definition: d3d12va_h264.c:43
NULL
#define NULL
Definition: coverity.c:32
AV_PICTURE_TYPE_SI
@ AV_PICTURE_TYPE_SI
Switching Intra.
Definition: avutil.h:283
AV_PICTURE_TYPE_I
@ AV_PICTURE_TYPE_I
Intra.
Definition: avutil.h:279
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
D3D12VA_DECODE_CONTEXT
#define D3D12VA_DECODE_CONTEXT(avctx)
Definition: d3d12va_decode.h:128
h264_ps.h
START_CODE_SIZE
#define START_CODE_SIZE
Definition: d3d12va_h264.c:104
size
int size
Definition: twinvq_data.h:10344
d3d12va_h264_start_frame
static int d3d12va_h264_start_frame(AVCodecContext *avctx, av_unused const uint8_t *buffer, av_unused uint32_t size)
Definition: d3d12va_h264.c:52
AVDXVAContext
Definition: dxva2_internal.h:74
ff_h264_d3d12va_hwaccel
const struct FFHWAccel ff_h264_d3d12va_hwaccel
ff_dxva2_h264_fill_picture_parameters
void ff_dxva2_h264_fill_picture_parameters(const AVCodecContext *avctx, AVDXVAContext *ctx, DXVA_PicParams_H264 *pp)
Definition: dxva2_h264.c:51
AVHWAccel::name
const char * name
Name of the hardware accelerated codec.
Definition: avcodec.h:2094
h264dec.h
H264DecodePictureContext::bitstream_size
unsigned bitstream_size
Definition: d3d12va_h264.c:40
H264Context
H264Context.
Definition: h264dec.h:332
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
H264DecodePictureContext::slice_count
unsigned slice_count
Definition: d3d12va_h264.c:37
H264DecodePictureContext::slice_short
DXVA_Slice_H264_Short slice_short[MAX_SLICES]
Definition: d3d12va_h264.c:38
d3d12va_h264_decode_slice
static int d3d12va_h264_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
Definition: d3d12va_h264.c:78
ret
ret
Definition: filter_design.txt:187
AVCodecContext
main external API structure.
Definition: avcodec.h:445
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
H264Picture
Definition: h264dec.h:106
H264DecodePictureContext::qm
DXVA_Qmatrix_H264 qm
Definition: d3d12va_h264.c:36
H264DecodePictureContext::bitstream
const uint8_t * bitstream
Definition: d3d12va_h264.c:39
START_CODE
#define START_CODE
Definition: d3d12va_h264.c:103
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
H264Picture::hwaccel_picture_private
void * hwaccel_picture_private
RefStruct reference for hardware accelerator private data.
Definition: h264dec.h:122
D3D12VADecodeContext
This structure is used to provide the necessary configurations and data to the FFmpeg Direct3D 12 HWA...
Definition: d3d12va_decode.h:37
update_input_arguments
static int update_input_arguments(AVCodecContext *avctx, D3D12_VIDEO_DECODE_INPUT_STREAM_ARGUMENTS *input_args, ID3D12Resource *buffer)
Definition: d3d12va_h264.c:105
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:472
H264DecodePictureContext::pp
DXVA_PicParams_H264 pp
Definition: d3d12va_h264.c:35
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
h
h
Definition: vp9dsp_template.c:2038
hwcontext_d3d12va_internal.h
H264DecodePictureContext
Definition: d3d12va_h264.c:34
ff_d3d12va_decode_init
int ff_d3d12va_decode_init(AVCodecContext *avctx)
init D3D12VADecodeContext
Definition: d3d12va_decode.c:283
d3d12va_decode.h