FFmpeg
dxva2_vp9.c
Go to the documentation of this file.
1 /*
2  * DXVA2 VP9 HW acceleration.
3  *
4  * copyright (c) 2015 Hendrik Leppkes
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 "libavutil/avassert.h"
24 #include "libavutil/pixdesc.h"
25 
26 #include "dxva2_internal.h"
27 #include "vp9shared.h"
28 
30  DXVA_PicParams_VP9 pp;
31  DXVA_Slice_VPx_Short slice;
32  const uint8_t *bitstream;
33  unsigned bitstream_size;
34 };
35 
36 static void fill_picture_entry(DXVA_PicEntry_VPx *pic,
37  unsigned index, unsigned flag)
38 {
39  av_assert0((index & 0x7f) == index && (flag & 0x01) == flag);
40  pic->bPicEntry = index | (flag << 7);
41 }
42 
44  DXVA_PicParams_VP9 *pp)
45 {
46  int i;
47  const AVPixFmtDescriptor * pixdesc = av_pix_fmt_desc_get(avctx->sw_pix_fmt);
48 
49  if (!pixdesc)
50  return -1;
51 
52  memset(pp, 0, sizeof(*pp));
53 
54  fill_picture_entry(&pp->CurrPic, ff_dxva2_get_surface_index(avctx, ctx, h->frames[CUR_FRAME].tf.f), 0);
55 
56  pp->profile = h->h.profile;
57  pp->wFormatAndPictureInfoFlags = ((h->h.keyframe == 0) << 0) |
58  ((h->h.invisible == 0) << 1) |
59  (h->h.errorres << 2) |
60  (pixdesc->log2_chroma_w << 3) | /* subsampling_x */
61  (pixdesc->log2_chroma_h << 4) | /* subsampling_y */
62  (0 << 5) | /* extra_plane */
63  (h->h.refreshctx << 6) |
64  (h->h.parallelmode << 7) |
65  (h->h.intraonly << 8) |
66  (h->h.framectxid << 9) |
67  (h->h.resetctx << 11) |
68  ((h->h.keyframe ? 0 : h->h.highprecisionmvs) << 13) |
69  (0 << 14); /* ReservedFormatInfo2Bits */
70 
71  pp->width = avctx->width;
72  pp->height = avctx->height;
73  pp->BitDepthMinus8Luma = pixdesc->comp[0].depth - 8;
74  pp->BitDepthMinus8Chroma = pixdesc->comp[1].depth - 8;
75  /* swap 0/1 to match the reference */
76  pp->interp_filter = h->h.filtermode ^ (h->h.filtermode <= 1);
77  pp->Reserved8Bits = 0;
78 
79  for (i = 0; i < 8; i++) {
80  if (h->refs[i].f->buf[0]) {
81  fill_picture_entry(&pp->ref_frame_map[i], ff_dxva2_get_surface_index(avctx, ctx, h->refs[i].f), 0);
82  pp->ref_frame_coded_width[i] = h->refs[i].f->width;
83  pp->ref_frame_coded_height[i] = h->refs[i].f->height;
84  } else
85  pp->ref_frame_map[i].bPicEntry = 0xFF;
86  }
87 
88  for (i = 0; i < 3; i++) {
89  uint8_t refidx = h->h.refidx[i];
90  if (h->refs[refidx].f->buf[0])
91  fill_picture_entry(&pp->frame_refs[i], ff_dxva2_get_surface_index(avctx, ctx, h->refs[refidx].f), 0);
92  else
93  pp->frame_refs[i].bPicEntry = 0xFF;
94 
95  pp->ref_frame_sign_bias[i + 1] = h->h.signbias[i];
96  }
97 
98  pp->filter_level = h->h.filter.level;
99  pp->sharpness_level = h->h.filter.sharpness;
100 
101  pp->wControlInfoFlags = (h->h.lf_delta.enabled << 0) |
102  (h->h.lf_delta.updated << 1) |
103  (h->h.use_last_frame_mvs << 2) |
104  (0 << 3); /* ReservedControlInfo5Bits */
105 
106  for (i = 0; i < 4; i++)
107  pp->ref_deltas[i] = h->h.lf_delta.ref[i];
108 
109  for (i = 0; i < 2; i++)
110  pp->mode_deltas[i] = h->h.lf_delta.mode[i];
111 
112  pp->base_qindex = h->h.yac_qi;
113  pp->y_dc_delta_q = h->h.ydc_qdelta;
114  pp->uv_dc_delta_q = h->h.uvdc_qdelta;
115  pp->uv_ac_delta_q = h->h.uvac_qdelta;
116 
117  /* segmentation data */
118  pp->stVP9Segments.wSegmentInfoFlags = (h->h.segmentation.enabled << 0) |
119  (h->h.segmentation.update_map << 1) |
120  (h->h.segmentation.temporal << 2) |
121  (h->h.segmentation.absolute_vals << 3) |
122  (0 << 4); /* ReservedSegmentFlags4Bits */
123 
124  for (i = 0; i < 7; i++)
125  pp->stVP9Segments.tree_probs[i] = h->h.segmentation.prob[i];
126 
127  if (h->h.segmentation.temporal)
128  for (i = 0; i < 3; i++)
129  pp->stVP9Segments.pred_probs[i] = h->h.segmentation.pred_prob[i];
130  else
131  memset(pp->stVP9Segments.pred_probs, 255, sizeof(pp->stVP9Segments.pred_probs));
132 
133  for (i = 0; i < 8; i++) {
134  pp->stVP9Segments.feature_mask[i] = (h->h.segmentation.feat[i].q_enabled << 0) |
135  (h->h.segmentation.feat[i].lf_enabled << 1) |
136  (h->h.segmentation.feat[i].ref_enabled << 2) |
137  (h->h.segmentation.feat[i].skip_enabled << 3);
138 
139  pp->stVP9Segments.feature_data[i][0] = h->h.segmentation.feat[i].q_val;
140  pp->stVP9Segments.feature_data[i][1] = h->h.segmentation.feat[i].lf_val;
141  pp->stVP9Segments.feature_data[i][2] = h->h.segmentation.feat[i].ref_val;
142  pp->stVP9Segments.feature_data[i][3] = 0; /* no data for skip */
143  }
144 
145  pp->log2_tile_cols = h->h.tiling.log2_tile_cols;
146  pp->log2_tile_rows = h->h.tiling.log2_tile_rows;
147 
148  pp->uncompressed_header_size_byte_aligned = h->h.uncompressed_header_size;
149  pp->first_partition_size = h->h.compressed_header_size;
150 
151  pp->StatusReportFeedbackNumber = 1 + DXVA_CONTEXT_REPORT_ID(avctx, ctx)++;
152  return 0;
153 }
154 
155 static void fill_slice_short(DXVA_Slice_VPx_Short *slice,
156  unsigned position, unsigned size)
157 {
158  memset(slice, 0, sizeof(*slice));
159  slice->BSNALunitDataLocation = position;
160  slice->SliceBytesInBuffer = size;
161  slice->wBadSliceChopping = 0;
162 }
163 
167 {
168  const VP9SharedContext *h = avctx->priv_data;
169  AVDXVAContext *ctx = DXVA_CONTEXT(avctx);
170  struct vp9_dxva2_picture_context *ctx_pic = h->frames[CUR_FRAME].hwaccel_picture_private;
171  void *dxva_data_ptr;
172  uint8_t *dxva_data;
173  unsigned dxva_size;
174  unsigned padding;
175  unsigned type;
176 
177 #if CONFIG_D3D11VA
178  if (ff_dxva2_is_d3d11(avctx)) {
179  type = D3D11_VIDEO_DECODER_BUFFER_BITSTREAM;
180  if (FAILED(ID3D11VideoContext_GetDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context,
182  type,
183  &dxva_size, &dxva_data_ptr)))
184  return -1;
185  }
186 #endif
187 #if CONFIG_DXVA2
188  if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
189  type = DXVA2_BitStreamDateBufferType;
190  if (FAILED(IDirectXVideoDecoder_GetBuffer(DXVA2_CONTEXT(ctx)->decoder,
191  type,
192  &dxva_data_ptr, &dxva_size)))
193  return -1;
194  }
195 #endif
196 
197  dxva_data = dxva_data_ptr;
198 
199  if (ctx_pic->slice.SliceBytesInBuffer > dxva_size) {
200  av_log(avctx, AV_LOG_ERROR, "Failed to build bitstream");
201  return -1;
202  }
203 
204  memcpy(dxva_data, ctx_pic->bitstream, ctx_pic->slice.SliceBytesInBuffer);
205 
206  padding = FFMIN(128 - ((ctx_pic->slice.SliceBytesInBuffer) & 127), dxva_size - ctx_pic->slice.SliceBytesInBuffer);
207  if (padding > 0) {
208  memset(dxva_data + ctx_pic->slice.SliceBytesInBuffer, 0, padding);
209  ctx_pic->slice.SliceBytesInBuffer += padding;
210  }
211 
212 #if CONFIG_D3D11VA
213  if (ff_dxva2_is_d3d11(avctx))
214  if (FAILED(ID3D11VideoContext_ReleaseDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, type)))
215  return -1;
216 #endif
217 #if CONFIG_DXVA2
218  if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD)
219  if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(DXVA2_CONTEXT(ctx)->decoder, type)))
220  return -1;
221 #endif
222 
223 #if CONFIG_D3D11VA
224  if (ff_dxva2_is_d3d11(avctx)) {
225  D3D11_VIDEO_DECODER_BUFFER_DESC *dsc11 = bs;
226  memset(dsc11, 0, sizeof(*dsc11));
227  dsc11->BufferType = type;
228  dsc11->DataSize = ctx_pic->slice.SliceBytesInBuffer;
229  dsc11->NumMBsInBuffer = 0;
230 
231  type = D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL;
232  }
233 #endif
234 #if CONFIG_DXVA2
235  if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
236  DXVA2_DecodeBufferDesc *dsc2 = bs;
237  memset(dsc2, 0, sizeof(*dsc2));
238  dsc2->CompressedBufferType = type;
239  dsc2->DataSize = ctx_pic->slice.SliceBytesInBuffer;
240  dsc2->NumMBsInBuffer = 0;
241 
242  type = DXVA2_SliceControlBufferType;
243  }
244 #endif
245 
246  return ff_dxva2_commit_buffer(avctx, ctx, sc,
247  type,
248  &ctx_pic->slice, sizeof(ctx_pic->slice), 0);
249 }
250 
251 
253  av_unused const uint8_t *buffer,
254  av_unused uint32_t size)
255 {
256  const VP9SharedContext *h = avctx->priv_data;
257  AVDXVAContext *ctx = DXVA_CONTEXT(avctx);
258  struct vp9_dxva2_picture_context *ctx_pic = h->frames[CUR_FRAME].hwaccel_picture_private;
259 
260  if (!DXVA_CONTEXT_VALID(avctx, ctx))
261  return -1;
262  av_assert0(ctx_pic);
263 
264  /* Fill up DXVA_PicParams_VP9 */
265  if (fill_picture_parameters(avctx, ctx, h, &ctx_pic->pp) < 0)
266  return -1;
267 
268  ctx_pic->bitstream_size = 0;
269  ctx_pic->bitstream = NULL;
270  return 0;
271 }
272 
274  const uint8_t *buffer,
275  uint32_t size)
276 {
277  const VP9SharedContext *h = avctx->priv_data;
278  struct vp9_dxva2_picture_context *ctx_pic = h->frames[CUR_FRAME].hwaccel_picture_private;
279  unsigned position;
280 
281  if (!ctx_pic->bitstream)
282  ctx_pic->bitstream = buffer;
283  ctx_pic->bitstream_size += size;
284 
285  position = buffer - ctx_pic->bitstream;
286  fill_slice_short(&ctx_pic->slice, position, size);
287 
288  return 0;
289 }
290 
292 {
293  VP9SharedContext *h = avctx->priv_data;
294  struct vp9_dxva2_picture_context *ctx_pic = h->frames[CUR_FRAME].hwaccel_picture_private;
295  int ret;
296 
297  if (ctx_pic->bitstream_size <= 0)
298  return -1;
299 
300  ret = ff_dxva2_common_end_frame(avctx, h->frames[CUR_FRAME].tf.f,
301  &ctx_pic->pp, sizeof(ctx_pic->pp),
302  NULL, 0,
304  return ret;
305 }
306 
307 #if CONFIG_VP9_DXVA2_HWACCEL
309  .name = "vp9_dxva2",
310  .type = AVMEDIA_TYPE_VIDEO,
311  .id = AV_CODEC_ID_VP9,
312  .pix_fmt = AV_PIX_FMT_DXVA2_VLD,
313  .init = ff_dxva2_decode_init,
314  .uninit = ff_dxva2_decode_uninit,
315  .start_frame = dxva2_vp9_start_frame,
316  .decode_slice = dxva2_vp9_decode_slice,
317  .end_frame = dxva2_vp9_end_frame,
318  .frame_params = ff_dxva2_common_frame_params,
319  .frame_priv_data_size = sizeof(struct vp9_dxva2_picture_context),
320  .priv_data_size = sizeof(FFDXVASharedContext),
321 };
322 #endif
323 
324 #if CONFIG_VP9_D3D11VA_HWACCEL
326  .name = "vp9_d3d11va",
327  .type = AVMEDIA_TYPE_VIDEO,
328  .id = AV_CODEC_ID_VP9,
329  .pix_fmt = AV_PIX_FMT_D3D11VA_VLD,
330  .init = ff_dxva2_decode_init,
331  .uninit = ff_dxva2_decode_uninit,
332  .start_frame = dxva2_vp9_start_frame,
333  .decode_slice = dxva2_vp9_decode_slice,
334  .end_frame = dxva2_vp9_end_frame,
335  .frame_params = ff_dxva2_common_frame_params,
336  .frame_priv_data_size = sizeof(struct vp9_dxva2_picture_context),
337  .priv_data_size = sizeof(FFDXVASharedContext),
338 };
339 #endif
340 
341 #if CONFIG_VP9_D3D11VA2_HWACCEL
343  .name = "vp9_d3d11va2",
344  .type = AVMEDIA_TYPE_VIDEO,
345  .id = AV_CODEC_ID_VP9,
346  .pix_fmt = AV_PIX_FMT_D3D11,
347  .init = ff_dxva2_decode_init,
348  .uninit = ff_dxva2_decode_uninit,
349  .start_frame = dxva2_vp9_start_frame,
350  .decode_slice = dxva2_vp9_decode_slice,
351  .end_frame = dxva2_vp9_end_frame,
352  .frame_params = ff_dxva2_common_frame_params,
353  .frame_priv_data_size = sizeof(struct vp9_dxva2_picture_context),
354  .priv_data_size = sizeof(FFDXVASharedContext),
355 };
356 #endif
fill_picture_entry
static void fill_picture_entry(DXVA_PicEntry_VPx *pic, unsigned index, unsigned flag)
Definition: dxva2_vp9.c:36
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2660
av_unused
#define av_unused
Definition: attributes.h:131
pixdesc.h
index
fg index
Definition: ffmpeg_filter.c:167
AVComponentDescriptor::depth
int depth
Number of bits in the component.
Definition: pixdesc.h:57
ff_dxva2_common_end_frame
int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame, const void *pp, unsigned pp_size, const void *qm, unsigned qm_size, int(*commit_bs_si)(AVCodecContext *, DECODER_BUFFER_DESC *bs, DECODER_BUFFER_DESC *slice))
Definition: dxva2.c:886
AV_PIX_FMT_D3D11VA_VLD
@ AV_PIX_FMT_D3D11VA_VLD
HW decoding through Direct3D11 via old API, Picture.data[3] contains a ID3D11VideoDecoderOutputView p...
Definition: pixfmt.h:219
AVHWAccel
Definition: avcodec.h:2039
decoder
static const chunk_decoder decoder[8]
Definition: dfa.c:330
commit_bitstream_and_slice_buffer
static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, DECODER_BUFFER_DESC *bs, DECODER_BUFFER_DESC *sc)
Definition: dxva2_vp9.c:164
type
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
Definition: writing_filters.txt:86
vp9shared.h
avassert.h
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
DXVA2_CONTEXT
#define DXVA2_CONTEXT(ctx)
Definition: dxva2_internal.h:102
AV_PIX_FMT_DXVA2_VLD
@ AV_PIX_FMT_DXVA2_VLD
HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer.
Definition: pixfmt.h:127
VP9SharedContext
Definition: vp9shared.h:159
AV_CODEC_ID_VP9
@ AV_CODEC_ID_VP9
Definition: codec_id.h:218
ff_vp9_dxva2_hwaccel
const AVHWAccel ff_vp9_dxva2_hwaccel
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
DXVA_CONTEXT
#define DXVA_CONTEXT(avctx)
Definition: dxva2_internal.h:99
ctx
AVFormatContext * ctx
Definition: movenc.c:48
AVPixFmtDescriptor::log2_chroma_w
uint8_t log2_chroma_w
Amount to shift the luma width right to find the chroma width.
Definition: pixdesc.h:80
vp9_dxva2_picture_context::bitstream
const uint8_t * bitstream
Definition: dxva2_vp9.c:32
dxva2_internal.h
if
if(ret)
Definition: filter_design.txt:179
ff_vp9_d3d11va2_hwaccel
const AVHWAccel ff_vp9_d3d11va2_hwaccel
NULL
#define NULL
Definition: coverity.c:32
ff_dxva2_decode_init
int ff_dxva2_decode_init(AVCodecContext *avctx)
Definition: dxva2.c:655
vp9_dxva2_picture_context::pp
DXVA_PicParams_VP9 pp
Definition: dxva2_vp9.c:30
FFDXVASharedContext
Definition: dxva2_internal.h:67
dxva2_vp9_start_frame
static int dxva2_vp9_start_frame(AVCodecContext *avctx, av_unused const uint8_t *buffer, av_unused uint32_t size)
Definition: dxva2_vp9.c:252
for
for(j=16;j >0;--j)
Definition: h264pred_template.c:469
ff_vp9_d3d11va_hwaccel
const AVHWAccel ff_vp9_d3d11va_hwaccel
fill_picture_parameters
static int fill_picture_parameters(const AVCodecContext *avctx, AVDXVAContext *ctx, const VP9SharedContext *h, DXVA_PicParams_VP9 *pp)
Definition: dxva2_vp9.c:43
dxva2_vp9_decode_slice
static int dxva2_vp9_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
Definition: dxva2_vp9.c:273
size
int size
Definition: twinvq_data.h:10344
AVDXVAContext
Definition: dxva2_internal.h:58
DECODER_BUFFER_DESC
void DECODER_BUFFER_DESC
Definition: dxva2_internal.h:56
AV_PIX_FMT_D3D11
@ AV_PIX_FMT_D3D11
Hardware surfaces for Direct3D11.
Definition: pixfmt.h:303
AVHWAccel::name
const char * name
Name of the hardware accelerated codec.
Definition: avcodec.h:2045
flag
#define flag(name)
Definition: cbs_av1.c:553
D3D11VA_CONTEXT
#define D3D11VA_CONTEXT(ctx)
Definition: dxva2_internal.h:101
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:271
vp9_dxva2_picture_context::slice
DXVA_Slice_VPx_Short slice
Definition: dxva2_vp9.c:31
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
vp9_dxva2_picture_context::bitstream_size
unsigned bitstream_size
Definition: dxva2_vp9.c:33
ff_dxva2_commit_buffer
int ff_dxva2_commit_buffer(AVCodecContext *avctx, AVDXVAContext *ctx, DECODER_BUFFER_DESC *dsc, unsigned type, const void *data, unsigned size, unsigned mb_count)
Definition: dxva2.c:797
vp9_dxva2_picture_context
Definition: dxva2_vp9.c:29
AVCodecContext::height
int height
Definition: avcodec.h:556
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:593
ff_dxva2_get_surface_index
unsigned ff_dxva2_get_surface_index(const AVCodecContext *avctx, const AVDXVAContext *ctx, const AVFrame *frame)
Definition: dxva2.c:770
ff_dxva2_common_frame_params
int ff_dxva2_common_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx)
Definition: dxva2.c:592
fill_slice_short
static void fill_slice_short(DXVA_Slice_VPx_Short *slice, unsigned position, unsigned size)
Definition: dxva2_vp9.c:155
ret
ret
Definition: filter_design.txt:187
AVCodecContext
main external API structure.
Definition: avcodec.h:383
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
ff_dxva2_is_d3d11
int ff_dxva2_is_d3d11(const AVCodecContext *avctx)
Definition: dxva2.c:1051
AVPixFmtDescriptor::comp
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
Definition: pixdesc.h:105
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
ff_dxva2_decode_uninit
int ff_dxva2_decode_uninit(AVCodecContext *avctx)
Definition: dxva2.c:730
CUR_FRAME
#define CUR_FRAME
Definition: vp9shared.h:163
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:69
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:410
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:556
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
h
h
Definition: vp9dsp_template.c:2038
AVCodecContext::sw_pix_fmt
enum AVPixelFormat sw_pix_fmt
Nominal unaccelerated pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:1717
AVPixFmtDescriptor::log2_chroma_h
uint8_t log2_chroma_h
Amount to shift the luma height right to find the chroma height.
Definition: pixdesc.h:89
dxva2_vp9_end_frame
static int dxva2_vp9_end_frame(AVCodecContext *avctx)
Definition: dxva2_vp9.c:291