1/*
2 * MPEG-H Part 2 / HEVC / H.265 HW decode acceleration through VDPAU
3 *
4 * Copyright (c) 2013 Philip Langdale
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 Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#include <vdpau/vdpau.h>
24
25#include "avcodec.h"
26#include "hevc_data.h"
27#include "hevcdec.h"
28#include "hwconfig.h"
29#include "vdpau.h"
30#include "vdpau_internal.h"
31#include "h265_profile_level.h"
32
33
34static int vdpau_hevc_start_frame(AVCodecContext *avctx,
35                                  const uint8_t *buffer, uint32_t size)
36{
37    HEVCContext *h = avctx->priv_data;
38    HEVCFrame *pic = h->ref;
39    struct vdpau_picture_context *pic_ctx = pic->hwaccel_picture_private;
40
41    VdpPictureInfoHEVC *info = &pic_ctx->info.hevc;
42#ifdef VDP_YCBCR_FORMAT_Y_U_V_444
43    VdpPictureInfoHEVC444 *info2 = &pic_ctx->info.hevc_444;
44#endif
45
46    const HEVCSPS *sps = h->ps.sps;
47    const HEVCPPS *pps = h->ps.pps;
48    const SliceHeader *sh = &h->sh;
49    const ScalingList *sl = pps->scaling_list_data_present_flag ?
50                            &pps->scaling_list : &sps->scaling_list;
51
52    /* init VdpPictureInfoHEVC */
53
54    /* SPS */
55    info->chroma_format_idc = sps->chroma_format_idc;
56    info->separate_colour_plane_flag = sps->separate_colour_plane_flag;
57    info->pic_width_in_luma_samples = sps->width;
58    info->pic_height_in_luma_samples = sps->height;
59    info->bit_depth_luma_minus8 = sps->bit_depth - 8;
60    info->bit_depth_chroma_minus8 = sps->bit_depth - 8;
61    info->log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_poc_lsb - 4;
62    /* Provide the value corresponding to the nuh_temporal_id of the frame
63       to be decoded. */
64    info->sps_max_dec_pic_buffering_minus1 = sps->temporal_layer[sps->max_sub_layers - 1].max_dec_pic_buffering - 1;
65    info->log2_min_luma_coding_block_size_minus3 = sps->log2_min_cb_size - 3;
66    info->log2_diff_max_min_luma_coding_block_size = sps->log2_diff_max_min_coding_block_size;
67    info->log2_min_transform_block_size_minus2 = sps->log2_min_tb_size - 2;
68    info->log2_diff_max_min_transform_block_size = sps->log2_max_trafo_size - sps->log2_min_tb_size;
69    info->max_transform_hierarchy_depth_inter = sps->max_transform_hierarchy_depth_inter;
70    info->max_transform_hierarchy_depth_intra = sps->max_transform_hierarchy_depth_intra;
71    info->scaling_list_enabled_flag = sps->scaling_list_enable_flag;
72    /* Scaling lists, in diagonal order, to be used for this frame. */
73    for (size_t i = 0; i < 6; i++) {
74        for (size_t j = 0; j < 16; j++) {
75            /* Scaling List for 4x4 quantization matrix,
76               indexed as ScalingList4x4[matrixId][i]. */
77            uint8_t pos = 4 * ff_hevc_diag_scan4x4_y[j] + ff_hevc_diag_scan4x4_x[j];
78            info->ScalingList4x4[i][j] = sl->sl[0][i][pos];
79        }
80        for (size_t j = 0; j < 64; j++) {
81            uint8_t pos = 8 * ff_hevc_diag_scan8x8_y[j] + ff_hevc_diag_scan8x8_x[j];
82            /* Scaling List for 8x8 quantization matrix,
83               indexed as ScalingList8x8[matrixId][i]. */
84            info->ScalingList8x8[i][j] = sl->sl[1][i][pos];
85            /* Scaling List for 16x16 quantization matrix,
86               indexed as ScalingList16x16[matrixId][i]. */
87            info->ScalingList16x16[i][j] = sl->sl[2][i][pos];
88            if (i < 2) {
89                /* Scaling List for 32x32 quantization matrix,
90                   indexed as ScalingList32x32[matrixId][i]. */
91                info->ScalingList32x32[i][j] = sl->sl[3][i * 3][pos];
92            }
93        }
94        /* Scaling List DC Coefficients for 16x16,
95           indexed as ScalingListDCCoeff16x16[matrixId]. */
96        info->ScalingListDCCoeff16x16[i] = sl->sl_dc[0][i];
97        if (i < 2) {
98            /* Scaling List DC Coefficients for 32x32,
99               indexed as ScalingListDCCoeff32x32[matrixId]. */
100            info->ScalingListDCCoeff32x32[i] = sl->sl_dc[1][i * 3];
101        }
102    }
103    info->amp_enabled_flag = sps->amp_enabled_flag;
104    info->sample_adaptive_offset_enabled_flag = sps->sao_enabled;
105    info->pcm_enabled_flag = sps->pcm_enabled_flag;
106    if (info->pcm_enabled_flag) {
107        /* Only needs to be set if pcm_enabled_flag is set. Ignored otherwise. */
108        info->pcm_sample_bit_depth_luma_minus1 = sps->pcm.bit_depth - 1;
109        /* Only needs to be set if pcm_enabled_flag is set. Ignored otherwise. */
110        info->pcm_sample_bit_depth_chroma_minus1 = sps->pcm.bit_depth_chroma - 1;
111        /* Only needs to be set if pcm_enabled_flag is set. Ignored otherwise. */
112        info->log2_min_pcm_luma_coding_block_size_minus3 = sps->pcm.log2_min_pcm_cb_size - 3;
113        /* Only needs to be set if pcm_enabled_flag is set. Ignored otherwise. */
114        info->log2_diff_max_min_pcm_luma_coding_block_size = sps->pcm.log2_max_pcm_cb_size - sps->pcm.log2_min_pcm_cb_size;
115        /* Only needs to be set if pcm_enabled_flag is set. Ignored otherwise. */
116        info->pcm_loop_filter_disabled_flag = sps->pcm.loop_filter_disable_flag;
117    }
118    /* Per spec, when zero, assume short_term_ref_pic_set_sps_flag
119       is also zero. */
120    info->num_short_term_ref_pic_sets = sps->nb_st_rps;
121    info->long_term_ref_pics_present_flag = sps->long_term_ref_pics_present_flag;
122    /* Only needed if long_term_ref_pics_present_flag is set. Ignored
123       otherwise. */
124    info->num_long_term_ref_pics_sps = sps->num_long_term_ref_pics_sps;
125    info->sps_temporal_mvp_enabled_flag = sps->sps_temporal_mvp_enabled_flag;
126    info->strong_intra_smoothing_enabled_flag = sps->sps_strong_intra_smoothing_enable_flag;
127
128    /* Copy the HEVC Picture Parameter Set bitstream fields. */
129    info->dependent_slice_segments_enabled_flag = pps->dependent_slice_segments_enabled_flag;
130    info->output_flag_present_flag = pps->output_flag_present_flag;
131    info->num_extra_slice_header_bits = pps->num_extra_slice_header_bits;
132    info->sign_data_hiding_enabled_flag = pps->sign_data_hiding_flag;
133    info->cabac_init_present_flag = pps->cabac_init_present_flag;
134    info->num_ref_idx_l0_default_active_minus1 = pps->num_ref_idx_l0_default_active - 1;
135    info->num_ref_idx_l1_default_active_minus1 = pps->num_ref_idx_l1_default_active - 1;
136    info->init_qp_minus26 = pps->pic_init_qp_minus26;
137    info->constrained_intra_pred_flag = pps->constrained_intra_pred_flag;
138    info->transform_skip_enabled_flag = pps->transform_skip_enabled_flag;
139    info->cu_qp_delta_enabled_flag = pps->cu_qp_delta_enabled_flag;
140    /* Only needed if cu_qp_delta_enabled_flag is set. Ignored otherwise. */
141    info->diff_cu_qp_delta_depth = pps->diff_cu_qp_delta_depth;
142    info->pps_cb_qp_offset = pps->cb_qp_offset;
143    info->pps_cr_qp_offset = pps->cr_qp_offset;
144    info->pps_slice_chroma_qp_offsets_present_flag = pps->pic_slice_level_chroma_qp_offsets_present_flag;
145    info->weighted_pred_flag = pps->weighted_pred_flag;
146    info->weighted_bipred_flag = pps->weighted_bipred_flag;
147    info->transquant_bypass_enabled_flag = pps->transquant_bypass_enable_flag;
148    info->tiles_enabled_flag = pps->tiles_enabled_flag;
149    info->entropy_coding_sync_enabled_flag = pps->entropy_coding_sync_enabled_flag;
150    if (info->tiles_enabled_flag) {
151        /* Only valid if tiles_enabled_flag is set. Ignored otherwise. */
152        info->num_tile_columns_minus1 = pps->num_tile_columns - 1;
153        /* Only valid if tiles_enabled_flag is set. Ignored otherwise. */
154        info->num_tile_rows_minus1 = pps->num_tile_rows - 1;
155        /* Only valid if tiles_enabled_flag is set. Ignored otherwise. */
156        info->uniform_spacing_flag = pps->uniform_spacing_flag;
157        /* Only need to set 0..num_tile_columns_minus1. The struct
158           definition reserves up to the maximum of 20. Invalid values are
159           ignored. */
160        for (ssize_t i = 0; i < pps->num_tile_columns; i++) {
161            info->column_width_minus1[i] = pps->column_width[i] - 1;
162        }
163        /* Only need to set 0..num_tile_rows_minus1. The struct
164           definition reserves up to the maximum of 22. Invalid values are
165           ignored.*/
166        for (ssize_t i = 0; i < pps->num_tile_rows; i++) {
167            info->row_height_minus1[i] = pps->row_height[i] - 1;
168        }
169        /* Only needed if tiles_enabled_flag is set. Invalid values are
170           ignored. */
171        info->loop_filter_across_tiles_enabled_flag = pps->loop_filter_across_tiles_enabled_flag;
172    }
173    info->pps_loop_filter_across_slices_enabled_flag = pps->seq_loop_filter_across_slices_enabled_flag;
174    info->deblocking_filter_control_present_flag = pps->deblocking_filter_control_present_flag;
175    /* Only valid if deblocking_filter_control_present_flag is set. Ignored
176       otherwise. */
177    info->deblocking_filter_override_enabled_flag = pps->deblocking_filter_override_enabled_flag;
178    /* Only valid if deblocking_filter_control_present_flag is set. Ignored
179       otherwise. */
180    info->pps_deblocking_filter_disabled_flag = pps->disable_dbf;
181    /* Only valid if deblocking_filter_control_present_flag is set and
182       pps_deblocking_filter_disabled_flag is not set. Ignored otherwise.*/
183    info->pps_beta_offset_div2 = pps->beta_offset / 2;
184    /* Only valid if deblocking_filter_control_present_flag is set and
185       pps_deblocking_filter_disabled_flag is not set. Ignored otherwise. */
186    info->pps_tc_offset_div2 = pps->tc_offset / 2;
187    info->lists_modification_present_flag = pps->lists_modification_present_flag;
188    info->log2_parallel_merge_level_minus2 = pps->log2_parallel_merge_level - 2;
189    info->slice_segment_header_extension_present_flag = pps->slice_header_extension_present_flag;
190
191    /* Set to 1 if nal_unit_type is equal to IDR_W_RADL or IDR_N_LP.
192       Set to zero otherwise. */
193    info->IDRPicFlag = IS_IDR(h);
194    /* Set to 1 if nal_unit_type in the range of BLA_W_LP to
195       RSV_IRAP_VCL23, inclusive. Set to zero otherwise.*/
196    info->RAPPicFlag = IS_IRAP(h);
197    /* See section 7.4.7.1 of the specification. */
198    info->CurrRpsIdx = sps->nb_st_rps;
199    if (sh->short_term_ref_pic_set_sps_flag == 1) {
200        for (size_t i = 0; i < sps->nb_st_rps; i++) {
201            if (sh->short_term_rps == &sps->st_rps[i]) {
202                info->CurrRpsIdx = i;
203                break;
204            }
205        }
206    }
207    /* See section 7.4.7.2 of the specification. */
208    info->NumPocTotalCurr = ff_hevc_frame_nb_refs(h);
209    if (sh->short_term_ref_pic_set_sps_flag == 0 && sh->short_term_rps) {
210        /* Corresponds to specification field, NumDeltaPocs[RefRpsIdx].
211           Only applicable when short_term_ref_pic_set_sps_flag == 0.
212           Implementations will ignore this value in other cases. See 7.4.8. */
213        info->NumDeltaPocsOfRefRpsIdx = sh->short_term_rps->rps_idx_num_delta_pocs;
214    }
215    /* Section 7.6.3.1 of the H.265/HEVC Specification defines the syntax of
216       the slice_segment_header. This header contains information that
217       some VDPAU implementations may choose to skip. The VDPAU API
218       requires client applications to track the number of bits used in the
219       slice header for structures associated with short term and long term
220       reference pictures. First, VDPAU requires the number of bits used by
221       the short_term_ref_pic_set array in the slice_segment_header. */
222    info->NumShortTermPictureSliceHeaderBits = sh->short_term_ref_pic_set_size;
223    /* Second, VDPAU requires the number of bits used for long term reference
224       pictures in the slice_segment_header. This is equal to the number
225       of bits used for the contents of the block beginning with
226       "if(long_term_ref_pics_present_flag)". */
227    info->NumLongTermPictureSliceHeaderBits = sh->long_term_ref_pic_set_size;
228
229    /* The value of PicOrderCntVal of the picture in the access unit
230       containing the SEI message. The picture being decoded. */
231    info->CurrPicOrderCntVal = h->poc;
232
233    /* Slice Decoding Process - Reference Picture Sets */
234    for (size_t i = 0; i < 16; i++) {
235        info->RefPics[i] = VDP_INVALID_HANDLE;
236        info->PicOrderCntVal[i] = 0;
237        info->IsLongTerm[i] = 0;
238    }
239    for (size_t i = 0, j = 0; i < FF_ARRAY_ELEMS(h->DPB); i++) {
240        const HEVCFrame *frame = &h->DPB[i];
241        if (frame != h->ref && (frame->flags & (HEVC_FRAME_FLAG_LONG_REF |
242                                                HEVC_FRAME_FLAG_SHORT_REF))) {
243            if (j > 15) {
244                av_log(avctx, AV_LOG_WARNING,
245                     "VDPAU only supports up to 16 references in the DPB. "
246                     "This frame may not be decoded correctly.\n");
247                break;
248            }
249            /* Array of video reference surfaces.
250               Set any unused positions to VDP_INVALID_HANDLE. */
251            info->RefPics[j] = ff_vdpau_get_surface_id(frame->frame);
252            /* Array of picture order counts. These correspond to positions
253               in the RefPics array. */
254            info->PicOrderCntVal[j] = frame->poc;
255            /* Array used to specify whether a particular RefPic is
256               a long term reference. A value of "1" indicates a long-term
257               reference. */
258            // XXX: Setting this caused glitches in the nvidia implementation
259            // Always setting it to zero, produces correct results
260            //info->IsLongTerm[j] = frame->flags & HEVC_FRAME_FLAG_LONG_REF;
261            info->IsLongTerm[j] = 0;
262            j++;
263        }
264    }
265    /* Copy of specification field, see Section 8.3.2 of the
266       H.265/HEVC Specification. */
267    info->NumPocStCurrBefore = h->rps[ST_CURR_BEF].nb_refs;
268    if (info->NumPocStCurrBefore > 8) {
269        av_log(avctx, AV_LOG_WARNING,
270             "VDPAU only supports up to 8 references in StCurrBefore. "
271             "This frame may not be decoded correctly.\n");
272        info->NumPocStCurrBefore = 8;
273    }
274    /* Copy of specification field, see Section 8.3.2 of the
275       H.265/HEVC Specification. */
276    info->NumPocStCurrAfter = h->rps[ST_CURR_AFT].nb_refs;
277    if (info->NumPocStCurrAfter > 8) {
278        av_log(avctx, AV_LOG_WARNING,
279             "VDPAU only supports up to 8 references in StCurrAfter. "
280             "This frame may not be decoded correctly.\n");
281        info->NumPocStCurrAfter = 8;
282    }
283    /* Copy of specification field, see Section 8.3.2 of the
284       H.265/HEVC Specification. */
285    info->NumPocLtCurr = h->rps[LT_CURR].nb_refs;
286    if (info->NumPocLtCurr > 8) {
287        av_log(avctx, AV_LOG_WARNING,
288             "VDPAU only supports up to 8 references in LtCurr. "
289             "This frame may not be decoded correctly.\n");
290        info->NumPocLtCurr = 8;
291    }
292    /* Reference Picture Set list, one of the short-term RPS. These
293       correspond to positions in the RefPics array. */
294    for (ssize_t i = 0, j = 0; i < h->rps[ST_CURR_BEF].nb_refs; i++) {
295        HEVCFrame *frame = h->rps[ST_CURR_BEF].ref[i];
296        if (frame) {
297            uint8_t found = 0;
298            uintptr_t id = ff_vdpau_get_surface_id(frame->frame);
299            for (size_t k = 0; k < 16; k++) {
300                if (id == info->RefPics[k]) {
301                    info->RefPicSetStCurrBefore[j] = k;
302                    j++;
303                    found = 1;
304                    break;
305                }
306            }
307            if (!found) {
308                av_log(avctx, AV_LOG_WARNING, "missing surface: %p\n",
309                       (void *)id);
310            }
311        } else {
312            av_log(avctx, AV_LOG_WARNING, "missing STR Before frame: %zd\n", i);
313        }
314    }
315    /* Reference Picture Set list, one of the short-term RPS. These
316       correspond to positions in the RefPics array. */
317    for (ssize_t i = 0, j = 0; i < h->rps[ST_CURR_AFT].nb_refs; i++) {
318        HEVCFrame *frame = h->rps[ST_CURR_AFT].ref[i];
319        if (frame) {
320            uint8_t found = 0;
321            uintptr_t id = ff_vdpau_get_surface_id(frame->frame);
322            for (size_t k = 0; k < 16; k++) {
323                if (id == info->RefPics[k]) {
324                    info->RefPicSetStCurrAfter[j] = k;
325                    j++;
326                    found = 1;
327                    break;
328                }
329            }
330            if (!found) {
331                av_log(avctx, AV_LOG_WARNING, "missing surface: %p\n",
332                       (void *)id);
333            }
334        } else {
335            av_log(avctx, AV_LOG_WARNING, "missing STR After frame: %zd\n", i);
336        }
337    }
338    /* Reference Picture Set list, one of the long-term RPS. These
339       correspond to positions in the RefPics array. */
340    for (ssize_t i = 0, j = 0; i < h->rps[LT_CURR].nb_refs; i++) {
341        HEVCFrame *frame = h->rps[LT_CURR].ref[i];
342        if (frame) {
343            uint8_t found = 0;
344            uintptr_t id = ff_vdpau_get_surface_id(frame->frame);
345            for (size_t k = 0; k < 16; k++) {
346                if (id == info->RefPics[k]) {
347                    info->RefPicSetLtCurr[j] = k;
348                    j++;
349                    found = 1;
350                    break;
351                }
352            }
353            if (!found) {
354                av_log(avctx, AV_LOG_WARNING, "missing surface: %p\n",
355                       (void *)id);
356            }
357        } else {
358            av_log(avctx, AV_LOG_WARNING, "missing LTR frame: %zd\n", i);
359        }
360    }
361
362#ifdef VDP_YCBCR_FORMAT_Y_U_V_444
363    if (sps->sps_range_extension_flag) {
364        info2->sps_range_extension_flag             = 1;
365        info2->transformSkipRotationEnableFlag      = sps->transform_skip_rotation_enabled_flag;
366        info2->transformSkipContextEnableFlag       = sps->transform_skip_context_enabled_flag;
367        info2->implicitRdpcmEnableFlag              = sps->implicit_rdpcm_enabled_flag;
368        info2->explicitRdpcmEnableFlag              = sps->explicit_rdpcm_enabled_flag;
369        info2->extendedPrecisionProcessingFlag      = sps->extended_precision_processing_flag;
370        info2->intraSmoothingDisabledFlag           = sps->intra_smoothing_disabled_flag;
371        info2->highPrecisionOffsetsEnableFlag       = sps->high_precision_offsets_enabled_flag;
372        info2->persistentRiceAdaptationEnableFlag   = sps->persistent_rice_adaptation_enabled_flag;
373        info2->cabacBypassAlignmentEnableFlag       = sps->cabac_bypass_alignment_enabled_flag;
374    } else {
375        info2->sps_range_extension_flag = 0;
376    }
377    if (pps->pps_range_extensions_flag) {
378        info2->pps_range_extension_flag             = 1;
379        info2->log2MaxTransformSkipSize             = pps->log2_max_transform_skip_block_size;
380        info2->crossComponentPredictionEnableFlag   = pps->cross_component_prediction_enabled_flag;
381        info2->chromaQpAdjustmentEnableFlag         = pps->chroma_qp_offset_list_enabled_flag;
382        info2->diffCuChromaQpAdjustmentDepth        = pps->diff_cu_chroma_qp_offset_depth;
383        info2->chromaQpAdjustmentTableSize          = pps->chroma_qp_offset_list_len_minus1 + 1;
384        info2->log2SaoOffsetScaleLuma               = pps->log2_sao_offset_scale_luma;
385        info2->log2SaoOffsetScaleChroma             = pps->log2_sao_offset_scale_chroma;
386        for (ssize_t i = 0; i < info2->chromaQpAdjustmentTableSize; i++)
387        {
388            info2->cb_qp_adjustment[i] = pps->cb_qp_offset_list[i];
389            info2->cr_qp_adjustment[i] = pps->cr_qp_offset_list[i];
390        }
391
392    } else {
393        info2->pps_range_extension_flag = 0;
394    }
395#endif
396
397    return ff_vdpau_common_start_frame(pic_ctx, buffer, size);
398}
399
400static const uint8_t start_code_prefix[3] = { 0x00, 0x00, 0x01 };
401
402static int vdpau_hevc_decode_slice(AVCodecContext *avctx,
403                                   const uint8_t *buffer, uint32_t size)
404{
405    HEVCContext *h = avctx->priv_data;
406    struct vdpau_picture_context *pic_ctx = h->ref->hwaccel_picture_private;
407    int val;
408
409    val = ff_vdpau_add_buffer(pic_ctx, start_code_prefix, 3);
410    if (val)
411        return val;
412
413    val = ff_vdpau_add_buffer(pic_ctx, buffer, size);
414    if (val)
415        return val;
416
417    return 0;
418}
419
420static int vdpau_hevc_end_frame(AVCodecContext *avctx)
421{
422    HEVCContext *h = avctx->priv_data;
423    struct vdpau_picture_context *pic_ctx = h->ref->hwaccel_picture_private;
424    int val;
425
426    val = ff_vdpau_common_end_frame(avctx, h->ref->frame, pic_ctx);
427    if (val < 0)
428        return val;
429
430    return 0;
431}
432
433
434
435static int ptl_convert(const PTLCommon *general_ptl, H265RawProfileTierLevel *h265_raw_ptl)
436{
437    h265_raw_ptl->general_profile_space = general_ptl->profile_space;
438    h265_raw_ptl->general_tier_flag     = general_ptl->tier_flag;
439    h265_raw_ptl->general_profile_idc   = general_ptl->profile_idc;
440
441    memcpy(h265_raw_ptl->general_profile_compatibility_flag,
442                                  general_ptl->profile_compatibility_flag, 32 * sizeof(uint8_t));
443
444#define copy_field(name) h265_raw_ptl->general_ ## name = general_ptl->name
445    copy_field(progressive_source_flag);
446    copy_field(interlaced_source_flag);
447    copy_field(non_packed_constraint_flag);
448    copy_field(frame_only_constraint_flag);
449    copy_field(max_12bit_constraint_flag);
450    copy_field(max_10bit_constraint_flag);
451    copy_field(max_8bit_constraint_flag);
452    copy_field(max_422chroma_constraint_flag);
453    copy_field(max_420chroma_constraint_flag);
454    copy_field(max_monochrome_constraint_flag);
455    copy_field(intra_constraint_flag);
456    copy_field(one_picture_only_constraint_flag);
457    copy_field(lower_bit_rate_constraint_flag);
458    copy_field(max_14bit_constraint_flag);
459    copy_field(inbld_flag);
460    copy_field(level_idc);
461#undef copy_field
462
463    return 0;
464}
465
466/*
467 * Find exact vdpau_profile for HEVC Range Extension
468 */
469static int vdpau_hevc_parse_rext_profile(AVCodecContext *avctx, VdpDecoderProfile *vdp_profile)
470{
471    const HEVCContext *h = avctx->priv_data;
472    const HEVCSPS *sps = h->ps.sps;
473    const PTL *ptl = &sps->ptl;
474    const PTLCommon *general_ptl = &ptl->general_ptl;
475    const H265ProfileDescriptor *profile;
476    H265RawProfileTierLevel h265_raw_ptl = {0};
477
478    /* convert PTLCommon to H265RawProfileTierLevel */
479    ptl_convert(general_ptl, &h265_raw_ptl);
480
481    profile = ff_h265_get_profile(&h265_raw_ptl);
482    if (!profile) {
483        av_log(avctx, AV_LOG_WARNING, "HEVC profile is not found.\n");
484        if (avctx->hwaccel_flags & AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH) {
485            // Default to selecting Main profile if profile mismatch is allowed
486            *vdp_profile = VDP_DECODER_PROFILE_HEVC_MAIN;
487            return 0;
488        } else
489            return AVERROR(ENOTSUP);
490    }
491
492    if (!strcmp(profile->name, "Main 12") ||
493        !strcmp(profile->name, "Main 12 Intra"))
494        *vdp_profile = VDP_DECODER_PROFILE_HEVC_MAIN_12;
495#ifdef VDP_DECODER_PROFILE_HEVC_MAIN_444
496    else if (!strcmp(profile->name, "Main 4:4:4") ||
497             !strcmp(profile->name, "Main 4:4:4 Intra"))
498        *vdp_profile = VDP_DECODER_PROFILE_HEVC_MAIN_444;
499#endif
500#ifdef VDP_DECODER_PROFILE_HEVC_MAIN_444_10
501    else if (!strcmp(profile->name, "Main 4:4:4 10") ||
502             !strcmp(profile->name, "Main 4:4:4 10 Intra"))
503        *vdp_profile = VDP_DECODER_PROFILE_HEVC_MAIN_444_10;
504    else if (!strcmp(profile->name, "Main 4:4:4 12") ||
505             !strcmp(profile->name, "Main 4:4:4 12 Intra"))
506        *vdp_profile = VDP_DECODER_PROFILE_HEVC_MAIN_444_12;
507#endif
508    else
509        return AVERROR(ENOTSUP);
510
511    return 0;
512}
513
514
515static int vdpau_hevc_init(AVCodecContext *avctx)
516{
517    VdpDecoderProfile profile;
518    uint32_t level = avctx->level;
519    int ret;
520
521    switch (avctx->profile) {
522    case FF_PROFILE_HEVC_MAIN:
523        profile = VDP_DECODER_PROFILE_HEVC_MAIN;
524        break;
525    case FF_PROFILE_HEVC_MAIN_10:
526        profile = VDP_DECODER_PROFILE_HEVC_MAIN_10;
527        break;
528    case FF_PROFILE_HEVC_MAIN_STILL_PICTURE:
529        profile = VDP_DECODER_PROFILE_HEVC_MAIN_STILL;
530        break;
531    case FF_PROFILE_HEVC_REXT:
532        ret = vdpau_hevc_parse_rext_profile(avctx, &profile);
533        if (ret)
534            return AVERROR(ENOTSUP);
535        break;
536    default:
537        return AVERROR(ENOTSUP);
538    }
539
540    return ff_vdpau_common_init(avctx, profile, level);
541}
542
543const AVHWAccel ff_hevc_vdpau_hwaccel = {
544    .name           = "hevc_vdpau",
545    .type           = AVMEDIA_TYPE_VIDEO,
546    .id             = AV_CODEC_ID_HEVC,
547    .pix_fmt        = AV_PIX_FMT_VDPAU,
548    .start_frame    = vdpau_hevc_start_frame,
549    .end_frame      = vdpau_hevc_end_frame,
550    .decode_slice   = vdpau_hevc_decode_slice,
551    .frame_priv_data_size = sizeof(struct vdpau_picture_context),
552    .init           = vdpau_hevc_init,
553    .uninit         = ff_vdpau_common_uninit,
554    .frame_params   = ff_vdpau_common_frame_params,
555    .priv_data_size = sizeof(VDPAUContext),
556    .caps_internal  = HWACCEL_CAP_ASYNC_SAFE,
557};
558