1/*
2 * DXVA2 H.264 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 "config_components.h"
24
25#include "libavutil/avassert.h"
26
27#include "dxva2_internal.h"
28#include "h264dec.h"
29#include "h264data.h"
30#include "h264_ps.h"
31#include "mpegutils.h"
32
33struct dxva2_picture_context {
34    DXVA_PicParams_H264   pp;
35    DXVA_Qmatrix_H264     qm;
36    unsigned              slice_count;
37    DXVA_Slice_H264_Short slice_short[MAX_SLICES];
38    DXVA_Slice_H264_Long  slice_long[MAX_SLICES];
39    const uint8_t         *bitstream;
40    unsigned              bitstream_size;
41};
42
43static void fill_picture_entry(DXVA_PicEntry_H264 *pic,
44                               unsigned index, unsigned flag)
45{
46    assert((index&0x7f) == index && (flag&0x01) == flag);
47    pic->bPicEntry = index | (flag << 7);
48}
49
50static void fill_picture_parameters(const AVCodecContext *avctx, AVDXVAContext *ctx, const H264Context *h,
51                                    DXVA_PicParams_H264 *pp)
52{
53    const H264Picture *current_picture = h->cur_pic_ptr;
54    const SPS *sps = h->ps.sps;
55    const PPS *pps = h->ps.pps;
56    int i, j;
57
58    memset(pp, 0, sizeof(*pp));
59    /* Configure current picture */
60    fill_picture_entry(&pp->CurrPic,
61                       ff_dxva2_get_surface_index(avctx, ctx, current_picture->f),
62                       h->picture_structure == PICT_BOTTOM_FIELD);
63    /* Configure the set of references */
64    pp->UsedForReferenceFlags  = 0;
65    pp->NonExistingFrameFlags  = 0;
66    for (i = 0, j = 0; i < FF_ARRAY_ELEMS(pp->RefFrameList); i++) {
67        const H264Picture *r;
68        if (j < h->short_ref_count) {
69            r = h->short_ref[j++];
70        } else {
71            r = NULL;
72            while (!r && j < h->short_ref_count + 16)
73                r = h->long_ref[j++ - h->short_ref_count];
74        }
75        if (r) {
76            fill_picture_entry(&pp->RefFrameList[i],
77                               ff_dxva2_get_surface_index(avctx, ctx, r->f),
78                               r->long_ref != 0);
79
80            if ((r->reference & PICT_TOP_FIELD) && r->field_poc[0] != INT_MAX)
81                pp->FieldOrderCntList[i][0] = r->field_poc[0];
82            if ((r->reference & PICT_BOTTOM_FIELD) && r->field_poc[1] != INT_MAX)
83                pp->FieldOrderCntList[i][1] = r->field_poc[1];
84
85            pp->FrameNumList[i] = r->long_ref ? r->pic_id : r->frame_num;
86            if (r->reference & PICT_TOP_FIELD)
87                pp->UsedForReferenceFlags |= 1 << (2*i + 0);
88            if (r->reference & PICT_BOTTOM_FIELD)
89                pp->UsedForReferenceFlags |= 1 << (2*i + 1);
90        } else {
91            pp->RefFrameList[i].bPicEntry = 0xff;
92            pp->FieldOrderCntList[i][0]   = 0;
93            pp->FieldOrderCntList[i][1]   = 0;
94            pp->FrameNumList[i]           = 0;
95        }
96    }
97
98    pp->wFrameWidthInMbsMinus1        = h->mb_width  - 1;
99    pp->wFrameHeightInMbsMinus1       = h->mb_height - 1;
100    pp->num_ref_frames                = sps->ref_frame_count;
101
102    pp->wBitFields                    = ((h->picture_structure != PICT_FRAME) <<  0) |
103                                        ((sps->mb_aff &&
104                                        (h->picture_structure == PICT_FRAME)) <<  1) |
105                                        (sps->residual_color_transform_flag   <<  2) |
106                                        /* sp_for_switch_flag (not implemented by FFmpeg) */
107                                        (0                                    <<  3) |
108                                        (sps->chroma_format_idc               <<  4) |
109                                        ((h->nal_ref_idc != 0)                <<  6) |
110                                        (pps->constrained_intra_pred          <<  7) |
111                                        (pps->weighted_pred                   <<  8) |
112                                        (pps->weighted_bipred_idc             <<  9) |
113                                        /* MbsConsecutiveFlag */
114                                        (1                                    << 11) |
115                                        (sps->frame_mbs_only_flag             << 12) |
116                                        (pps->transform_8x8_mode              << 13) |
117                                        ((sps->level_idc >= 31)               << 14) |
118                                        /* IntraPicFlag (Modified if we detect a non
119                                         * intra slice in dxva2_h264_decode_slice) */
120                                        (1                                    << 15);
121
122    pp->bit_depth_luma_minus8         = sps->bit_depth_luma - 8;
123    pp->bit_depth_chroma_minus8       = sps->bit_depth_chroma - 8;
124    if (DXVA_CONTEXT_WORKAROUND(avctx, ctx) & FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG)
125        pp->Reserved16Bits            = 0;
126    else if (DXVA_CONTEXT_WORKAROUND(avctx, ctx) & FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO)
127        pp->Reserved16Bits            = 0x34c;
128    else
129        pp->Reserved16Bits            = 3; /* FIXME is there a way to detect the right mode ? */
130    pp->StatusReportFeedbackNumber    = 1 + DXVA_CONTEXT_REPORT_ID(avctx, ctx)++;
131    pp->CurrFieldOrderCnt[0] = 0;
132    if ((h->picture_structure & PICT_TOP_FIELD) &&
133        current_picture->field_poc[0] != INT_MAX)
134        pp->CurrFieldOrderCnt[0] = current_picture->field_poc[0];
135    pp->CurrFieldOrderCnt[1] = 0;
136    if ((h->picture_structure & PICT_BOTTOM_FIELD) &&
137        current_picture->field_poc[1] != INT_MAX)
138        pp->CurrFieldOrderCnt[1] = current_picture->field_poc[1];
139    pp->pic_init_qs_minus26           = pps->init_qs - 26;
140    pp->chroma_qp_index_offset        = pps->chroma_qp_index_offset[0];
141    pp->second_chroma_qp_index_offset = pps->chroma_qp_index_offset[1];
142    pp->ContinuationFlag              = 1;
143    pp->pic_init_qp_minus26           = pps->init_qp - 26;
144    pp->num_ref_idx_l0_active_minus1  = pps->ref_count[0] - 1;
145    pp->num_ref_idx_l1_active_minus1  = pps->ref_count[1] - 1;
146    pp->Reserved8BitsA                = 0;
147    pp->frame_num                     = h->poc.frame_num;
148    pp->log2_max_frame_num_minus4     = sps->log2_max_frame_num - 4;
149    pp->pic_order_cnt_type            = sps->poc_type;
150    if (sps->poc_type == 0)
151        pp->log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_poc_lsb - 4;
152    else if (sps->poc_type == 1)
153        pp->delta_pic_order_always_zero_flag = sps->delta_pic_order_always_zero_flag;
154    pp->direct_8x8_inference_flag     = sps->direct_8x8_inference_flag;
155    pp->entropy_coding_mode_flag      = pps->cabac;
156    pp->pic_order_present_flag        = pps->pic_order_present;
157    pp->num_slice_groups_minus1       = pps->slice_group_count - 1;
158    pp->slice_group_map_type          = pps->mb_slice_group_map_type;
159    pp->deblocking_filter_control_present_flag = pps->deblocking_filter_parameters_present;
160    pp->redundant_pic_cnt_present_flag= pps->redundant_pic_cnt_present;
161    pp->Reserved8BitsB                = 0;
162    pp->slice_group_change_rate_minus1= 0;  /* XXX not implemented by FFmpeg */
163    //pp->SliceGroupMap[810];               /* XXX not implemented by FFmpeg */
164}
165
166static void fill_scaling_lists(const AVCodecContext *avctx, AVDXVAContext *ctx, const H264Context *h, DXVA_Qmatrix_H264 *qm)
167{
168    const PPS *pps = h->ps.pps;
169    unsigned i, j;
170    memset(qm, 0, sizeof(*qm));
171    if (DXVA_CONTEXT_WORKAROUND(avctx, ctx) & FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG) {
172        for (i = 0; i < 6; i++)
173            for (j = 0; j < 16; j++)
174                qm->bScalingLists4x4[i][j] = pps->scaling_matrix4[i][j];
175
176        for (i = 0; i < 64; i++) {
177            qm->bScalingLists8x8[0][i] = pps->scaling_matrix8[0][i];
178            qm->bScalingLists8x8[1][i] = pps->scaling_matrix8[3][i];
179        }
180    } else {
181        for (i = 0; i < 6; i++)
182            for (j = 0; j < 16; j++)
183                qm->bScalingLists4x4[i][j] = pps->scaling_matrix4[i][ff_zigzag_scan[j]];
184
185        for (i = 0; i < 64; i++) {
186            qm->bScalingLists8x8[0][i] = pps->scaling_matrix8[0][ff_zigzag_direct[i]];
187            qm->bScalingLists8x8[1][i] = pps->scaling_matrix8[3][ff_zigzag_direct[i]];
188        }
189    }
190}
191
192static int is_slice_short(const AVCodecContext *avctx, AVDXVAContext *ctx)
193{
194    assert(DXVA_CONTEXT_CFG_BITSTREAM(avctx, ctx) == 1 ||
195           DXVA_CONTEXT_CFG_BITSTREAM(avctx, ctx) == 2);
196    return DXVA_CONTEXT_CFG_BITSTREAM(avctx, ctx) == 2;
197}
198
199static void fill_slice_short(DXVA_Slice_H264_Short *slice,
200                             unsigned position, unsigned size)
201{
202    memset(slice, 0, sizeof(*slice));
203    slice->BSNALunitDataLocation = position;
204    slice->SliceBytesInBuffer    = size;
205    slice->wBadSliceChopping     = 0;
206}
207
208static int get_refpic_index(const DXVA_PicParams_H264 *pp, int surface_index)
209{
210    int i;
211    for (i = 0; i < FF_ARRAY_ELEMS(pp->RefFrameList); i++) {
212        if ((pp->RefFrameList[i].bPicEntry & 0x7f) == surface_index)
213          return i;
214    }
215    return 0x7f;
216}
217
218static void fill_slice_long(AVCodecContext *avctx, DXVA_Slice_H264_Long *slice,
219                            const DXVA_PicParams_H264 *pp, unsigned position, unsigned size)
220{
221    const H264Context *h = avctx->priv_data;
222    H264SliceContext *sl = &h->slice_ctx[0];
223    AVDXVAContext *ctx = DXVA_CONTEXT(avctx);
224    unsigned list;
225
226    memset(slice, 0, sizeof(*slice));
227    slice->BSNALunitDataLocation = position;
228    slice->SliceBytesInBuffer    = size;
229    slice->wBadSliceChopping     = 0;
230
231    slice->first_mb_in_slice     = (sl->mb_y >> FIELD_OR_MBAFF_PICTURE(h)) * h->mb_width + sl->mb_x;
232    slice->NumMbsForSlice        = 0; /* XXX it is set once we have all slices */
233    slice->BitOffsetToSliceData  = get_bits_count(&sl->gb) - 8;
234    slice->slice_type            = ff_h264_get_slice_type(sl);
235    if (sl->slice_type_fixed)
236        slice->slice_type += 5;
237    slice->luma_log2_weight_denom       = sl->pwt.luma_log2_weight_denom;
238    slice->chroma_log2_weight_denom     = sl->pwt.chroma_log2_weight_denom;
239    if (sl->list_count > 0)
240        slice->num_ref_idx_l0_active_minus1 = sl->ref_count[0] - 1;
241    if (sl->list_count > 1)
242        slice->num_ref_idx_l1_active_minus1 = sl->ref_count[1] - 1;
243    slice->slice_alpha_c0_offset_div2   = sl->slice_alpha_c0_offset / 2;
244    slice->slice_beta_offset_div2       = sl->slice_beta_offset     / 2;
245    slice->Reserved8Bits                = 0;
246
247    for (list = 0; list < 2; list++) {
248        unsigned i;
249        for (i = 0; i < FF_ARRAY_ELEMS(slice->RefPicList[list]); i++) {
250            if (list < sl->list_count && i < sl->ref_count[list]) {
251                const H264Picture *r = sl->ref_list[list][i].parent;
252                unsigned plane;
253                unsigned index;
254                if (DXVA_CONTEXT_WORKAROUND(avctx, ctx) & FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO)
255                    index = ff_dxva2_get_surface_index(avctx, ctx, r->f);
256                else
257                    index = get_refpic_index(pp, ff_dxva2_get_surface_index(avctx, ctx, r->f));
258                fill_picture_entry(&slice->RefPicList[list][i], index,
259                                   sl->ref_list[list][i].reference == PICT_BOTTOM_FIELD);
260                for (plane = 0; plane < 3; plane++) {
261                    int w, o;
262                    if (plane == 0 && sl->pwt.luma_weight_flag[list]) {
263                        w = sl->pwt.luma_weight[i][list][0];
264                        o = sl->pwt.luma_weight[i][list][1];
265                    } else if (plane >= 1 && sl->pwt.chroma_weight_flag[list]) {
266                        w = sl->pwt.chroma_weight[i][list][plane-1][0];
267                        o = sl->pwt.chroma_weight[i][list][plane-1][1];
268                    } else {
269                        w = 1 << (plane == 0 ? sl->pwt.luma_log2_weight_denom :
270                                               sl->pwt.chroma_log2_weight_denom);
271                        o = 0;
272                    }
273                    slice->Weights[list][i][plane][0] = w;
274                    slice->Weights[list][i][plane][1] = o;
275                }
276            } else {
277                unsigned plane;
278                slice->RefPicList[list][i].bPicEntry = 0xff;
279                for (plane = 0; plane < 3; plane++) {
280                    slice->Weights[list][i][plane][0] = 0;
281                    slice->Weights[list][i][plane][1] = 0;
282                }
283            }
284        }
285    }
286    slice->slice_qs_delta    = 0; /* XXX not implemented by FFmpeg */
287    slice->slice_qp_delta    = sl->qscale - h->ps.pps->init_qp;
288    slice->redundant_pic_cnt = sl->redundant_pic_count;
289    if (sl->slice_type == AV_PICTURE_TYPE_B)
290        slice->direct_spatial_mv_pred_flag = sl->direct_spatial_mv_pred;
291    slice->cabac_init_idc = h->ps.pps->cabac ? sl->cabac_init_idc : 0;
292    if (sl->deblocking_filter < 2)
293        slice->disable_deblocking_filter_idc = 1 - sl->deblocking_filter;
294    else
295        slice->disable_deblocking_filter_idc = sl->deblocking_filter;
296    slice->slice_id = h->current_slice - 1;
297}
298
299static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx,
300                                             DECODER_BUFFER_DESC *bs,
301                                             DECODER_BUFFER_DESC *sc)
302{
303    const H264Context *h = avctx->priv_data;
304    const unsigned mb_count = h->mb_width * h->mb_height;
305    AVDXVAContext *ctx = DXVA_CONTEXT(avctx);
306    const H264Picture *current_picture = h->cur_pic_ptr;
307    struct dxva2_picture_context *ctx_pic = current_picture->hwaccel_picture_private;
308    DXVA_Slice_H264_Short *slice = NULL;
309    void     *dxva_data_ptr = NULL;
310    uint8_t  *dxva_data, *current, *end;
311    unsigned dxva_size = 0;
312    void     *slice_data;
313    unsigned slice_size;
314    unsigned padding;
315    unsigned i;
316    unsigned type;
317
318    /* Create an annex B bitstream buffer with only slice NAL and finalize slice */
319#if CONFIG_D3D11VA
320    if (ff_dxva2_is_d3d11(avctx)) {
321        type = D3D11_VIDEO_DECODER_BUFFER_BITSTREAM;
322        if (FAILED(ID3D11VideoContext_GetDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context,
323                                                       D3D11VA_CONTEXT(ctx)->decoder,
324                                                       type,
325                                                       &dxva_size, &dxva_data_ptr)))
326            return -1;
327    }
328#endif
329#if CONFIG_DXVA2
330    if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
331        type = DXVA2_BitStreamDateBufferType;
332        if (FAILED(IDirectXVideoDecoder_GetBuffer(DXVA2_CONTEXT(ctx)->decoder,
333                                                  type,
334                                                  &dxva_data_ptr, &dxva_size)))
335            return -1;
336    }
337#endif
338
339    dxva_data = dxva_data_ptr;
340    current = dxva_data;
341    end = dxva_data + dxva_size;
342
343    for (i = 0; i < ctx_pic->slice_count; i++) {
344        static const uint8_t start_code[] = { 0, 0, 1 };
345        static const unsigned start_code_size = sizeof(start_code);
346        unsigned position, size;
347
348        assert(offsetof(DXVA_Slice_H264_Short, BSNALunitDataLocation) ==
349               offsetof(DXVA_Slice_H264_Long,  BSNALunitDataLocation));
350        assert(offsetof(DXVA_Slice_H264_Short, SliceBytesInBuffer) ==
351               offsetof(DXVA_Slice_H264_Long,  SliceBytesInBuffer));
352
353        if (is_slice_short(avctx, ctx))
354            slice = &ctx_pic->slice_short[i];
355        else
356            slice = (DXVA_Slice_H264_Short*)&ctx_pic->slice_long[i];
357
358        position = slice->BSNALunitDataLocation;
359        size     = slice->SliceBytesInBuffer;
360        if (start_code_size + size > end - current) {
361            av_log(avctx, AV_LOG_ERROR, "Failed to build bitstream");
362            break;
363        }
364
365        slice->BSNALunitDataLocation = current - dxva_data;
366        slice->SliceBytesInBuffer    = start_code_size + size;
367
368        if (!is_slice_short(avctx, ctx)) {
369            DXVA_Slice_H264_Long *slice_long = (DXVA_Slice_H264_Long*)slice;
370            if (i < ctx_pic->slice_count - 1)
371                slice_long->NumMbsForSlice =
372                    slice_long[1].first_mb_in_slice - slice_long[0].first_mb_in_slice;
373            else
374                slice_long->NumMbsForSlice = mb_count - slice_long->first_mb_in_slice;
375        }
376
377        memcpy(current, start_code, start_code_size);
378        current += start_code_size;
379
380        memcpy(current, &ctx_pic->bitstream[position], size);
381        current += size;
382    }
383    padding = FFMIN(128 - ((current - dxva_data) & 127), end - current);
384    if (slice && padding > 0) {
385        memset(current, 0, padding);
386        current += padding;
387
388        slice->SliceBytesInBuffer += padding;
389    }
390#if CONFIG_D3D11VA
391    if (ff_dxva2_is_d3d11(avctx))
392        if (FAILED(ID3D11VideoContext_ReleaseDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, type)))
393            return -1;
394#endif
395#if CONFIG_DXVA2
396    if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD)
397        if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(DXVA2_CONTEXT(ctx)->decoder, type)))
398            return -1;
399#endif
400    if (i < ctx_pic->slice_count)
401        return -1;
402
403#if CONFIG_D3D11VA
404    if (ff_dxva2_is_d3d11(avctx)) {
405        D3D11_VIDEO_DECODER_BUFFER_DESC *dsc11 = bs;
406        memset(dsc11, 0, sizeof(*dsc11));
407        dsc11->BufferType           = type;
408        dsc11->DataSize             = current - dxva_data;
409        dsc11->NumMBsInBuffer       = mb_count;
410
411        type = D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL;
412
413        av_assert0((dsc11->DataSize & 127) == 0);
414    }
415#endif
416#if CONFIG_DXVA2
417    if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
418        DXVA2_DecodeBufferDesc *dsc2 = bs;
419        memset(dsc2, 0, sizeof(*dsc2));
420        dsc2->CompressedBufferType = type;
421        dsc2->DataSize             = current - dxva_data;
422        dsc2->NumMBsInBuffer       = mb_count;
423
424        type = DXVA2_SliceControlBufferType;
425
426        av_assert0((dsc2->DataSize & 127) == 0);
427    }
428#endif
429
430    if (is_slice_short(avctx, ctx)) {
431        slice_data = ctx_pic->slice_short;
432        slice_size = ctx_pic->slice_count * sizeof(*ctx_pic->slice_short);
433    } else {
434        slice_data = ctx_pic->slice_long;
435        slice_size = ctx_pic->slice_count * sizeof(*ctx_pic->slice_long);
436    }
437    return ff_dxva2_commit_buffer(avctx, ctx, sc,
438                                  type,
439                                  slice_data, slice_size, mb_count);
440}
441
442
443static int dxva2_h264_start_frame(AVCodecContext *avctx,
444                                  av_unused const uint8_t *buffer,
445                                  av_unused uint32_t size)
446{
447    const H264Context *h = avctx->priv_data;
448    AVDXVAContext *ctx = DXVA_CONTEXT(avctx);
449    struct dxva2_picture_context *ctx_pic = h->cur_pic_ptr->hwaccel_picture_private;
450
451    if (!DXVA_CONTEXT_VALID(avctx, ctx))
452        return -1;
453    assert(ctx_pic);
454
455    /* Fill up DXVA_PicParams_H264 */
456    fill_picture_parameters(avctx, ctx, h, &ctx_pic->pp);
457
458    /* Fill up DXVA_Qmatrix_H264 */
459    fill_scaling_lists(avctx, ctx, h, &ctx_pic->qm);
460
461    ctx_pic->slice_count    = 0;
462    ctx_pic->bitstream_size = 0;
463    ctx_pic->bitstream      = NULL;
464    return 0;
465}
466
467static int dxva2_h264_decode_slice(AVCodecContext *avctx,
468                                   const uint8_t *buffer,
469                                   uint32_t size)
470{
471    const H264Context *h = avctx->priv_data;
472    const H264SliceContext *sl = &h->slice_ctx[0];
473    AVDXVAContext *ctx = DXVA_CONTEXT(avctx);
474    const H264Picture *current_picture = h->cur_pic_ptr;
475    struct dxva2_picture_context *ctx_pic = current_picture->hwaccel_picture_private;
476    unsigned position;
477
478    if (ctx_pic->slice_count >= MAX_SLICES)
479        return -1;
480
481    if (!ctx_pic->bitstream)
482        ctx_pic->bitstream = buffer;
483    ctx_pic->bitstream_size += size;
484
485    position = buffer - ctx_pic->bitstream;
486    if (is_slice_short(avctx, ctx))
487        fill_slice_short(&ctx_pic->slice_short[ctx_pic->slice_count],
488                         position, size);
489    else
490        fill_slice_long(avctx, &ctx_pic->slice_long[ctx_pic->slice_count],
491                        &ctx_pic->pp, position, size);
492    ctx_pic->slice_count++;
493
494    if (sl->slice_type != AV_PICTURE_TYPE_I && sl->slice_type != AV_PICTURE_TYPE_SI)
495        ctx_pic->pp.wBitFields &= ~(1 << 15); /* Set IntraPicFlag to 0 */
496    return 0;
497}
498
499static int dxva2_h264_end_frame(AVCodecContext *avctx)
500{
501    H264Context *h = avctx->priv_data;
502    H264SliceContext *sl = &h->slice_ctx[0];
503    struct dxva2_picture_context *ctx_pic =
504        h->cur_pic_ptr->hwaccel_picture_private;
505    int ret;
506
507    if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0)
508        return -1;
509    ret = ff_dxva2_common_end_frame(avctx, h->cur_pic_ptr->f,
510                                    &ctx_pic->pp, sizeof(ctx_pic->pp),
511                                    &ctx_pic->qm, sizeof(ctx_pic->qm),
512                                    commit_bitstream_and_slice_buffer);
513    if (!ret)
514        ff_h264_draw_horiz_band(h, sl, 0, h->avctx->height);
515    return ret;
516}
517
518#if CONFIG_H264_DXVA2_HWACCEL
519const AVHWAccel ff_h264_dxva2_hwaccel = {
520    .name           = "h264_dxva2",
521    .type           = AVMEDIA_TYPE_VIDEO,
522    .id             = AV_CODEC_ID_H264,
523    .pix_fmt        = AV_PIX_FMT_DXVA2_VLD,
524    .init           = ff_dxva2_decode_init,
525    .uninit         = ff_dxva2_decode_uninit,
526    .start_frame    = dxva2_h264_start_frame,
527    .decode_slice   = dxva2_h264_decode_slice,
528    .end_frame      = dxva2_h264_end_frame,
529    .frame_params   = ff_dxva2_common_frame_params,
530    .frame_priv_data_size = sizeof(struct dxva2_picture_context),
531    .priv_data_size = sizeof(FFDXVASharedContext),
532};
533#endif
534
535#if CONFIG_H264_D3D11VA_HWACCEL
536const AVHWAccel ff_h264_d3d11va_hwaccel = {
537    .name           = "h264_d3d11va",
538    .type           = AVMEDIA_TYPE_VIDEO,
539    .id             = AV_CODEC_ID_H264,
540    .pix_fmt        = AV_PIX_FMT_D3D11VA_VLD,
541    .init           = ff_dxva2_decode_init,
542    .uninit         = ff_dxva2_decode_uninit,
543    .start_frame    = dxva2_h264_start_frame,
544    .decode_slice   = dxva2_h264_decode_slice,
545    .end_frame      = dxva2_h264_end_frame,
546    .frame_params   = ff_dxva2_common_frame_params,
547    .frame_priv_data_size = sizeof(struct dxva2_picture_context),
548    .priv_data_size = sizeof(FFDXVASharedContext),
549};
550#endif
551
552#if CONFIG_H264_D3D11VA2_HWACCEL
553const AVHWAccel ff_h264_d3d11va2_hwaccel = {
554    .name           = "h264_d3d11va2",
555    .type           = AVMEDIA_TYPE_VIDEO,
556    .id             = AV_CODEC_ID_H264,
557    .pix_fmt        = AV_PIX_FMT_D3D11,
558    .init           = ff_dxva2_decode_init,
559    .uninit         = ff_dxva2_decode_uninit,
560    .start_frame    = dxva2_h264_start_frame,
561    .decode_slice   = dxva2_h264_decode_slice,
562    .end_frame      = dxva2_h264_end_frame,
563    .frame_params   = ff_dxva2_common_frame_params,
564    .frame_priv_data_size = sizeof(struct dxva2_picture_context),
565    .priv_data_size = sizeof(FFDXVASharedContext),
566};
567#endif
568