FFmpeg
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
d3d12va_vc1.c
Go to the documentation of this file.
1 /*
2  * Direct3D12 WMV3/VC-1 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"
26 #include "mpegutils.h"
27 #include "mpegvideodec.h"
28 #include "vc1.h"
29 #include "vc1data.h"
30 #include "d3d12va_decode.h"
31 #include "dxva2_internal.h"
32 
33 #define MAX_SLICES 1024
34 #define INVALID_REF 0xffff
35 
36 typedef struct D3D12DecodePictureContext {
37  DXVA_PictureParameters pp;
38  unsigned slice_count;
39  DXVA_SliceInfo slices[MAX_SLICES];
40  const uint8_t *bitstream;
41  unsigned bitstream_size;
43 
45  av_unused const AVBufferRef *buffer_ref,
46  av_unused const uint8_t *buffer,
47  av_unused uint32_t size)
48 {
49  const VC1Context *v = avctx->priv_data;
52 
53  if (!ctx)
54  return -1;
55 
56  av_assert0(ctx_pic);
57 
58  ctx->used_mask = 0;
59 
61  ctx_pic->pp.wDeblockedPictureIndex = INVALID_REF;
62 
63  ctx_pic->bitstream = NULL;
64  ctx_pic->bitstream_size = 0;
65  ctx_pic->slice_count = 0;
66 
67  return 0;
68 }
69 
70 static int d3d12va_vc1_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
71 {
72  const VC1Context *v = avctx->priv_data;
74 
75  if (ctx_pic->slice_count >= MAX_SLICES) {
76  return AVERROR(ERANGE);
77  }
78 
79  if (avctx->codec_id == AV_CODEC_ID_VC1 &&
80  size >= 4 && IS_MARKER(AV_RB32(buffer))) {
81  buffer += 4;
82  size -= 4;
83  }
84 
85  if (!ctx_pic->bitstream)
86  ctx_pic->bitstream = buffer;
87  ctx_pic->bitstream_size += size;
88 
89  ff_dxva2_vc1_fill_slice(avctx, &ctx_pic->slices[ctx_pic->slice_count++],
90  buffer - ctx_pic->bitstream, size);
91 
92  return 0;
93 }
94 
95 static int update_input_arguments(AVCodecContext *avctx, D3D12_VIDEO_DECODE_INPUT_STREAM_ARGUMENTS *input_args, ID3D12Resource *buffer)
96 {
97  const VC1Context *v = avctx->priv_data;
98  const MpegEncContext *s = &v->s;
99  D3D12DecodePictureContext *ctx_pic = s->cur_pic.ptr->hwaccel_picture_private;
100  D3D12_VIDEO_DECODE_FRAME_ARGUMENT *args = &input_args->FrameArguments[input_args->NumFrameArguments++];
101 
102  const unsigned mb_count = s->mb_width * (s->mb_height >> v->field_mode);
103  uint8_t *mapped_data, *mapped_ptr;
104 
105  static const uint8_t start_code[] = { 0, 0, 1, 0x0d };
106 
107  if (FAILED(ID3D12Resource_Map(buffer, 0, NULL, (void **)&mapped_data))) {
108  av_log(avctx, AV_LOG_ERROR, "Failed to map D3D12 Buffer resource!\n");
109  return AVERROR(EINVAL);
110  }
111 
112  mapped_ptr = mapped_data;
113  for (int i = 0; i < ctx_pic->slice_count; i++) {
114  DXVA_SliceInfo *slice = &ctx_pic->slices[i];
115  unsigned position = slice->dwSliceDataLocation;
116  unsigned size = slice->dwSliceBitsInBuffer / 8;
117 
118  slice->dwSliceDataLocation = mapped_ptr - mapped_data;
119  if (i < ctx_pic->slice_count - 1)
120  slice->wNumberMBsInSlice = slice[1].wNumberMBsInSlice - slice[0].wNumberMBsInSlice;
121  else
122  slice->wNumberMBsInSlice = mb_count - slice[0].wNumberMBsInSlice;
123 
124  if (avctx->codec_id == AV_CODEC_ID_VC1) {
125  memcpy(mapped_ptr, start_code, sizeof(start_code));
126  if (i == 0 && v->second_field)
127  mapped_ptr[3] = 0x0c;
128  else if (i > 0)
129  mapped_ptr[3] = 0x0b;
130 
131  mapped_ptr += sizeof(start_code);
132  slice->dwSliceBitsInBuffer += sizeof(start_code) * 8;
133  }
134 
135  memcpy(mapped_ptr, &ctx_pic->bitstream[position], size);
136  mapped_ptr += size;
137  }
138 
139  ID3D12Resource_Unmap(buffer, 0, NULL);
140 
141  args->Type = D3D12_VIDEO_DECODE_ARGUMENT_TYPE_SLICE_CONTROL;
142  args->Size = sizeof(DXVA_SliceInfo) * ctx_pic->slice_count;
143  args->pData = ctx_pic->slices;
144 
145  input_args->CompressedBitstream = (D3D12_VIDEO_DECODE_COMPRESSED_BITSTREAM){
146  .pBuffer = buffer,
147  .Offset = 0,
148  .Size = mapped_ptr - mapped_data,
149  };
150 
151  return 0;
152 }
153 
155 {
156  const VC1Context *v = avctx->priv_data;
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, v->s.cur_pic.ptr->f,
163  &ctx_pic->pp, sizeof(ctx_pic->pp),
164  NULL, 0,
166 }
167 
169 {
170  int ret;
172  ctx->cfg.DecodeProfile = D3D12_VIDEO_DECODE_PROFILE_VC1_D2010;
173 
174  ctx->max_num_ref = 3;
175 
176  ret = ff_d3d12va_decode_init(avctx);
177  if (ret < 0) {
178  ctx->cfg.DecodeProfile = D3D12_VIDEO_DECODE_PROFILE_VC1;
179  ret = ff_d3d12va_decode_init(avctx);
180  }
181 
182  return ret;
183 }
184 
185 #if CONFIG_WMV3_D3D12VA_HWACCEL
187  .p.name = "wmv3_d3d12va",
188  .p.type = AVMEDIA_TYPE_VIDEO,
189  .p.id = AV_CODEC_ID_WMV3,
190  .p.pix_fmt = AV_PIX_FMT_D3D12,
191  .init = d3d12va_vc1_decode_init,
192  .uninit = ff_d3d12va_decode_uninit,
193  .start_frame = d3d12va_vc1_start_frame,
194  .decode_slice = d3d12va_vc1_decode_slice,
195  .end_frame = d3d12va_vc1_end_frame,
196  .frame_params = ff_d3d12va_common_frame_params,
197  .frame_priv_data_size = sizeof(D3D12DecodePictureContext),
198  .priv_data_size = sizeof(D3D12VADecodeContext),
199 };
200 #endif
201 
202 #if CONFIG_VC1_D3D12VA_HWACCEL
204  .p.name = "vc1_d3d12va",
205  .p.type = AVMEDIA_TYPE_VIDEO,
206  .p.id = AV_CODEC_ID_VC1,
207  .p.pix_fmt = AV_PIX_FMT_D3D12,
208  .init = d3d12va_vc1_decode_init,
209  .uninit = ff_d3d12va_decode_uninit,
210  .start_frame = d3d12va_vc1_start_frame,
211  .decode_slice = d3d12va_vc1_decode_slice,
212  .end_frame = d3d12va_vc1_end_frame,
213  .frame_params = ff_d3d12va_common_frame_params,
214  .frame_priv_data_size = sizeof(D3D12DecodePictureContext),
215  .priv_data_size = sizeof(D3D12VADecodeContext),
216 };
217 #endif
VC1Context
The VC1 Context.
Definition: vc1.h:173
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
vc1.h
d3d12va_vc1_decode_slice
static int d3d12va_vc1_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
Definition: d3d12va_vc1.c:70
D3D12DecodePictureContext::bitstream_size
unsigned bitstream_size
Definition: d3d12va_mpeg2.c:40
av_unused
#define av_unused
Definition: attributes.h:131
FFHWAccel::p
AVHWAccel p
The public AVHWAccel.
Definition: hwaccel_internal.h:38
start_code
static const uint8_t start_code[]
Definition: videotoolboxenc.c:230
D3D12DecodePictureContext
Definition: d3d12va_mpeg2.c:34
mpegutils.h
FFHWAccel
Definition: hwaccel_internal.h:34
avassert.h
mpegvideodec.h
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:209
av_cold
#define av_cold
Definition: attributes.h:90
ff_dxva2_vc1_fill_picture_parameters
void ff_dxva2_vc1_fill_picture_parameters(AVCodecContext *avctx, AVDXVAContext *ctx, DXVA_PictureParameters *pp)
Definition: dxva2_vc1.c:43
s
#define s(width, name)
Definition: cbs_vp9.c:198
MPVWorkPicture::ptr
MPVPicture * ptr
RefStruct reference.
Definition: mpegpicture.h:99
D3D12DecodePictureContext::slices
DXVA_SliceInfo slices[MAX_SLICES]
Definition: d3d12va_mpeg2.c:38
ff_wmv3_d3d12va_hwaccel
const struct FFHWAccel ff_wmv3_d3d12va_hwaccel
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:40
D3D12DecodePictureContext::pp
DXVA_PictureParameters pp
Definition: d3d12va_mpeg2.c:35
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
MpegEncContext::cur_pic
MPVWorkPicture cur_pic
copy of the current picture structure.
Definition: mpegvideo.h:177
AVCodecContext::codec_id
enum AVCodecID codec_id
Definition: avcodec.h:461
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_vc1.c:95
AV_CODEC_ID_WMV3
@ AV_CODEC_ID_WMV3
Definition: codec_id.h:123
NULL
#define NULL
Definition: coverity.c:32
VC1Context::field_mode
int field_mode
1 for interlaced field pictures
Definition: vc1.h:351
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
IS_MARKER
#define IS_MARKER(state)
Definition: dca_parser.c:51
AV_PIX_FMT_D3D12
@ AV_PIX_FMT_D3D12
Hardware surfaces for Direct3D 12.
Definition: pixfmt.h:440
d3d12va_vc1_start_frame
static int d3d12va_vc1_start_frame(AVCodecContext *avctx, av_unused const AVBufferRef *buffer_ref, av_unused const uint8_t *buffer, av_unused uint32_t size)
Definition: d3d12va_vc1.c:44
D3D12VA_DECODE_CONTEXT
#define D3D12VA_DECODE_CONTEXT(avctx)
Definition: d3d12va_decode.h:128
ff_vc1_d3d12va_hwaccel
const struct FFHWAccel ff_vc1_d3d12va_hwaccel
D3D12DecodePictureContext::slice_count
unsigned slice_count
Definition: d3d12va_mpeg2.c:37
ff_dxva2_vc1_fill_slice
void ff_dxva2_vc1_fill_slice(AVCodecContext *avctx, DXVA_SliceInfo *slice, unsigned position, unsigned size)
Definition: dxva2_vc1.c:167
size
int size
Definition: twinvq_data.h:10344
AV_RB32
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_RB32
Definition: bytestream.h:96
AVDXVAContext
Definition: dxva2_internal.h:74
vc1data.h
AVHWAccel::name
const char * name
Name of the hardware accelerated codec.
Definition: avcodec.h:2124
MPVPicture::hwaccel_picture_private
void * hwaccel_picture_private
RefStruct reference for hardware accelerator private data.
Definition: mpegpicture.h:75
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
ff_d3d12va_decode_init
av_cold int ff_d3d12va_decode_init(AVCodecContext *avctx)
init D3D12VADecodeContext
Definition: d3d12va_decode.c:283
d3d12va_vc1_decode_init
static av_cold int d3d12va_vc1_decode_init(AVCodecContext *avctx)
Definition: d3d12va_vc1.c:168
VC1Context::s
MpegEncContext s
Definition: vc1.h:174
AV_CODEC_ID_VC1
@ AV_CODEC_ID_VC1
Definition: codec_id.h:122
VC1Context::second_field
int second_field
Definition: vc1.h:353
ret
ret
Definition: filter_design.txt:187
MPVPicture::f
struct AVFrame * f
Definition: mpegpicture.h:59
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
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
D3D12VADecodeContext
This structure is used to provide the necessary configurations and data to the FFmpeg Direct3D 12 HWA...
Definition: d3d12va_decode.h:37
MAX_SLICES
#define MAX_SLICES
Definition: d3d12va_vc1.c:33
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_vc1_end_frame
static int d3d12va_vc1_end_frame(AVCodecContext *avctx)
Definition: d3d12va_vc1.c:154
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
INVALID_REF
#define INVALID_REF
Definition: d3d12va_vc1.c:34
hwcontext_d3d12va_internal.h
MpegEncContext
MpegEncContext.
Definition: mpegvideo.h:73
D3D12DecodePictureContext::bitstream
const uint8_t * bitstream
Definition: d3d12va_mpeg2.c:39
d3d12va_decode.h