comparison dxva2_h264.c @ 10952:ea8f891d997d libavcodec

H264 DXVA2 implementation It allows VLD H264 decoding using DXVA2 (GPU assisted decoding API under VISTA and Windows 7). It is implemented by using AVHWAccel API. It has been tested successfully for some time in VLC using an nvidia card on Windows 7. To compile it, you need to have the system header dxva2api.h (either from microsoft or using http://downloads.videolan.org/pub/videolan/testing/contrib/dxva2api.h) The generated libavcodec.dll does not depend directly on any new lib as the necessary objects are given by the application using FFmpeg.
author fenrir
date Wed, 20 Jan 2010 18:54:51 +0000
parents
children b1ccfdc1b409
comparison
equal deleted inserted replaced
10951:38b3b209b4bc 10952:ea8f891d997d
1 /*
2 * DXVA2 H264 HW acceleration.
3 *
4 * copyright (c) 2009 Laurent Aimar
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 "dxva2.h"
24 #include "avcodec.h"
25
26 #include "mpegvideo.h"
27 #include "h264.h"
28 #include "h264data.h"
29
30 struct dxva2_picture_context {
31 DXVA_PicParams_H264 pp;
32 DXVA_Qmatrix_H264 qm;
33 unsigned slice_count;
34 DXVA_Slice_H264_Short slice_short[MAX_SLICES];
35 DXVA_Slice_H264_Long slice_long[MAX_SLICES];
36 const uint8_t *bitstream;
37 unsigned bitstream_size;
38 };
39
40 static void *get_surface(const Picture *picture)
41 {
42 return picture->data[3];
43 }
44 static unsigned get_surface_index(const struct dxva_context *ctx,
45 const Picture *picture)
46 {
47 void *surface = get_surface(picture);
48 unsigned i;
49
50 for (i = 0; i < ctx->surface_count; i++)
51 if (ctx->surface[i] == surface)
52 return i;
53
54 assert(0);
55 return 0;
56 }
57
58 static void fill_picture_entry(DXVA_PicEntry_H264 *pic,
59 unsigned index, unsigned flag)
60 {
61 assert((index&0x7f) == index && (flag&0x01) == flag);
62 pic->bPicEntry = index | (flag << 7);
63 }
64
65 static void fill_picture_parameters(struct dxva_context *ctx, const H264Context *h,
66 DXVA_PicParams_H264 *pp)
67 {
68 const MpegEncContext *s = &h->s;
69 const Picture *current_picture = s->current_picture_ptr;
70 int i;
71
72 memset(pp, 0, sizeof(*pp));
73 /* Configure current picture */
74 fill_picture_entry(&pp->CurrPic,
75 get_surface_index(ctx, current_picture),
76 s->picture_structure == PICT_BOTTOM_FIELD);
77 /* Configure the set of references */
78 pp->UsedForReferenceFlags = 0;
79 pp->NonExistingFrameFlags = 0;
80 for (i = 0; i < FF_ARRAY_ELEMS(pp->RefFrameList); i++) {
81 if (i < h->short_ref_count + h->long_ref_count) {
82 const Picture *r;
83 if (i < h->short_ref_count) {
84 r = h->short_ref[i];
85 assert(!r->long_ref);
86 } else {
87 r = h->long_ref[i - h->short_ref_count];
88 assert(r->long_ref);
89 }
90 fill_picture_entry(&pp->RefFrameList[i],
91 get_surface_index(ctx, r),
92 r->long_ref != 0);
93
94 if ((r->reference & PICT_TOP_FIELD) && r->field_poc[0] != INT_MAX)
95 pp->FieldOrderCntList[i][0] = r->field_poc[0];
96 if ((r->reference & PICT_BOTTOM_FIELD) && r->field_poc[1] != INT_MAX)
97 pp->FieldOrderCntList[i][1] = r->field_poc[1];
98
99 pp->FrameNumList[i] = r->long_ref ? r->pic_id : r->frame_num;
100 if (r->reference & PICT_TOP_FIELD)
101 pp->UsedForReferenceFlags |= 1 << (2*i + 0);
102 if (r->reference & PICT_BOTTOM_FIELD)
103 pp->UsedForReferenceFlags |= 1 << (2*i + 1);
104 } else {
105 pp->RefFrameList[i].bPicEntry = 0xff;
106 pp->FieldOrderCntList[i][0] = 0;
107 pp->FieldOrderCntList[i][1] = 0;
108 pp->FrameNumList[i] = 0;
109 }
110 }
111
112 pp->wFrameWidthInMbsMinus1 = s->mb_width - 1;
113 pp->wFrameHeightInMbsMinus1 = s->mb_height - 1;
114 pp->num_ref_frames = h->sps.ref_frame_count;
115
116 pp->wBitFields = ((s->picture_structure != PICT_FRAME) << 0) |
117 (h->sps.mb_aff << 1) |
118 (h->sps.residual_color_transform_flag << 2) |
119 /* sp_for_switch_flag (not implemented by FFmpeg) */
120 (0 << 3) |
121 (h->sps.chroma_format_idc << 4) |
122 ((h->nal_ref_idc != 0) << 6) |
123 (h->pps.constrained_intra_pred << 7) |
124 (h->pps.weighted_pred << 8) |
125 (h->pps.weighted_bipred_idc << 9) |
126 /* MbsConsecutiveFlag */
127 (1 << 11) |
128 (h->sps.frame_mbs_only_flag << 12) |
129 (h->pps.transform_8x8_mode << 13) |
130 ((h->sps.level_idc >= 31) << 14) |
131 /* IntraPicFlag (Modified if we detect a non
132 * intra slice in decode_slice) */
133 (1 << 15);
134
135 pp->bit_depth_luma_minus8 = h->sps.bit_depth_luma - 8;
136 pp->bit_depth_chroma_minus8 = h->sps.bit_depth_chroma - 8;
137 pp->Reserved16Bits = 3; /* FIXME is there a way to detect the right mode ? */
138 pp->StatusReportFeedbackNumber = 1 + ctx->report_id++;
139 pp->CurrFieldOrderCnt[0] = 0;
140 if ((s->picture_structure & PICT_TOP_FIELD) &&
141 current_picture->field_poc[0] != INT_MAX)
142 pp->CurrFieldOrderCnt[0] = current_picture->field_poc[0];
143 pp->CurrFieldOrderCnt[1] = 0;
144 if ((s->picture_structure & PICT_BOTTOM_FIELD) &&
145 current_picture->field_poc[1] != INT_MAX)
146 pp->CurrFieldOrderCnt[1] = current_picture->field_poc[1];
147 pp->pic_init_qs_minus26 = h->pps.init_qs - 26;
148 pp->chroma_qp_index_offset = h->pps.chroma_qp_index_offset[0];
149 pp->second_chroma_qp_index_offset = h->pps.chroma_qp_index_offset[1];
150 pp->ContinuationFlag = 1;
151 pp->pic_init_qp_minus26 = h->pps.init_qp - 26;
152 pp->num_ref_idx_l0_active_minus1 = h->pps.ref_count[0] - 1;
153 pp->num_ref_idx_l1_active_minus1 = h->pps.ref_count[1] - 1;
154 pp->Reserved8BitsA = 0;
155 pp->frame_num = h->frame_num;
156 pp->log2_max_frame_num_minus4 = h->sps.log2_max_frame_num - 4;
157 pp->pic_order_cnt_type = h->sps.poc_type;
158 if (h->sps.poc_type == 0)
159 pp->log2_max_pic_order_cnt_lsb_minus4 = h->sps.log2_max_poc_lsb - 4;
160 else if (h->sps.poc_type == 1)
161 pp->delta_pic_order_always_zero_flag = h->sps.delta_pic_order_always_zero_flag;
162 pp->direct_8x8_inference_flag = h->sps.direct_8x8_inference_flag;
163 pp->entropy_coding_mode_flag = h->pps.cabac;
164 pp->pic_order_present_flag = h->pps.pic_order_present;
165 pp->num_slice_groups_minus1 = h->pps.slice_group_count - 1;
166 pp->slice_group_map_type = h->pps.mb_slice_group_map_type;
167 pp->deblocking_filter_control_present_flag = h->pps.deblocking_filter_parameters_present;
168 pp->redundant_pic_cnt_present_flag= h->pps.redundant_pic_cnt_present;
169 pp->Reserved8BitsB = 0;
170 pp->slice_group_change_rate_minus1= 0; /* XXX not implemented by FFmpeg */
171 //pp->SliceGroupMap[810]; /* XXX not implemented by FFmpeg */
172 }
173
174 static void fill_scaling_lists(const H264Context *h, DXVA_Qmatrix_H264 *qm)
175 {
176 unsigned i, j;
177 memset(qm, 0, sizeof(*qm));
178 for (i = 0; i < 6; i++)
179 for (j = 0; j < 16; j++)
180 qm->bScalingLists4x4[i][j] = h->pps.scaling_matrix4[i][zigzag_scan[j]];
181
182 for (i = 0; i < 2; i++)
183 for (j = 0; j < 64; j++)
184 qm->bScalingLists8x8[i][j] = h->pps.scaling_matrix8[i][ff_zigzag_direct[j]];
185 }
186
187 static int is_slice_short(struct dxva_context *ctx)
188 {
189 assert(ctx->cfg->ConfigBitstreamRaw == 1 ||
190 ctx->cfg->ConfigBitstreamRaw == 2);
191 return ctx->cfg->ConfigBitstreamRaw == 2;
192 }
193
194 static void fill_slice_short(DXVA_Slice_H264_Short *slice,
195 unsigned position, unsigned size)
196 {
197 memset(slice, 0, sizeof(*slice));
198 slice->BSNALunitDataLocation = position;
199 slice->SliceBytesInBuffer = size;
200 slice->wBadSliceChopping = 0;
201 }
202
203 static void fill_slice_long(AVCodecContext *avctx, DXVA_Slice_H264_Long *slice,
204 unsigned position, unsigned size)
205 {
206 H264Context *h = avctx->priv_data; /* FIXME Can't use const because of get_bits_count */
207 struct dxva_context *ctx = avctx->hwaccel_context;
208 MpegEncContext *s = &h->s;
209 unsigned list;
210
211 memset(slice, 0, sizeof(*slice));
212 slice->BSNALunitDataLocation = position;
213 slice->SliceBytesInBuffer = size;
214 slice->wBadSliceChopping = 0;
215
216 slice->first_mb_in_slice = (s->mb_y >> FIELD_OR_MBAFF_PICTURE) * s->mb_width + s->mb_x;
217 slice->NumMbsForSlice = 0; /* XXX it is set once we have all slices */
218 slice->BitOffsetToSliceData = get_bits_count(&s->gb) + 8;
219 slice->slice_type = ff_h264_get_slice_type(h);
220 if (h->slice_type_fixed)
221 slice->slice_type += 5;
222 slice->luma_log2_weight_denom = h->luma_log2_weight_denom;
223 slice->chroma_log2_weight_denom = h->chroma_log2_weight_denom;
224 if (h->list_count > 0)
225 slice->num_ref_idx_l0_active_minus1 = h->ref_count[0] - 1;
226 if (h->list_count > 1)
227 slice->num_ref_idx_l1_active_minus1 = h->ref_count[1] - 1;
228 slice->slice_alpha_c0_offset_div2 = h->slice_alpha_c0_offset / 2;
229 slice->slice_beta_offset_div2 = h->slice_beta_offset / 2;
230 slice->Reserved8Bits = 0;
231
232 for (list = 0; list < 2; list++) {
233 unsigned i;
234 for (i = 0; i < FF_ARRAY_ELEMS(slice->RefPicList[list]); i++) {
235 if (list < h->list_count && i < h->ref_count[list]) {
236 const Picture *r = &h->ref_list[list][i];
237 unsigned plane;
238 fill_picture_entry(&slice->RefPicList[list][i],
239 get_surface_index(ctx, r),
240 r->reference == PICT_BOTTOM_FIELD);
241 for (plane = 0; plane < 3; plane++) {
242 int w, o;
243 if (plane == 0 && h->luma_weight_flag[list]) {
244 w = h->luma_weight[list][i];
245 o = h->luma_offset[list][i];
246 } else if (plane >= 1 && h->chroma_weight_flag[list]) {
247 w = h->chroma_weight[list][i][plane-1];
248 o = h->chroma_offset[list][i][plane-1];
249 } else {
250 w = 1 << (plane == 0 ? h->luma_log2_weight_denom :
251 h->chroma_log2_weight_denom);
252 o = 0;
253 }
254 slice->Weights[list][i][plane][0] = w;
255 slice->Weights[list][i][plane][1] = o;
256 }
257 } else {
258 unsigned plane;
259 slice->RefPicList[list][i].bPicEntry = 0xff;
260 for (plane = 0; plane < 3; plane++) {
261 slice->Weights[list][i][plane][0] = 0;
262 slice->Weights[list][i][plane][1] = 0;
263 }
264 }
265 }
266 }
267 slice->slice_qs_delta = 0; /* XXX not implemented by FFmpeg */
268 slice->slice_qp_delta = s->qscale - h->pps.init_qp;
269 slice->redundant_pic_cnt = h->redundant_pic_count;
270 if (h->slice_type == FF_B_TYPE)
271 slice->direct_spatial_mv_pred_flag = h->direct_spatial_mv_pred;
272 slice->cabac_init_idc = h->pps.cabac ? h->cabac_init_idc : 0;
273 if (h->deblocking_filter < 2)
274 slice->disable_deblocking_filter_idc = 1 - h->deblocking_filter;
275 else
276 slice->disable_deblocking_filter_idc = h->deblocking_filter;
277 slice->slice_id = h->current_slice - 1;
278 }
279
280 static int commit_buffer(AVCodecContext *avctx,
281 struct dxva_context *ctx,
282 DXVA2_DecodeBufferDesc *dsc,
283 unsigned type, const void *data, unsigned size,
284 unsigned mb_count)
285 {
286 void *dxva_data;
287 unsigned dxva_size;
288 int result;
289
290 if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx->decoder, type,
291 &dxva_data, &dxva_size))) {
292 av_log(avctx, AV_LOG_ERROR, "Failed to get a buffer for %d\n", type);
293 return -1;
294 }
295 if (size <= dxva_size) {
296 memcpy(dxva_data, data, size);
297
298 memset(dsc, 0, sizeof(*dsc));
299 dsc->CompressedBufferType = type;
300 dsc->DataSize = size;
301 dsc->NumMBsInBuffer = mb_count;
302
303 result = 0;
304 } else {
305 av_log(avctx, AV_LOG_ERROR, "Buffer for type %d was too small\n", type);
306 result = -1;
307 }
308 if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(ctx->decoder, type))) {
309 av_log(avctx, AV_LOG_ERROR, "Failed to release buffer type %d\n", type);
310 result = -1;
311 }
312 return result;
313 }
314
315 static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx,
316 struct dxva_context *ctx,
317 struct dxva2_picture_context *ctx_pic,
318 DXVA2_DecodeBufferDesc *bs,
319 DXVA2_DecodeBufferDesc *sc,
320 unsigned mb_count)
321 {
322 DXVA_Slice_H264_Short *slice = NULL;
323 uint8_t *dxva_data, *current, *end;
324 unsigned dxva_size;
325 void *slice_data;
326 unsigned slice_size;
327 unsigned padding;
328 unsigned i;
329
330 /* Create an annex B bitstream buffer with only slice NAL and finalize slice */
331 if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx->decoder,
332 DXVA2_BitStreamDateBufferType,
333 &dxva_data, &dxva_size)))
334 return -1;
335 current = dxva_data;
336 end = dxva_data + dxva_size;
337
338 for (i = 0; i < ctx_pic->slice_count; i++) {
339 static const uint8_t start_code[] = { 0, 0, 1 };
340 static const unsigned start_code_size = sizeof(start_code);
341 unsigned position, size;
342
343 assert(offsetof(DXVA_Slice_H264_Short, BSNALunitDataLocation) ==
344 offsetof(DXVA_Slice_H264_Long, BSNALunitDataLocation));
345 assert(offsetof(DXVA_Slice_H264_Short, SliceBytesInBuffer) ==
346 offsetof(DXVA_Slice_H264_Long, SliceBytesInBuffer));
347
348 if (is_slice_short(ctx))
349 slice = &ctx_pic->slice_short[i];
350 else
351 slice = (DXVA_Slice_H264_Short*)&ctx_pic->slice_long[i];
352
353 position = slice->BSNALunitDataLocation;
354 size = slice->SliceBytesInBuffer;
355 if (start_code_size + size > end - current) {
356 av_log(avctx, AV_LOG_ERROR, "Failed to build bitstream");
357 break;
358 }
359
360 slice->BSNALunitDataLocation = current - dxva_data;
361 slice->SliceBytesInBuffer = start_code_size + size;
362
363 if (!is_slice_short(ctx)) {
364 DXVA_Slice_H264_Long *slice_long = (DXVA_Slice_H264_Long*)slice;
365 if (i < ctx_pic->slice_count - 1)
366 slice_long->NumMbsForSlice =
367 slice_long[1].first_mb_in_slice - slice_long[0].first_mb_in_slice;
368 else
369 slice_long->NumMbsForSlice = mb_count - slice_long->first_mb_in_slice;
370 }
371
372 memcpy(current, start_code, start_code_size);
373 current += start_code_size;
374
375 memcpy(current, &ctx_pic->bitstream[position], size);
376 current += size;
377 }
378 padding = FFMIN(128 - ((current - dxva_data) & 127), end - current);
379 if (slice && padding > 0) {
380 memset(current, 0, padding);
381 current += padding;
382
383 slice->SliceBytesInBuffer += padding;
384 }
385 if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(ctx->decoder,
386 DXVA2_BitStreamDateBufferType)))
387 return -1;
388 if (i < ctx_pic->slice_count)
389 return -1;
390
391 memset(bs, 0, sizeof(*bs));
392 bs->CompressedBufferType = DXVA2_BitStreamDateBufferType;
393 bs->DataSize = current - dxva_data;
394 bs->NumMBsInBuffer = mb_count;
395
396 if (is_slice_short(ctx)) {
397 slice_data = ctx_pic->slice_short;
398 slice_size = ctx_pic->slice_count * sizeof(*ctx_pic->slice_short);
399 } else {
400 slice_data = ctx_pic->slice_long;
401 slice_size = ctx_pic->slice_count * sizeof(*ctx_pic->slice_long);
402 }
403 assert((bs->DataSize & 127) == 0);
404 return commit_buffer(avctx, ctx, sc,
405 DXVA2_SliceControlBufferType,
406 slice_data, slice_size, mb_count);
407 }
408
409
410 static int start_frame(AVCodecContext *avctx,
411 av_unused const uint8_t *buffer,
412 av_unused uint32_t size)
413 {
414 const H264Context *h = avctx->priv_data;
415 struct dxva_context *ctx = avctx->hwaccel_context;
416 struct dxva2_picture_context *ctx_pic = h->s.current_picture_ptr->hwaccel_picture_private;
417
418 if (!ctx->decoder || !ctx->cfg || ctx->surface_count <= 0)
419 return -1;
420 assert(ctx_pic);
421
422 /* Fill up DXVA_PicParams_H264 */
423 fill_picture_parameters(ctx, h, &ctx_pic->pp);
424
425 /* Fill up DXVA_Qmatrix_H264 */
426 fill_scaling_lists(h, &ctx_pic->qm);
427
428 ctx_pic->slice_count = 0;
429 ctx_pic->bitstream_size = 0;
430 ctx_pic->bitstream = NULL;
431 return 0;
432 }
433
434 static int decode_slice(AVCodecContext *avctx,
435 const uint8_t *buffer, uint32_t size)
436 {
437 H264Context *h = avctx->priv_data; /* FIXME Can't use const because of get_bits_count */
438 struct dxva_context *ctx = avctx->hwaccel_context;
439 const Picture *current_picture = h->s.current_picture_ptr;
440 struct dxva2_picture_context *ctx_pic = current_picture->hwaccel_picture_private;
441 unsigned position;
442
443 if (ctx_pic->slice_count >= MAX_SLICES)
444 return -1;
445
446 if (!ctx_pic->bitstream)
447 ctx_pic->bitstream = buffer;
448 ctx_pic->bitstream_size += size;
449
450 position = buffer - ctx_pic->bitstream;
451 if (is_slice_short(ctx))
452 fill_slice_short(&ctx_pic->slice_short[ctx_pic->slice_count],
453 position, size);
454 else
455 fill_slice_long(avctx, &ctx_pic->slice_long[ctx_pic->slice_count],
456 position, size);
457 ctx_pic->slice_count++;
458
459 if (h->slice_type != FF_I_TYPE && h->slice_type != FF_SI_TYPE)
460 ctx_pic->pp.wBitFields &= ~(1 << 15); /* Set IntraPicFlag to 0 */
461 return 0;
462 }
463
464 static int end_frame(AVCodecContext *avctx)
465 {
466 H264Context *h = avctx->priv_data;
467 MpegEncContext *s = &h->s;
468 const unsigned mb_count = s->mb_width * s->mb_height;
469 struct dxva_context *ctx = avctx->hwaccel_context;
470 const Picture *current_picture = h->s.current_picture_ptr;
471 struct dxva2_picture_context *ctx_pic = current_picture->hwaccel_picture_private;
472 unsigned buffer_count = 0;
473 DXVA2_DecodeBufferDesc buffer[4];
474 DXVA2_DecodeExecuteParams exec;
475 int result;
476
477 if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0)
478 return -1;
479
480 if (FAILED(IDirectXVideoDecoder_BeginFrame(ctx->decoder,
481 get_surface(current_picture),
482 NULL))) {
483 av_log(avctx, AV_LOG_ERROR, "Failed to begin frame\n");
484 return -1;
485 }
486
487 result = commit_buffer(avctx, ctx, &buffer[buffer_count],
488 DXVA2_PictureParametersBufferType,
489 &ctx_pic->pp, sizeof(ctx_pic->pp), 0);
490 if (result) {
491 av_log(avctx, AV_LOG_ERROR,
492 "Failed to add picture parameter buffer\n");
493 goto end;
494 }
495 buffer_count++;
496
497 result = commit_buffer(avctx, ctx, &buffer[buffer_count],
498 DXVA2_InverseQuantizationMatrixBufferType,
499 &ctx_pic->qm, sizeof(ctx_pic->qm), 0);
500 if (result) {
501 av_log(avctx, AV_LOG_ERROR,
502 "Failed to add inverse quantization matrix buffer\n");
503 goto end;
504 }
505 buffer_count++;
506
507 result = commit_bitstream_and_slice_buffer(avctx, ctx, ctx_pic,
508 &buffer[buffer_count + 0],
509 &buffer[buffer_count + 1],
510 mb_count);
511 if (result) {
512 av_log(avctx, AV_LOG_ERROR,
513 "Failed to add bitstream or slice control buffer\n");
514 goto end;
515 }
516 buffer_count += 2;
517
518 /* TODO Film Grain when possible */
519
520 assert(buffer_count == 4);
521
522 memset(&exec, 0, sizeof(exec));
523 exec.NumCompBuffers = buffer_count;
524 exec.pCompressedBuffers = buffer;
525 exec.pExtensionData = NULL;
526 if (FAILED(IDirectXVideoDecoder_Execute(ctx->decoder, &exec))) {
527 av_log(avctx, AV_LOG_ERROR, "Failed to execute\n");
528 result = -1;
529 }
530
531 end:
532 if (FAILED(IDirectXVideoDecoder_EndFrame(ctx->decoder, NULL))) {
533 av_log(avctx, AV_LOG_ERROR, "Failed to end frame\n");
534 result = -1;
535 }
536
537 if (!result)
538 ff_draw_horiz_band(s, 0, s->avctx->height);
539 return result;
540 }
541
542 AVHWAccel h264_dxva2_hwaccel = {
543 .name = "h264_dxva2",
544 .type = CODEC_TYPE_VIDEO,
545 .id = CODEC_ID_H264,
546 .pix_fmt = PIX_FMT_DXVA2_VLD,
547 .capabilities = 0,
548 .start_frame = start_frame,
549 .decode_slice = decode_slice,
550 .end_frame = end_frame,
551 .priv_data_size = sizeof(struct dxva2_picture_context),
552 };
553