1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * H.264 HW decode acceleration through VA API
3cabdff1aSopenharmony_ci *
4cabdff1aSopenharmony_ci * Copyright (C) 2008-2009 Splitted-Desktop Systems
5cabdff1aSopenharmony_ci *
6cabdff1aSopenharmony_ci * This file is part of FFmpeg.
7cabdff1aSopenharmony_ci *
8cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
9cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
10cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
11cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
12cabdff1aSopenharmony_ci *
13cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
14cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
15cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16cabdff1aSopenharmony_ci * Lesser General Public License for more details.
17cabdff1aSopenharmony_ci *
18cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
19cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
20cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21cabdff1aSopenharmony_ci */
22cabdff1aSopenharmony_ci
23cabdff1aSopenharmony_ci#include "h264dec.h"
24cabdff1aSopenharmony_ci#include "h264_ps.h"
25cabdff1aSopenharmony_ci#include "hwconfig.h"
26cabdff1aSopenharmony_ci#include "vaapi_decode.h"
27cabdff1aSopenharmony_ci
28cabdff1aSopenharmony_ci/**
29cabdff1aSopenharmony_ci * @file
30cabdff1aSopenharmony_ci * This file implements the glue code between FFmpeg's and VA API's
31cabdff1aSopenharmony_ci * structures for H.264 decoding.
32cabdff1aSopenharmony_ci */
33cabdff1aSopenharmony_ci
34cabdff1aSopenharmony_ci/**
35cabdff1aSopenharmony_ci * Initialize an empty VA API picture.
36cabdff1aSopenharmony_ci *
37cabdff1aSopenharmony_ci * VA API requires a fixed-size reference picture array.
38cabdff1aSopenharmony_ci */
39cabdff1aSopenharmony_cistatic void init_vaapi_pic(VAPictureH264 *va_pic)
40cabdff1aSopenharmony_ci{
41cabdff1aSopenharmony_ci    va_pic->picture_id          = VA_INVALID_ID;
42cabdff1aSopenharmony_ci    va_pic->flags               = VA_PICTURE_H264_INVALID;
43cabdff1aSopenharmony_ci    va_pic->TopFieldOrderCnt    = 0;
44cabdff1aSopenharmony_ci    va_pic->BottomFieldOrderCnt = 0;
45cabdff1aSopenharmony_ci}
46cabdff1aSopenharmony_ci
47cabdff1aSopenharmony_ci/**
48cabdff1aSopenharmony_ci * Translate an FFmpeg Picture into its VA API form.
49cabdff1aSopenharmony_ci *
50cabdff1aSopenharmony_ci * @param[out] va_pic          A pointer to VA API's own picture struct
51cabdff1aSopenharmony_ci * @param[in]  pic             A pointer to the FFmpeg picture struct to convert
52cabdff1aSopenharmony_ci * @param[in]  pic_structure   The picture field type (as defined in mpegvideo.h),
53cabdff1aSopenharmony_ci *                             supersedes pic's field type if nonzero.
54cabdff1aSopenharmony_ci */
55cabdff1aSopenharmony_cistatic void fill_vaapi_pic(VAPictureH264 *va_pic,
56cabdff1aSopenharmony_ci                           const H264Picture *pic,
57cabdff1aSopenharmony_ci                           int            pic_structure)
58cabdff1aSopenharmony_ci{
59cabdff1aSopenharmony_ci    if (pic_structure == 0)
60cabdff1aSopenharmony_ci        pic_structure = pic->reference;
61cabdff1aSopenharmony_ci    pic_structure &= PICT_FRAME; /* PICT_TOP_FIELD|PICT_BOTTOM_FIELD */
62cabdff1aSopenharmony_ci
63cabdff1aSopenharmony_ci    va_pic->picture_id = ff_vaapi_get_surface_id(pic->f);
64cabdff1aSopenharmony_ci    va_pic->frame_idx  = pic->long_ref ? pic->pic_id : pic->frame_num;
65cabdff1aSopenharmony_ci
66cabdff1aSopenharmony_ci    va_pic->flags      = 0;
67cabdff1aSopenharmony_ci    if (pic_structure != PICT_FRAME)
68cabdff1aSopenharmony_ci        va_pic->flags |= (pic_structure & PICT_TOP_FIELD) ? VA_PICTURE_H264_TOP_FIELD : VA_PICTURE_H264_BOTTOM_FIELD;
69cabdff1aSopenharmony_ci    if (pic->reference)
70cabdff1aSopenharmony_ci        va_pic->flags |= pic->long_ref ? VA_PICTURE_H264_LONG_TERM_REFERENCE : VA_PICTURE_H264_SHORT_TERM_REFERENCE;
71cabdff1aSopenharmony_ci
72cabdff1aSopenharmony_ci    va_pic->TopFieldOrderCnt = 0;
73cabdff1aSopenharmony_ci    if (pic->field_poc[0] != INT_MAX)
74cabdff1aSopenharmony_ci        va_pic->TopFieldOrderCnt = pic->field_poc[0];
75cabdff1aSopenharmony_ci
76cabdff1aSopenharmony_ci    va_pic->BottomFieldOrderCnt = 0;
77cabdff1aSopenharmony_ci    if (pic->field_poc[1] != INT_MAX)
78cabdff1aSopenharmony_ci        va_pic->BottomFieldOrderCnt = pic->field_poc[1];
79cabdff1aSopenharmony_ci}
80cabdff1aSopenharmony_ci
81cabdff1aSopenharmony_ci/** Decoded Picture Buffer (DPB). */
82cabdff1aSopenharmony_citypedef struct DPB {
83cabdff1aSopenharmony_ci    int            size;        ///< Current number of reference frames in the DPB
84cabdff1aSopenharmony_ci    int            max_size;    ///< Max number of reference frames. This is FF_ARRAY_ELEMS(VAPictureParameterBufferH264.ReferenceFrames)
85cabdff1aSopenharmony_ci    VAPictureH264 *va_pics;     ///< Pointer to VAPictureParameterBufferH264.ReferenceFrames array
86cabdff1aSopenharmony_ci} DPB;
87cabdff1aSopenharmony_ci
88cabdff1aSopenharmony_ci/**
89cabdff1aSopenharmony_ci * Append picture to the decoded picture buffer, in a VA API form that
90cabdff1aSopenharmony_ci * merges the second field picture attributes with the first, if
91cabdff1aSopenharmony_ci * available.  The decoded picture buffer's size must be large enough
92cabdff1aSopenharmony_ci * to receive the new VA API picture object.
93cabdff1aSopenharmony_ci */
94cabdff1aSopenharmony_cistatic int dpb_add(DPB *dpb, const H264Picture *pic)
95cabdff1aSopenharmony_ci{
96cabdff1aSopenharmony_ci    int i;
97cabdff1aSopenharmony_ci
98cabdff1aSopenharmony_ci    if (dpb->size >= dpb->max_size)
99cabdff1aSopenharmony_ci        return -1;
100cabdff1aSopenharmony_ci
101cabdff1aSopenharmony_ci    for (i = 0; i < dpb->size; i++) {
102cabdff1aSopenharmony_ci        VAPictureH264 * const va_pic = &dpb->va_pics[i];
103cabdff1aSopenharmony_ci        if (va_pic->picture_id == ff_vaapi_get_surface_id(pic->f)) {
104cabdff1aSopenharmony_ci            VAPictureH264 temp_va_pic;
105cabdff1aSopenharmony_ci            fill_vaapi_pic(&temp_va_pic, pic, 0);
106cabdff1aSopenharmony_ci
107cabdff1aSopenharmony_ci            if ((temp_va_pic.flags ^ va_pic->flags) & (VA_PICTURE_H264_TOP_FIELD | VA_PICTURE_H264_BOTTOM_FIELD)) {
108cabdff1aSopenharmony_ci                va_pic->flags |= temp_va_pic.flags & (VA_PICTURE_H264_TOP_FIELD | VA_PICTURE_H264_BOTTOM_FIELD);
109cabdff1aSopenharmony_ci                /* Merge second field */
110cabdff1aSopenharmony_ci                if (temp_va_pic.flags & VA_PICTURE_H264_TOP_FIELD) {
111cabdff1aSopenharmony_ci                    va_pic->TopFieldOrderCnt    = temp_va_pic.TopFieldOrderCnt;
112cabdff1aSopenharmony_ci                } else {
113cabdff1aSopenharmony_ci                    va_pic->BottomFieldOrderCnt = temp_va_pic.BottomFieldOrderCnt;
114cabdff1aSopenharmony_ci                }
115cabdff1aSopenharmony_ci            }
116cabdff1aSopenharmony_ci            return 0;
117cabdff1aSopenharmony_ci        }
118cabdff1aSopenharmony_ci    }
119cabdff1aSopenharmony_ci
120cabdff1aSopenharmony_ci    fill_vaapi_pic(&dpb->va_pics[dpb->size++], pic, 0);
121cabdff1aSopenharmony_ci    return 0;
122cabdff1aSopenharmony_ci}
123cabdff1aSopenharmony_ci
124cabdff1aSopenharmony_ci/** Fill in VA API reference frames array. */
125cabdff1aSopenharmony_cistatic int fill_vaapi_ReferenceFrames(VAPictureParameterBufferH264 *pic_param,
126cabdff1aSopenharmony_ci                                      const H264Context            *h)
127cabdff1aSopenharmony_ci{
128cabdff1aSopenharmony_ci    DPB dpb;
129cabdff1aSopenharmony_ci    int i;
130cabdff1aSopenharmony_ci
131cabdff1aSopenharmony_ci    dpb.size     = 0;
132cabdff1aSopenharmony_ci    dpb.max_size = FF_ARRAY_ELEMS(pic_param->ReferenceFrames);
133cabdff1aSopenharmony_ci    dpb.va_pics  = pic_param->ReferenceFrames;
134cabdff1aSopenharmony_ci    for (i = 0; i < dpb.max_size; i++)
135cabdff1aSopenharmony_ci        init_vaapi_pic(&dpb.va_pics[i]);
136cabdff1aSopenharmony_ci
137cabdff1aSopenharmony_ci    for (i = 0; i < h->short_ref_count; i++) {
138cabdff1aSopenharmony_ci        const H264Picture *pic = h->short_ref[i];
139cabdff1aSopenharmony_ci        if (pic && pic->reference && dpb_add(&dpb, pic) < 0)
140cabdff1aSopenharmony_ci            return -1;
141cabdff1aSopenharmony_ci    }
142cabdff1aSopenharmony_ci
143cabdff1aSopenharmony_ci    for (i = 0; i < 16; i++) {
144cabdff1aSopenharmony_ci        const H264Picture *pic = h->long_ref[i];
145cabdff1aSopenharmony_ci        if (pic && pic->reference && dpb_add(&dpb, pic) < 0)
146cabdff1aSopenharmony_ci            return -1;
147cabdff1aSopenharmony_ci    }
148cabdff1aSopenharmony_ci    return 0;
149cabdff1aSopenharmony_ci}
150cabdff1aSopenharmony_ci
151cabdff1aSopenharmony_ci/**
152cabdff1aSopenharmony_ci * Fill in VA API reference picture lists from the FFmpeg reference
153cabdff1aSopenharmony_ci * picture list.
154cabdff1aSopenharmony_ci *
155cabdff1aSopenharmony_ci * @param[out] RefPicList  VA API internal reference picture list
156cabdff1aSopenharmony_ci * @param[in]  ref_list    A pointer to the FFmpeg reference list
157cabdff1aSopenharmony_ci * @param[in]  ref_count   The number of reference pictures in ref_list
158cabdff1aSopenharmony_ci */
159cabdff1aSopenharmony_cistatic void fill_vaapi_RefPicList(VAPictureH264 RefPicList[32],
160cabdff1aSopenharmony_ci                                  const H264Ref *ref_list,
161cabdff1aSopenharmony_ci                                  unsigned int  ref_count)
162cabdff1aSopenharmony_ci{
163cabdff1aSopenharmony_ci    unsigned int i, n = 0;
164cabdff1aSopenharmony_ci    for (i = 0; i < ref_count; i++)
165cabdff1aSopenharmony_ci        if (ref_list[i].reference)
166cabdff1aSopenharmony_ci            fill_vaapi_pic(&RefPicList[n++], ref_list[i].parent,
167cabdff1aSopenharmony_ci                           ref_list[i].reference);
168cabdff1aSopenharmony_ci
169cabdff1aSopenharmony_ci    for (; n < 32; n++)
170cabdff1aSopenharmony_ci        init_vaapi_pic(&RefPicList[n]);
171cabdff1aSopenharmony_ci}
172cabdff1aSopenharmony_ci
173cabdff1aSopenharmony_ci/**
174cabdff1aSopenharmony_ci * Fill in prediction weight table.
175cabdff1aSopenharmony_ci *
176cabdff1aSopenharmony_ci * VA API requires a plain prediction weight table as it does not infer
177cabdff1aSopenharmony_ci * any value.
178cabdff1aSopenharmony_ci *
179cabdff1aSopenharmony_ci * @param[in]  h                   A pointer to the current H.264 context
180cabdff1aSopenharmony_ci * @param[in]  list                The reference frame list index to use
181cabdff1aSopenharmony_ci * @param[out] luma_weight_flag    VA API plain luma weight flag
182cabdff1aSopenharmony_ci * @param[out] luma_weight         VA API plain luma weight table
183cabdff1aSopenharmony_ci * @param[out] luma_offset         VA API plain luma offset table
184cabdff1aSopenharmony_ci * @param[out] chroma_weight_flag  VA API plain chroma weight flag
185cabdff1aSopenharmony_ci * @param[out] chroma_weight       VA API plain chroma weight table
186cabdff1aSopenharmony_ci * @param[out] chroma_offset       VA API plain chroma offset table
187cabdff1aSopenharmony_ci */
188cabdff1aSopenharmony_cistatic void fill_vaapi_plain_pred_weight_table(const H264Context *h,
189cabdff1aSopenharmony_ci                                               int            list,
190cabdff1aSopenharmony_ci                                               unsigned char *luma_weight_flag,
191cabdff1aSopenharmony_ci                                               short          luma_weight[32],
192cabdff1aSopenharmony_ci                                               short          luma_offset[32],
193cabdff1aSopenharmony_ci                                               unsigned char *chroma_weight_flag,
194cabdff1aSopenharmony_ci                                               short          chroma_weight[32][2],
195cabdff1aSopenharmony_ci                                               short          chroma_offset[32][2])
196cabdff1aSopenharmony_ci{
197cabdff1aSopenharmony_ci    const H264SliceContext *sl = &h->slice_ctx[0];
198cabdff1aSopenharmony_ci    unsigned int i, j;
199cabdff1aSopenharmony_ci
200cabdff1aSopenharmony_ci    *luma_weight_flag    = sl->pwt.luma_weight_flag[list];
201cabdff1aSopenharmony_ci    *chroma_weight_flag  = sl->pwt.chroma_weight_flag[list];
202cabdff1aSopenharmony_ci
203cabdff1aSopenharmony_ci    for (i = 0; i < sl->ref_count[list]; i++) {
204cabdff1aSopenharmony_ci        /* VA API also wants the inferred (default) values, not
205cabdff1aSopenharmony_ci           only what is available in the bitstream (7.4.3.2). */
206cabdff1aSopenharmony_ci        if (sl->pwt.luma_weight_flag[list]) {
207cabdff1aSopenharmony_ci            luma_weight[i] = sl->pwt.luma_weight[i][list][0];
208cabdff1aSopenharmony_ci            luma_offset[i] = sl->pwt.luma_weight[i][list][1];
209cabdff1aSopenharmony_ci        } else {
210cabdff1aSopenharmony_ci            luma_weight[i] = 1 << sl->pwt.luma_log2_weight_denom;
211cabdff1aSopenharmony_ci            luma_offset[i] = 0;
212cabdff1aSopenharmony_ci        }
213cabdff1aSopenharmony_ci        for (j = 0; j < 2; j++) {
214cabdff1aSopenharmony_ci            if (sl->pwt.chroma_weight_flag[list]) {
215cabdff1aSopenharmony_ci                chroma_weight[i][j] = sl->pwt.chroma_weight[i][list][j][0];
216cabdff1aSopenharmony_ci                chroma_offset[i][j] = sl->pwt.chroma_weight[i][list][j][1];
217cabdff1aSopenharmony_ci            } else {
218cabdff1aSopenharmony_ci                chroma_weight[i][j] = 1 << sl->pwt.chroma_log2_weight_denom;
219cabdff1aSopenharmony_ci                chroma_offset[i][j] = 0;
220cabdff1aSopenharmony_ci            }
221cabdff1aSopenharmony_ci        }
222cabdff1aSopenharmony_ci    }
223cabdff1aSopenharmony_ci}
224cabdff1aSopenharmony_ci
225cabdff1aSopenharmony_ci/** Initialize and start decoding a frame with VA API. */
226cabdff1aSopenharmony_cistatic int vaapi_h264_start_frame(AVCodecContext          *avctx,
227cabdff1aSopenharmony_ci                                  av_unused const uint8_t *buffer,
228cabdff1aSopenharmony_ci                                  av_unused uint32_t       size)
229cabdff1aSopenharmony_ci{
230cabdff1aSopenharmony_ci    const H264Context *h = avctx->priv_data;
231cabdff1aSopenharmony_ci    VAAPIDecodePicture *pic = h->cur_pic_ptr->hwaccel_picture_private;
232cabdff1aSopenharmony_ci    const PPS *pps = h->ps.pps;
233cabdff1aSopenharmony_ci    const SPS *sps = h->ps.sps;
234cabdff1aSopenharmony_ci    VAPictureParameterBufferH264 pic_param;
235cabdff1aSopenharmony_ci    VAIQMatrixBufferH264 iq_matrix;
236cabdff1aSopenharmony_ci    int err;
237cabdff1aSopenharmony_ci
238cabdff1aSopenharmony_ci    pic->output_surface = ff_vaapi_get_surface_id(h->cur_pic_ptr->f);
239cabdff1aSopenharmony_ci
240cabdff1aSopenharmony_ci    pic_param = (VAPictureParameterBufferH264) {
241cabdff1aSopenharmony_ci        .picture_width_in_mbs_minus1                = h->mb_width - 1,
242cabdff1aSopenharmony_ci        .picture_height_in_mbs_minus1               = h->mb_height - 1,
243cabdff1aSopenharmony_ci        .bit_depth_luma_minus8                      = sps->bit_depth_luma - 8,
244cabdff1aSopenharmony_ci        .bit_depth_chroma_minus8                    = sps->bit_depth_chroma - 8,
245cabdff1aSopenharmony_ci        .num_ref_frames                             = sps->ref_frame_count,
246cabdff1aSopenharmony_ci        .seq_fields.bits = {
247cabdff1aSopenharmony_ci            .chroma_format_idc                      = sps->chroma_format_idc,
248cabdff1aSopenharmony_ci            .residual_colour_transform_flag         = sps->residual_color_transform_flag,
249cabdff1aSopenharmony_ci            .gaps_in_frame_num_value_allowed_flag   = sps->gaps_in_frame_num_allowed_flag,
250cabdff1aSopenharmony_ci            .frame_mbs_only_flag                    = sps->frame_mbs_only_flag,
251cabdff1aSopenharmony_ci            .mb_adaptive_frame_field_flag           = sps->mb_aff,
252cabdff1aSopenharmony_ci            .direct_8x8_inference_flag              = sps->direct_8x8_inference_flag,
253cabdff1aSopenharmony_ci            .MinLumaBiPredSize8x8                   = sps->level_idc >= 31, /* A.3.3.2 */
254cabdff1aSopenharmony_ci            .log2_max_frame_num_minus4              = sps->log2_max_frame_num - 4,
255cabdff1aSopenharmony_ci            .pic_order_cnt_type                     = sps->poc_type,
256cabdff1aSopenharmony_ci            .log2_max_pic_order_cnt_lsb_minus4      = sps->log2_max_poc_lsb - 4,
257cabdff1aSopenharmony_ci            .delta_pic_order_always_zero_flag       = sps->delta_pic_order_always_zero_flag,
258cabdff1aSopenharmony_ci        },
259cabdff1aSopenharmony_ci        .pic_init_qp_minus26                        = pps->init_qp - 26,
260cabdff1aSopenharmony_ci        .pic_init_qs_minus26                        = pps->init_qs - 26,
261cabdff1aSopenharmony_ci        .chroma_qp_index_offset                     = pps->chroma_qp_index_offset[0],
262cabdff1aSopenharmony_ci        .second_chroma_qp_index_offset              = pps->chroma_qp_index_offset[1],
263cabdff1aSopenharmony_ci        .pic_fields.bits = {
264cabdff1aSopenharmony_ci            .entropy_coding_mode_flag               = pps->cabac,
265cabdff1aSopenharmony_ci            .weighted_pred_flag                     = pps->weighted_pred,
266cabdff1aSopenharmony_ci            .weighted_bipred_idc                    = pps->weighted_bipred_idc,
267cabdff1aSopenharmony_ci            .transform_8x8_mode_flag                = pps->transform_8x8_mode,
268cabdff1aSopenharmony_ci            .field_pic_flag                         = h->picture_structure != PICT_FRAME,
269cabdff1aSopenharmony_ci            .constrained_intra_pred_flag            = pps->constrained_intra_pred,
270cabdff1aSopenharmony_ci            .pic_order_present_flag                 = pps->pic_order_present,
271cabdff1aSopenharmony_ci            .deblocking_filter_control_present_flag = pps->deblocking_filter_parameters_present,
272cabdff1aSopenharmony_ci            .redundant_pic_cnt_present_flag         = pps->redundant_pic_cnt_present,
273cabdff1aSopenharmony_ci            .reference_pic_flag                     = h->nal_ref_idc != 0,
274cabdff1aSopenharmony_ci        },
275cabdff1aSopenharmony_ci        .frame_num                                  = h->poc.frame_num,
276cabdff1aSopenharmony_ci    };
277cabdff1aSopenharmony_ci
278cabdff1aSopenharmony_ci    fill_vaapi_pic(&pic_param.CurrPic, h->cur_pic_ptr, h->picture_structure);
279cabdff1aSopenharmony_ci    err = fill_vaapi_ReferenceFrames(&pic_param, h);
280cabdff1aSopenharmony_ci    if (err < 0)
281cabdff1aSopenharmony_ci        goto fail;
282cabdff1aSopenharmony_ci
283cabdff1aSopenharmony_ci    err = ff_vaapi_decode_make_param_buffer(avctx, pic,
284cabdff1aSopenharmony_ci                                            VAPictureParameterBufferType,
285cabdff1aSopenharmony_ci                                            &pic_param, sizeof(pic_param));
286cabdff1aSopenharmony_ci    if (err < 0)
287cabdff1aSopenharmony_ci        goto fail;
288cabdff1aSopenharmony_ci
289cabdff1aSopenharmony_ci    memcpy(iq_matrix.ScalingList4x4,
290cabdff1aSopenharmony_ci           pps->scaling_matrix4, sizeof(iq_matrix.ScalingList4x4));
291cabdff1aSopenharmony_ci    memcpy(iq_matrix.ScalingList8x8[0],
292cabdff1aSopenharmony_ci           pps->scaling_matrix8[0], sizeof(iq_matrix.ScalingList8x8[0]));
293cabdff1aSopenharmony_ci    memcpy(iq_matrix.ScalingList8x8[1],
294cabdff1aSopenharmony_ci           pps->scaling_matrix8[3], sizeof(iq_matrix.ScalingList8x8[0]));
295cabdff1aSopenharmony_ci
296cabdff1aSopenharmony_ci    err = ff_vaapi_decode_make_param_buffer(avctx, pic,
297cabdff1aSopenharmony_ci                                            VAIQMatrixBufferType,
298cabdff1aSopenharmony_ci                                            &iq_matrix, sizeof(iq_matrix));
299cabdff1aSopenharmony_ci    if (err < 0)
300cabdff1aSopenharmony_ci        goto fail;
301cabdff1aSopenharmony_ci
302cabdff1aSopenharmony_ci    return 0;
303cabdff1aSopenharmony_ci
304cabdff1aSopenharmony_cifail:
305cabdff1aSopenharmony_ci    ff_vaapi_decode_cancel(avctx, pic);
306cabdff1aSopenharmony_ci    return err;
307cabdff1aSopenharmony_ci}
308cabdff1aSopenharmony_ci
309cabdff1aSopenharmony_ci/** End a hardware decoding based frame. */
310cabdff1aSopenharmony_cistatic int vaapi_h264_end_frame(AVCodecContext *avctx)
311cabdff1aSopenharmony_ci{
312cabdff1aSopenharmony_ci    const H264Context *h = avctx->priv_data;
313cabdff1aSopenharmony_ci    VAAPIDecodePicture *pic = h->cur_pic_ptr->hwaccel_picture_private;
314cabdff1aSopenharmony_ci    H264SliceContext *sl = &h->slice_ctx[0];
315cabdff1aSopenharmony_ci    int ret;
316cabdff1aSopenharmony_ci
317cabdff1aSopenharmony_ci    ret = ff_vaapi_decode_issue(avctx, pic);
318cabdff1aSopenharmony_ci    if (ret < 0)
319cabdff1aSopenharmony_ci        goto finish;
320cabdff1aSopenharmony_ci
321cabdff1aSopenharmony_ci    ff_h264_draw_horiz_band(h, sl, 0, h->avctx->height);
322cabdff1aSopenharmony_ci
323cabdff1aSopenharmony_cifinish:
324cabdff1aSopenharmony_ci    return ret;
325cabdff1aSopenharmony_ci}
326cabdff1aSopenharmony_ci
327cabdff1aSopenharmony_ci/** Decode the given H.264 slice with VA API. */
328cabdff1aSopenharmony_cistatic int vaapi_h264_decode_slice(AVCodecContext *avctx,
329cabdff1aSopenharmony_ci                                   const uint8_t  *buffer,
330cabdff1aSopenharmony_ci                                   uint32_t        size)
331cabdff1aSopenharmony_ci{
332cabdff1aSopenharmony_ci    const H264Context *h = avctx->priv_data;
333cabdff1aSopenharmony_ci    VAAPIDecodePicture *pic = h->cur_pic_ptr->hwaccel_picture_private;
334cabdff1aSopenharmony_ci    const H264SliceContext *sl  = &h->slice_ctx[0];
335cabdff1aSopenharmony_ci    VASliceParameterBufferH264 slice_param;
336cabdff1aSopenharmony_ci    int err;
337cabdff1aSopenharmony_ci
338cabdff1aSopenharmony_ci    slice_param = (VASliceParameterBufferH264) {
339cabdff1aSopenharmony_ci        .slice_data_size               = size,
340cabdff1aSopenharmony_ci        .slice_data_offset             = 0,
341cabdff1aSopenharmony_ci        .slice_data_flag               = VA_SLICE_DATA_FLAG_ALL,
342cabdff1aSopenharmony_ci        .slice_data_bit_offset         = get_bits_count(&sl->gb),
343cabdff1aSopenharmony_ci        .first_mb_in_slice             = (sl->mb_y >> FIELD_OR_MBAFF_PICTURE(h)) * h->mb_width + sl->mb_x,
344cabdff1aSopenharmony_ci        .slice_type                    = ff_h264_get_slice_type(sl),
345cabdff1aSopenharmony_ci        .direct_spatial_mv_pred_flag   = sl->slice_type == AV_PICTURE_TYPE_B ? sl->direct_spatial_mv_pred : 0,
346cabdff1aSopenharmony_ci        .num_ref_idx_l0_active_minus1  = sl->list_count > 0 ? sl->ref_count[0] - 1 : 0,
347cabdff1aSopenharmony_ci        .num_ref_idx_l1_active_minus1  = sl->list_count > 1 ? sl->ref_count[1] - 1 : 0,
348cabdff1aSopenharmony_ci        .cabac_init_idc                = sl->cabac_init_idc,
349cabdff1aSopenharmony_ci        .slice_qp_delta                = sl->qscale - h->ps.pps->init_qp,
350cabdff1aSopenharmony_ci        .disable_deblocking_filter_idc = sl->deblocking_filter < 2 ? !sl->deblocking_filter : sl->deblocking_filter,
351cabdff1aSopenharmony_ci        .slice_alpha_c0_offset_div2    = sl->slice_alpha_c0_offset / 2,
352cabdff1aSopenharmony_ci        .slice_beta_offset_div2        = sl->slice_beta_offset     / 2,
353cabdff1aSopenharmony_ci        .luma_log2_weight_denom        = sl->pwt.luma_log2_weight_denom,
354cabdff1aSopenharmony_ci        .chroma_log2_weight_denom      = sl->pwt.chroma_log2_weight_denom,
355cabdff1aSopenharmony_ci    };
356cabdff1aSopenharmony_ci
357cabdff1aSopenharmony_ci    fill_vaapi_RefPicList(slice_param.RefPicList0, sl->ref_list[0],
358cabdff1aSopenharmony_ci                          sl->list_count > 0 ? sl->ref_count[0] : 0);
359cabdff1aSopenharmony_ci    fill_vaapi_RefPicList(slice_param.RefPicList1, sl->ref_list[1],
360cabdff1aSopenharmony_ci                          sl->list_count > 1 ? sl->ref_count[1] : 0);
361cabdff1aSopenharmony_ci
362cabdff1aSopenharmony_ci    fill_vaapi_plain_pred_weight_table(h, 0,
363cabdff1aSopenharmony_ci                                       &slice_param.luma_weight_l0_flag,
364cabdff1aSopenharmony_ci                                       slice_param.luma_weight_l0,
365cabdff1aSopenharmony_ci                                       slice_param.luma_offset_l0,
366cabdff1aSopenharmony_ci                                       &slice_param.chroma_weight_l0_flag,
367cabdff1aSopenharmony_ci                                       slice_param.chroma_weight_l0,
368cabdff1aSopenharmony_ci                                       slice_param.chroma_offset_l0);
369cabdff1aSopenharmony_ci    fill_vaapi_plain_pred_weight_table(h, 1,
370cabdff1aSopenharmony_ci                                       &slice_param.luma_weight_l1_flag,
371cabdff1aSopenharmony_ci                                       slice_param.luma_weight_l1,
372cabdff1aSopenharmony_ci                                       slice_param.luma_offset_l1,
373cabdff1aSopenharmony_ci                                       &slice_param.chroma_weight_l1_flag,
374cabdff1aSopenharmony_ci                                       slice_param.chroma_weight_l1,
375cabdff1aSopenharmony_ci                                       slice_param.chroma_offset_l1);
376cabdff1aSopenharmony_ci
377cabdff1aSopenharmony_ci    err = ff_vaapi_decode_make_slice_buffer(avctx, pic,
378cabdff1aSopenharmony_ci                                            &slice_param, sizeof(slice_param),
379cabdff1aSopenharmony_ci                                            buffer, size);
380cabdff1aSopenharmony_ci    if (err) {
381cabdff1aSopenharmony_ci        ff_vaapi_decode_cancel(avctx, pic);
382cabdff1aSopenharmony_ci        return err;
383cabdff1aSopenharmony_ci    }
384cabdff1aSopenharmony_ci
385cabdff1aSopenharmony_ci    return 0;
386cabdff1aSopenharmony_ci}
387cabdff1aSopenharmony_ci
388cabdff1aSopenharmony_ciconst AVHWAccel ff_h264_vaapi_hwaccel = {
389cabdff1aSopenharmony_ci    .name                 = "h264_vaapi",
390cabdff1aSopenharmony_ci    .type                 = AVMEDIA_TYPE_VIDEO,
391cabdff1aSopenharmony_ci    .id                   = AV_CODEC_ID_H264,
392cabdff1aSopenharmony_ci    .pix_fmt              = AV_PIX_FMT_VAAPI,
393cabdff1aSopenharmony_ci    .start_frame          = &vaapi_h264_start_frame,
394cabdff1aSopenharmony_ci    .end_frame            = &vaapi_h264_end_frame,
395cabdff1aSopenharmony_ci    .decode_slice         = &vaapi_h264_decode_slice,
396cabdff1aSopenharmony_ci    .frame_priv_data_size = sizeof(VAAPIDecodePicture),
397cabdff1aSopenharmony_ci    .init                 = &ff_vaapi_decode_init,
398cabdff1aSopenharmony_ci    .uninit               = &ff_vaapi_decode_uninit,
399cabdff1aSopenharmony_ci    .frame_params         = &ff_vaapi_common_frame_params,
400cabdff1aSopenharmony_ci    .priv_data_size       = sizeof(VAAPIDecodeContext),
401cabdff1aSopenharmony_ci    .caps_internal        = HWACCEL_CAP_ASYNC_SAFE,
402cabdff1aSopenharmony_ci};
403