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