• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
vdpau_hevc_start_frame(AVCodecContext * avctx,const uint8_t * buffer,uint32_t size)34 static 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 
400 static const uint8_t start_code_prefix[3] = { 0x00, 0x00, 0x01 };
401 
vdpau_hevc_decode_slice(AVCodecContext * avctx,const uint8_t * buffer,uint32_t size)402 static 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 
vdpau_hevc_end_frame(AVCodecContext * avctx)420 static 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 
ptl_convert(const PTLCommon * general_ptl,H265RawProfileTierLevel * h265_raw_ptl)435 static 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  */
vdpau_hevc_parse_rext_profile(AVCodecContext * avctx,VdpDecoderProfile * vdp_profile)469 static 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 
vdpau_hevc_init(AVCodecContext * avctx)515 static 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 
543 const 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