| /* | |
| * This file is part of FFmpeg. | |
| * | |
| * FFmpeg is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Lesser General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * | |
| * FFmpeg is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with FFmpeg; if not, write to the Free Software | |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
| */ | |
| #include "hevcdec.h" | |
| #include "hevc_data.h" | |
| #include "hevc_ps.h" | |
| #include "vulkan_decode.h" | |
| const FFVulkanDecodeDescriptor ff_vk_dec_hevc_desc = { | |
| .codec_id = AV_CODEC_ID_HEVC, | |
| .decode_extension = FF_VK_EXT_VIDEO_DECODE_H265, | |
| .decode_op = VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR, | |
| .ext_props = { | |
| .extensionName = VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_EXTENSION_NAME, | |
| .specVersion = VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_SPEC_VERSION, | |
| }, | |
| }; | |
| typedef struct HEVCHeaderSPS { | |
| StdVideoH265ScalingLists scaling; | |
| StdVideoH265HrdParameters vui_header; | |
| StdVideoH265SequenceParameterSetVui vui; | |
| StdVideoH265ProfileTierLevel ptl; | |
| StdVideoH265DecPicBufMgr dpbm; | |
| StdVideoH265PredictorPaletteEntries pal; | |
| StdVideoH265SubLayerHrdParameters nal_hdr[HEVC_MAX_SUB_LAYERS]; | |
| StdVideoH265SubLayerHrdParameters vcl_hdr[HEVC_MAX_SUB_LAYERS]; | |
| StdVideoH265ShortTermRefPicSet str[HEVC_MAX_SHORT_TERM_REF_PIC_SETS]; | |
| StdVideoH265LongTermRefPicsSps ltr; | |
| } HEVCHeaderSPS; | |
| typedef struct HEVCHeaderPPS { | |
| StdVideoH265ScalingLists scaling; | |
| StdVideoH265PredictorPaletteEntries pal; | |
| } HEVCHeaderPPS; | |
| typedef struct HEVCHeaderVPSSet { | |
| StdVideoH265SubLayerHrdParameters nal_hdr[HEVC_MAX_SUB_LAYERS]; | |
| StdVideoH265SubLayerHrdParameters vcl_hdr[HEVC_MAX_SUB_LAYERS]; | |
| } HEVCHeaderVPSSet; | |
| typedef struct HEVCHeaderVPS { | |
| StdVideoH265ProfileTierLevel ptl; | |
| StdVideoH265DecPicBufMgr dpbm; | |
| StdVideoH265HrdParameters hdr[HEVC_MAX_LAYER_SETS]; | |
| HEVCHeaderVPSSet *sls; | |
| } HEVCHeaderVPS; | |
| typedef struct HEVCHeaderSet { | |
| StdVideoH265SequenceParameterSet sps[HEVC_MAX_SPS_COUNT]; | |
| HEVCHeaderSPS hsps[HEVC_MAX_SPS_COUNT]; | |
| StdVideoH265PictureParameterSet pps[HEVC_MAX_PPS_COUNT]; | |
| HEVCHeaderPPS hpps[HEVC_MAX_PPS_COUNT]; | |
| StdVideoH265VideoParameterSet vps[HEVC_MAX_PPS_COUNT]; | |
| HEVCHeaderVPS *hvps; | |
| } HEVCHeaderSet; | |
| static int alloc_hevc_header_structs(FFVulkanDecodeContext *s, | |
| int nb_vps, | |
| const int vps_list_idx[HEVC_MAX_VPS_COUNT], | |
| const HEVCVPS * const vps_list[HEVC_MAX_VPS_COUNT]) | |
| { | |
| uint8_t *data_ptr; | |
| HEVCHeaderSet *hdr; | |
| size_t buf_size = sizeof(HEVCHeaderSet) + nb_vps*sizeof(HEVCHeaderVPS); | |
| for (int i = 0; i < nb_vps; i++) { | |
| const HEVCVPS *vps = vps_list[vps_list_idx[i]]; | |
| buf_size += sizeof(HEVCHeaderVPSSet)*vps->vps_num_hrd_parameters; | |
| } | |
| if (buf_size > s->hevc_headers_size) { | |
| av_freep(&s->hevc_headers); | |
| s->hevc_headers_size = 0; | |
| s->hevc_headers = av_mallocz(buf_size); | |
| if (!s->hevc_headers) | |
| return AVERROR(ENOMEM); | |
| s->hevc_headers_size = buf_size; | |
| } | |
| /* Setup struct pointers */ | |
| hdr = s->hevc_headers; | |
| data_ptr = (uint8_t *)hdr; | |
| hdr->hvps = (HEVCHeaderVPS *)(data_ptr + sizeof(HEVCHeaderSet)); | |
| data_ptr += sizeof(HEVCHeaderSet) + nb_vps*sizeof(HEVCHeaderVPS); | |
| for (int i = 0; i < nb_vps; i++) { | |
| const HEVCVPS *vps = vps_list[vps_list_idx[i]]; | |
| hdr->hvps[i].sls = (HEVCHeaderVPSSet *)data_ptr; | |
| data_ptr += sizeof(HEVCHeaderVPSSet)*vps->vps_num_hrd_parameters; | |
| } | |
| return 0; | |
| } | |
| typedef struct HEVCVulkanDecodePicture { | |
| FFVulkanDecodePicture vp; | |
| /* Current picture */ | |
| StdVideoDecodeH265ReferenceInfo h265_ref; | |
| VkVideoDecodeH265DpbSlotInfoKHR vkh265_ref; | |
| /* Picture refs */ | |
| HEVCFrame *ref_src [HEVC_MAX_REFS]; | |
| StdVideoDecodeH265ReferenceInfo h265_refs [HEVC_MAX_REFS]; | |
| VkVideoDecodeH265DpbSlotInfoKHR vkh265_refs[HEVC_MAX_REFS]; | |
| /* Current picture (contd.) */ | |
| StdVideoDecodeH265PictureInfo h265pic; | |
| VkVideoDecodeH265PictureInfoKHR h265_pic_info; | |
| } HEVCVulkanDecodePicture; | |
| static int vk_hevc_fill_pict(AVCodecContext *avctx, HEVCFrame **ref_src, | |
| VkVideoReferenceSlotInfoKHR *ref_slot, /* Main structure */ | |
| VkVideoPictureResourceInfoKHR *ref, /* Goes in ^ */ | |
| VkVideoDecodeH265DpbSlotInfoKHR *vkh265_ref, /* Goes in ^ */ | |
| StdVideoDecodeH265ReferenceInfo *h265_ref, /* Goes in ^ */ | |
| HEVCFrame *pic, int is_current, int pic_id) | |
| { | |
| FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; | |
| HEVCVulkanDecodePicture *hp = pic->hwaccel_picture_private; | |
| FFVulkanDecodePicture *vkpic = &hp->vp; | |
| int err = ff_vk_decode_prepare_frame(dec, pic->frame, vkpic, is_current, | |
| dec->dedicated_dpb); | |
| if (err < 0) | |
| return err; | |
| *h265_ref = (StdVideoDecodeH265ReferenceInfo) { | |
| .flags = (StdVideoDecodeH265ReferenceInfoFlags) { | |
| .used_for_long_term_reference = pic->flags & HEVC_FRAME_FLAG_LONG_REF, | |
| .unused_for_reference = 0, | |
| }, | |
| .PicOrderCntVal = pic->poc, | |
| }; | |
| *vkh265_ref = (VkVideoDecodeH265DpbSlotInfoKHR) { | |
| .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_DPB_SLOT_INFO_KHR, | |
| .pStdReferenceInfo = h265_ref, | |
| }; | |
| *ref = (VkVideoPictureResourceInfoKHR) { | |
| .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR, | |
| .codedOffset = (VkOffset2D){ 0, 0 }, | |
| .codedExtent = (VkExtent2D){ pic->frame->width, pic->frame->height }, | |
| .baseArrayLayer = dec->layered_dpb ? pic_id : 0, | |
| .imageViewBinding = vkpic->img_view_ref, | |
| }; | |
| *ref_slot = (VkVideoReferenceSlotInfoKHR) { | |
| .sType = VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR, | |
| .pNext = vkh265_ref, | |
| .slotIndex = pic_id, | |
| .pPictureResource = ref, | |
| }; | |
| if (ref_src) | |
| *ref_src = pic; | |
| return 0; | |
| } | |
| static StdVideoH265LevelIdc convert_to_vk_level_idc(int level_idc) | |
| { | |
| switch (level_idc) { | |
| case 10: return STD_VIDEO_H265_LEVEL_IDC_1_0; | |
| case 20: return STD_VIDEO_H265_LEVEL_IDC_2_0; | |
| case 21: return STD_VIDEO_H265_LEVEL_IDC_2_1; | |
| case 30: return STD_VIDEO_H265_LEVEL_IDC_3_0; | |
| case 31: return STD_VIDEO_H265_LEVEL_IDC_3_1; | |
| case 40: return STD_VIDEO_H265_LEVEL_IDC_4_0; | |
| case 41: return STD_VIDEO_H265_LEVEL_IDC_4_1; | |
| case 50: return STD_VIDEO_H265_LEVEL_IDC_5_0; | |
| case 51: return STD_VIDEO_H265_LEVEL_IDC_5_1; | |
| case 60: return STD_VIDEO_H265_LEVEL_IDC_6_0; | |
| case 61: return STD_VIDEO_H265_LEVEL_IDC_6_1; | |
| default: | |
| case 62: return STD_VIDEO_H265_LEVEL_IDC_6_2; | |
| } | |
| } | |
| static void copy_scaling_list(const ScalingList *sl, StdVideoH265ScalingLists *vksl) | |
| { | |
| for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_4X4_NUM_LISTS; i++) { | |
| for (int j = 0; j < STD_VIDEO_H265_SCALING_LIST_4X4_NUM_ELEMENTS; j++) { | |
| uint8_t pos = 4 * ff_hevc_diag_scan4x4_y[j] + ff_hevc_diag_scan4x4_x[j]; | |
| vksl->ScalingList4x4[i][j] = sl->sl[0][i][pos]; | |
| } | |
| } | |
| for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_8X8_NUM_LISTS; i++) { | |
| for (int j = 0; j < STD_VIDEO_H265_SCALING_LIST_8X8_NUM_ELEMENTS; j++) { | |
| uint8_t pos = 8 * ff_hevc_diag_scan8x8_y[j] + ff_hevc_diag_scan8x8_x[j]; | |
| vksl->ScalingList8x8[i][j] = sl->sl[1][i][pos]; | |
| } | |
| } | |
| for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS; i++) { | |
| for (int j = 0; j < STD_VIDEO_H265_SCALING_LIST_16X16_NUM_ELEMENTS; j++) { | |
| uint8_t pos = 8 * ff_hevc_diag_scan8x8_y[j] + ff_hevc_diag_scan8x8_x[j]; | |
| vksl->ScalingList16x16[i][j] = sl->sl[2][i][pos]; | |
| } | |
| } | |
| for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS; i++) { | |
| for (int j = 0; j < STD_VIDEO_H265_SCALING_LIST_32X32_NUM_ELEMENTS; j++) { | |
| uint8_t pos = 8 * ff_hevc_diag_scan8x8_y[j] + ff_hevc_diag_scan8x8_x[j]; | |
| vksl->ScalingList32x32[i][j] = sl->sl[3][i * 3][pos]; | |
| } | |
| } | |
| memcpy(vksl->ScalingListDCCoef16x16, sl->sl_dc[0], | |
| STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS * sizeof(*vksl->ScalingListDCCoef16x16)); | |
| for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS; i++) | |
| vksl->ScalingListDCCoef32x32[i] = sl->sl_dc[1][i * 3]; | |
| } | |
| static void set_sps(const HEVCSPS *sps, int sps_idx, | |
| StdVideoH265ScalingLists *vksps_scaling, | |
| StdVideoH265HrdParameters *vksps_vui_header, | |
| StdVideoH265SequenceParameterSetVui *vksps_vui, | |
| StdVideoH265SequenceParameterSet *vksps, | |
| StdVideoH265SubLayerHrdParameters *slhdrnal, | |
| StdVideoH265SubLayerHrdParameters *slhdrvcl, | |
| StdVideoH265ProfileTierLevel *ptl, | |
| StdVideoH265DecPicBufMgr *dpbm, | |
| StdVideoH265PredictorPaletteEntries *pal, | |
| StdVideoH265ShortTermRefPicSet *str, | |
| StdVideoH265LongTermRefPicsSps *ltr) | |
| { | |
| copy_scaling_list(&sps->scaling_list, vksps_scaling); | |
| *vksps_vui_header = (StdVideoH265HrdParameters) { | |
| .flags = (StdVideoH265HrdFlags) { | |
| .nal_hrd_parameters_present_flag = sps->hdr.nal_hrd_parameters_present_flag, | |
| .vcl_hrd_parameters_present_flag = sps->hdr.vcl_hrd_parameters_present_flag, | |
| .sub_pic_hrd_params_present_flag = sps->hdr.sub_pic_hrd_params_present_flag, | |
| .sub_pic_cpb_params_in_pic_timing_sei_flag = sps->hdr.sub_pic_cpb_params_in_pic_timing_sei_flag, | |
| .fixed_pic_rate_general_flag = sps->hdr.flags.fixed_pic_rate_general_flag, | |
| .fixed_pic_rate_within_cvs_flag = sps->hdr.flags.fixed_pic_rate_within_cvs_flag, | |
| .low_delay_hrd_flag = sps->hdr.flags.low_delay_hrd_flag, | |
| }, | |
| .tick_divisor_minus2 = sps->hdr.tick_divisor_minus2, | |
| .du_cpb_removal_delay_increment_length_minus1 = sps->hdr.du_cpb_removal_delay_increment_length_minus1, | |
| .dpb_output_delay_du_length_minus1 = sps->hdr.dpb_output_delay_du_length_minus1, | |
| .bit_rate_scale = sps->hdr.bit_rate_scale, | |
| .cpb_size_scale = sps->hdr.cpb_size_scale, | |
| .cpb_size_du_scale = sps->hdr.cpb_size_du_scale, | |
| .initial_cpb_removal_delay_length_minus1 = sps->hdr.initial_cpb_removal_delay_length_minus1, | |
| .au_cpb_removal_delay_length_minus1 = sps->hdr.au_cpb_removal_delay_length_minus1, | |
| .dpb_output_delay_length_minus1 = sps->hdr.dpb_output_delay_length_minus1, | |
| /* Reserved - 3*16 bits */ | |
| .pSubLayerHrdParametersNal = slhdrnal, | |
| .pSubLayerHrdParametersVcl = slhdrvcl, | |
| }; | |
| memcpy(vksps_vui_header->cpb_cnt_minus1, sps->hdr.cpb_cnt_minus1, | |
| STD_VIDEO_H265_SUBLAYERS_LIST_SIZE*sizeof(*vksps_vui_header->cpb_cnt_minus1)); | |
| memcpy(vksps_vui_header->elemental_duration_in_tc_minus1, sps->hdr.elemental_duration_in_tc_minus1, | |
| STD_VIDEO_H265_SUBLAYERS_LIST_SIZE*sizeof(*vksps_vui_header->elemental_duration_in_tc_minus1)); | |
| memcpy(slhdrnal, sps->hdr.nal_params, HEVC_MAX_SUB_LAYERS*sizeof(*slhdrnal)); | |
| memcpy(slhdrvcl, sps->hdr.vcl_params, HEVC_MAX_SUB_LAYERS*sizeof(*slhdrvcl)); | |
| *vksps_vui = (StdVideoH265SequenceParameterSetVui) { | |
| .flags = (StdVideoH265SpsVuiFlags) { | |
| .aspect_ratio_info_present_flag = sps->vui.common.aspect_ratio_info_present_flag, | |
| .overscan_info_present_flag = sps->vui.common.overscan_info_present_flag, | |
| .overscan_appropriate_flag = sps->vui.common.overscan_appropriate_flag, | |
| .video_signal_type_present_flag = sps->vui.common.video_signal_type_present_flag, | |
| .video_full_range_flag = sps->vui.common.video_full_range_flag, | |
| .colour_description_present_flag = sps->vui.common.colour_description_present_flag, | |
| .chroma_loc_info_present_flag = sps->vui.common.chroma_loc_info_present_flag, | |
| .neutral_chroma_indication_flag = sps->vui.neutra_chroma_indication_flag, | |
| .field_seq_flag = sps->vui.field_seq_flag, | |
| .frame_field_info_present_flag = sps->vui.frame_field_info_present_flag, | |
| .default_display_window_flag = sps->vui.default_display_window_flag, | |
| .vui_timing_info_present_flag = sps->vui.vui_timing_info_present_flag, | |
| .vui_poc_proportional_to_timing_flag = sps->vui.vui_poc_proportional_to_timing_flag, | |
| .vui_hrd_parameters_present_flag = sps->vui.vui_hrd_parameters_present_flag, | |
| .bitstream_restriction_flag = sps->vui.bitstream_restriction_flag, | |
| .tiles_fixed_structure_flag = sps->vui.tiles_fixed_structure_flag, | |
| .motion_vectors_over_pic_boundaries_flag = sps->vui.motion_vectors_over_pic_boundaries_flag, | |
| .restricted_ref_pic_lists_flag = sps->vui.restricted_ref_pic_lists_flag, | |
| }, | |
| .aspect_ratio_idc = sps->vui.common.aspect_ratio_idc, | |
| .sar_width = sps->vui.common.sar.num, | |
| .sar_height = sps->vui.common.sar.den, | |
| .video_format = sps->vui.common.video_format, | |
| .colour_primaries = sps->vui.common.colour_primaries, | |
| .transfer_characteristics = sps->vui.common.transfer_characteristics, | |
| .matrix_coeffs = sps->vui.common.matrix_coeffs, | |
| .chroma_sample_loc_type_top_field = sps->vui.common.chroma_sample_loc_type_top_field, | |
| .chroma_sample_loc_type_bottom_field = sps->vui.common.chroma_sample_loc_type_bottom_field, | |
| /* Reserved */ | |
| /* Reserved */ | |
| .def_disp_win_left_offset = sps->vui.def_disp_win.left_offset, | |
| .def_disp_win_right_offset = sps->vui.def_disp_win.right_offset, | |
| .def_disp_win_top_offset = sps->vui.def_disp_win.top_offset, | |
| .def_disp_win_bottom_offset = sps->vui.def_disp_win.bottom_offset, | |
| .vui_num_units_in_tick = sps->vui.vui_num_units_in_tick, | |
| .vui_time_scale = sps->vui.vui_time_scale, | |
| .vui_num_ticks_poc_diff_one_minus1 = sps->vui.vui_num_ticks_poc_diff_one_minus1, | |
| .min_spatial_segmentation_idc = sps->vui.min_spatial_segmentation_idc, | |
| .max_bytes_per_pic_denom = sps->vui.max_bytes_per_pic_denom, | |
| .max_bits_per_min_cu_denom = sps->vui.max_bits_per_min_cu_denom, | |
| .log2_max_mv_length_horizontal = sps->vui.log2_max_mv_length_horizontal, | |
| .log2_max_mv_length_vertical = sps->vui.log2_max_mv_length_vertical, | |
| .pHrdParameters = vksps_vui_header, | |
| }; | |
| *ptl = (StdVideoH265ProfileTierLevel) { | |
| .flags = (StdVideoH265ProfileTierLevelFlags) { | |
| .general_tier_flag = sps->ptl.general_ptl.tier_flag, | |
| .general_progressive_source_flag = sps->ptl.general_ptl.progressive_source_flag, | |
| .general_interlaced_source_flag = sps->ptl.general_ptl.interlaced_source_flag, | |
| .general_non_packed_constraint_flag = sps->ptl.general_ptl.non_packed_constraint_flag, | |
| .general_frame_only_constraint_flag = sps->ptl.general_ptl.frame_only_constraint_flag, | |
| }, | |
| .general_profile_idc = sps->ptl.general_ptl.profile_idc, | |
| .general_level_idc = convert_to_vk_level_idc(sps->ptl.general_ptl.level_idc), | |
| }; | |
| for (int i = 0; i < sps->max_sub_layers; i++) { | |
| dpbm->max_latency_increase_plus1[i] = sps->temporal_layer[i].max_latency_increase + 1; | |
| dpbm->max_dec_pic_buffering_minus1[i] = sps->temporal_layer[i].max_dec_pic_buffering - 1; | |
| dpbm->max_num_reorder_pics[i] = sps->temporal_layer[i].num_reorder_pics; | |
| } | |
| for (int i = 0; i < (sps->chroma_format_idc ? 3 : 1); i++) | |
| for (int j = 0; j < sps->sps_num_palette_predictor_initializers; j++) | |
| pal->PredictorPaletteEntries[i][j] = sps->sps_palette_predictor_initializer[i][j]; | |
| for (int i = 0; i < sps->nb_st_rps; i++) { | |
| str[i] = (StdVideoH265ShortTermRefPicSet) { | |
| .flags = (StdVideoH265ShortTermRefPicSetFlags) { | |
| .inter_ref_pic_set_prediction_flag = sps->st_rps[i].rps_predict, | |
| .delta_rps_sign = sps->st_rps[i].delta_rps_sign, | |
| }, | |
| .delta_idx_minus1 = sps->st_rps[i].delta_idx - 1, | |
| .use_delta_flag = sps->st_rps[i].use_delta_flag, | |
| .abs_delta_rps_minus1 = sps->st_rps[i].abs_delta_rps - 1, | |
| .used_by_curr_pic_flag = 0x0, | |
| .used_by_curr_pic_s0_flag = 0x0, | |
| .used_by_curr_pic_s1_flag = 0x0, | |
| /* Reserved */ | |
| /* Reserved */ | |
| /* Reserved */ | |
| .num_negative_pics = sps->st_rps[i].num_negative_pics, | |
| .num_positive_pics = sps->st_rps[i].num_delta_pocs - sps->st_rps[i].num_negative_pics, | |
| }; | |
| /* NOTE: This is the predicted, and *reordered* version. | |
| * Probably incorrect, but the spec doesn't say which version to use. */ | |
| for (int j = 0; j < sps->st_rps[i].num_delta_pocs; j++) | |
| str[i].used_by_curr_pic_flag |= sps->st_rps[i].used[j] << j; | |
| for (int j = 0; j < str[i].num_negative_pics; j++) { | |
| str[i].delta_poc_s0_minus1[j] = sps->st_rps[i].delta_poc_s0[j] - 1; | |
| str[i].used_by_curr_pic_s0_flag |= sps->st_rps[i].used[j] << j; | |
| } | |
| for (int j = 0; j < str[i].num_positive_pics; j++) { | |
| str[i].delta_poc_s1_minus1[j] = sps->st_rps[i].delta_poc_s1[j] - 1; | |
| str[i].used_by_curr_pic_s0_flag |= sps->st_rps[i].used[str[i].num_negative_pics + j] << j; | |
| } | |
| } | |
| *ltr = (StdVideoH265LongTermRefPicsSps) { | |
| .used_by_curr_pic_lt_sps_flag = 0x0, | |
| }; | |
| for (int i = 0; i < sps->num_long_term_ref_pics_sps; i++) { | |
| ltr->used_by_curr_pic_lt_sps_flag |= sps->used_by_curr_pic_lt_sps_flag[i] << i; | |
| ltr->lt_ref_pic_poc_lsb_sps[i] = sps->lt_ref_pic_poc_lsb_sps[i]; | |
| } | |
| *vksps = (StdVideoH265SequenceParameterSet) { | |
| .flags = (StdVideoH265SpsFlags) { | |
| .sps_temporal_id_nesting_flag = sps->temporal_id_nesting_flag, | |
| .separate_colour_plane_flag = sps->separate_colour_plane_flag, | |
| .conformance_window_flag = sps->conformance_window_flag, | |
| .sps_sub_layer_ordering_info_present_flag = sps->sublayer_ordering_info_flag, | |
| .scaling_list_enabled_flag = sps->scaling_list_enable_flag, | |
| .sps_scaling_list_data_present_flag = sps->scaling_list_enable_flag, | |
| .amp_enabled_flag = sps->amp_enabled_flag, | |
| .sample_adaptive_offset_enabled_flag = sps->sao_enabled, | |
| .pcm_enabled_flag = sps->pcm_enabled_flag, | |
| .pcm_loop_filter_disabled_flag = sps->pcm.loop_filter_disable_flag, | |
| .long_term_ref_pics_present_flag = sps->long_term_ref_pics_present_flag, | |
| .sps_temporal_mvp_enabled_flag = sps->sps_temporal_mvp_enabled_flag, | |
| .strong_intra_smoothing_enabled_flag = sps->sps_strong_intra_smoothing_enable_flag, | |
| .vui_parameters_present_flag = sps->vui_present, | |
| .sps_extension_present_flag = sps->sps_extension_present_flag, | |
| .sps_range_extension_flag = sps->sps_range_extension_flag, | |
| .transform_skip_rotation_enabled_flag = sps->transform_skip_rotation_enabled_flag, | |
| .transform_skip_context_enabled_flag = sps->transform_skip_context_enabled_flag, | |
| .implicit_rdpcm_enabled_flag = sps->implicit_rdpcm_enabled_flag, | |
| .explicit_rdpcm_enabled_flag = sps->explicit_rdpcm_enabled_flag, | |
| .extended_precision_processing_flag = sps->extended_precision_processing_flag, | |
| .intra_smoothing_disabled_flag = sps->intra_smoothing_disabled_flag, | |
| .high_precision_offsets_enabled_flag = sps->high_precision_offsets_enabled_flag, | |
| .persistent_rice_adaptation_enabled_flag = sps->persistent_rice_adaptation_enabled_flag, | |
| .cabac_bypass_alignment_enabled_flag = sps->cabac_bypass_alignment_enabled_flag, | |
| .sps_scc_extension_flag = sps->sps_scc_extension_flag, | |
| .sps_curr_pic_ref_enabled_flag = sps->sps_curr_pic_ref_enabled_flag, | |
| .palette_mode_enabled_flag = sps->palette_mode_enabled_flag, | |
| .sps_palette_predictor_initializers_present_flag = sps->sps_palette_predictor_initializers_present_flag, | |
| .intra_boundary_filtering_disabled_flag = sps->intra_boundary_filtering_disabled_flag, | |
| }, | |
| .chroma_format_idc = sps->chroma_format_idc, | |
| .pic_width_in_luma_samples = sps->width, | |
| .pic_height_in_luma_samples = sps->height, | |
| .sps_video_parameter_set_id = sps->vps_id, | |
| .sps_max_sub_layers_minus1 = sps->max_sub_layers - 1, | |
| .sps_seq_parameter_set_id = sps_idx, | |
| .bit_depth_luma_minus8 = sps->bit_depth - 8, | |
| .bit_depth_chroma_minus8 = sps->bit_depth_chroma - 8, | |
| .log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_poc_lsb - 4, | |
| .log2_min_luma_coding_block_size_minus3 = sps->log2_min_cb_size - 3, | |
| .log2_diff_max_min_luma_coding_block_size = sps->log2_diff_max_min_coding_block_size, | |
| .log2_min_luma_transform_block_size_minus2 = sps->log2_min_tb_size - 2, | |
| .log2_diff_max_min_luma_transform_block_size = sps->log2_diff_max_min_transform_block_size, | |
| .max_transform_hierarchy_depth_inter = sps->max_transform_hierarchy_depth_inter, | |
| .max_transform_hierarchy_depth_intra = sps->max_transform_hierarchy_depth_intra, | |
| .num_short_term_ref_pic_sets = sps->nb_st_rps, | |
| .num_long_term_ref_pics_sps = sps->num_long_term_ref_pics_sps, | |
| .pcm_sample_bit_depth_luma_minus1 = sps->pcm.bit_depth - 1, | |
| .pcm_sample_bit_depth_chroma_minus1 = sps->pcm.bit_depth_chroma - 1, | |
| .log2_min_pcm_luma_coding_block_size_minus3 = sps->pcm.log2_min_pcm_cb_size - 3, | |
| .log2_diff_max_min_pcm_luma_coding_block_size = sps->pcm.log2_max_pcm_cb_size - sps->pcm.log2_min_pcm_cb_size, | |
| /* Reserved */ | |
| /* Reserved */ | |
| .palette_max_size = sps->palette_max_size, | |
| .delta_palette_max_predictor_size = sps->delta_palette_max_predictor_size, | |
| .motion_vector_resolution_control_idc = sps->motion_vector_resolution_control_idc, | |
| .sps_num_palette_predictor_initializers_minus1 = sps->sps_num_palette_predictor_initializers - 1, | |
| .conf_win_left_offset = sps->pic_conf_win.left_offset, | |
| .conf_win_right_offset = sps->pic_conf_win.right_offset, | |
| .conf_win_top_offset = sps->pic_conf_win.top_offset, | |
| .conf_win_bottom_offset = sps->pic_conf_win.bottom_offset, | |
| .pProfileTierLevel = ptl, | |
| .pDecPicBufMgr = dpbm, | |
| .pScalingLists = vksps_scaling, | |
| .pShortTermRefPicSet = str, | |
| .pLongTermRefPicsSps = ltr, | |
| .pSequenceParameterSetVui = vksps_vui, | |
| .pPredictorPaletteEntries = pal, | |
| }; | |
| } | |
| static void set_pps(const HEVCPPS *pps, const HEVCSPS *sps, | |
| StdVideoH265ScalingLists *vkpps_scaling, | |
| StdVideoH265PictureParameterSet *vkpps, | |
| StdVideoH265PredictorPaletteEntries *pal) | |
| { | |
| copy_scaling_list(&pps->scaling_list, vkpps_scaling); | |
| *vkpps = (StdVideoH265PictureParameterSet) { | |
| .flags = (StdVideoH265PpsFlags) { | |
| .dependent_slice_segments_enabled_flag = pps->dependent_slice_segments_enabled_flag, | |
| .output_flag_present_flag = pps->output_flag_present_flag, | |
| .sign_data_hiding_enabled_flag = pps->sign_data_hiding_flag, | |
| .cabac_init_present_flag = pps->cabac_init_present_flag, | |
| .constrained_intra_pred_flag = pps->constrained_intra_pred_flag, | |
| .transform_skip_enabled_flag = pps->transform_skip_enabled_flag, | |
| .cu_qp_delta_enabled_flag = pps->cu_qp_delta_enabled_flag, | |
| .pps_slice_chroma_qp_offsets_present_flag = pps->pic_slice_level_chroma_qp_offsets_present_flag, | |
| .weighted_pred_flag = pps->weighted_pred_flag, | |
| .weighted_bipred_flag = pps->weighted_bipred_flag, | |
| .transquant_bypass_enabled_flag = pps->transquant_bypass_enable_flag, | |
| .tiles_enabled_flag = pps->tiles_enabled_flag, | |
| .entropy_coding_sync_enabled_flag = pps->entropy_coding_sync_enabled_flag, | |
| .uniform_spacing_flag = pps->uniform_spacing_flag, | |
| .loop_filter_across_tiles_enabled_flag = pps->loop_filter_across_tiles_enabled_flag, | |
| .pps_loop_filter_across_slices_enabled_flag = pps->seq_loop_filter_across_slices_enabled_flag, | |
| .deblocking_filter_control_present_flag = pps->deblocking_filter_control_present_flag, | |
| .deblocking_filter_override_enabled_flag = pps->deblocking_filter_override_enabled_flag, | |
| .pps_deblocking_filter_disabled_flag = pps->disable_dbf, | |
| .pps_scaling_list_data_present_flag = pps->scaling_list_data_present_flag, | |
| .lists_modification_present_flag = pps->lists_modification_present_flag, | |
| .slice_segment_header_extension_present_flag = pps->slice_header_extension_present_flag, | |
| .pps_extension_present_flag = pps->pps_extension_present_flag, | |
| .cross_component_prediction_enabled_flag = pps->cross_component_prediction_enabled_flag, | |
| .chroma_qp_offset_list_enabled_flag = pps->chroma_qp_offset_list_enabled_flag, | |
| .pps_curr_pic_ref_enabled_flag = pps->pps_curr_pic_ref_enabled_flag, | |
| .residual_adaptive_colour_transform_enabled_flag = pps->residual_adaptive_colour_transform_enabled_flag, | |
| .pps_slice_act_qp_offsets_present_flag = pps->pps_slice_act_qp_offsets_present_flag, | |
| .pps_palette_predictor_initializers_present_flag = pps->pps_palette_predictor_initializers_present_flag, | |
| .monochrome_palette_flag = pps->monochrome_palette_flag, | |
| .pps_range_extension_flag = pps->pps_range_extensions_flag, | |
| }, | |
| .pps_pic_parameter_set_id = pps->pps_id, | |
| .pps_seq_parameter_set_id = pps->sps_id, | |
| .sps_video_parameter_set_id = sps->vps_id, | |
| .num_extra_slice_header_bits = pps->num_extra_slice_header_bits, | |
| .num_ref_idx_l0_default_active_minus1 = pps->num_ref_idx_l0_default_active - 1, | |
| .num_ref_idx_l1_default_active_minus1 = pps->num_ref_idx_l1_default_active - 1, | |
| .init_qp_minus26 = pps->pic_init_qp_minus26, | |
| .diff_cu_qp_delta_depth = pps->diff_cu_qp_delta_depth, | |
| .pps_cb_qp_offset = pps->cb_qp_offset, | |
| .pps_cr_qp_offset = pps->cr_qp_offset, | |
| .pps_beta_offset_div2 = pps->beta_offset >> 1, | |
| .pps_tc_offset_div2 = pps->tc_offset >> 1, | |
| .log2_parallel_merge_level_minus2 = pps->log2_parallel_merge_level - 2, | |
| .log2_max_transform_skip_block_size_minus2 = pps->log2_max_transform_skip_block_size - 2, | |
| .diff_cu_chroma_qp_offset_depth = pps->diff_cu_chroma_qp_offset_depth, | |
| .chroma_qp_offset_list_len_minus1 = pps->chroma_qp_offset_list_len_minus1, | |
| .log2_sao_offset_scale_luma = pps->log2_sao_offset_scale_luma, | |
| .log2_sao_offset_scale_chroma = pps->log2_sao_offset_scale_chroma, | |
| .pps_act_y_qp_offset_plus5 = pps->pps_act_y_qp_offset + 5, | |
| .pps_act_cb_qp_offset_plus5 = pps->pps_act_cb_qp_offset + 5, | |
| .pps_act_cr_qp_offset_plus3 = pps->pps_act_cr_qp_offset + 3, | |
| .pps_num_palette_predictor_initializers = pps->pps_num_palette_predictor_initializers, | |
| .luma_bit_depth_entry_minus8 = pps->luma_bit_depth_entry - 8, | |
| .chroma_bit_depth_entry_minus8 = pps->chroma_bit_depth_entry - 8, | |
| .num_tile_columns_minus1 = pps->num_tile_columns - 1, | |
| .num_tile_rows_minus1 = pps->num_tile_rows - 1, | |
| .pScalingLists = vkpps_scaling, | |
| .pPredictorPaletteEntries = pal, | |
| }; | |
| for (int i = 0; i < (pps->monochrome_palette_flag ? 1 : 3); i++) { | |
| for (int j = 0; j < pps->pps_num_palette_predictor_initializers; j++) | |
| pal->PredictorPaletteEntries[i][j] = pps->pps_palette_predictor_initializer[i][j]; | |
| } | |
| for (int i = 0; i < pps->num_tile_columns - 1; i++) | |
| vkpps->column_width_minus1[i] = pps->column_width[i] - 1; | |
| for (int i = 0; i < pps->num_tile_rows - 1; i++) | |
| vkpps->row_height_minus1[i] = pps->row_height[i] - 1; | |
| for (int i = 0; i <= pps->chroma_qp_offset_list_len_minus1; i++) { | |
| vkpps->cb_qp_offset_list[i] = pps->cb_qp_offset_list[i]; | |
| vkpps->cr_qp_offset_list[i] = pps->cr_qp_offset_list[i]; | |
| } | |
| } | |
| static void set_vps(const HEVCVPS *vps, | |
| StdVideoH265VideoParameterSet *vkvps, | |
| StdVideoH265ProfileTierLevel *ptl, | |
| StdVideoH265DecPicBufMgr *dpbm, | |
| StdVideoH265HrdParameters *sls_hdr, | |
| HEVCHeaderVPSSet sls[]) | |
| { | |
| for (int i = 0; i < vps->vps_num_hrd_parameters; i++) { | |
| const HEVCHdrParams *src = &vps->hdr[i]; | |
| sls_hdr[i] = (StdVideoH265HrdParameters) { | |
| .flags = (StdVideoH265HrdFlags) { | |
| .nal_hrd_parameters_present_flag = src->nal_hrd_parameters_present_flag, | |
| .vcl_hrd_parameters_present_flag = src->vcl_hrd_parameters_present_flag, | |
| .sub_pic_hrd_params_present_flag = src->sub_pic_hrd_params_present_flag, | |
| .sub_pic_cpb_params_in_pic_timing_sei_flag = src->sub_pic_cpb_params_in_pic_timing_sei_flag, | |
| .fixed_pic_rate_general_flag = src->flags.fixed_pic_rate_general_flag, | |
| .fixed_pic_rate_within_cvs_flag = src->flags.fixed_pic_rate_within_cvs_flag, | |
| .low_delay_hrd_flag = src->flags.low_delay_hrd_flag, | |
| }, | |
| .tick_divisor_minus2 = src->tick_divisor_minus2, | |
| .du_cpb_removal_delay_increment_length_minus1 = src->du_cpb_removal_delay_increment_length_minus1, | |
| .dpb_output_delay_du_length_minus1 = src->dpb_output_delay_du_length_minus1, | |
| .bit_rate_scale = src->bit_rate_scale, | |
| .cpb_size_scale = src->cpb_size_scale, | |
| .cpb_size_du_scale = src->cpb_size_du_scale, | |
| .initial_cpb_removal_delay_length_minus1 = src->initial_cpb_removal_delay_length_minus1, | |
| .au_cpb_removal_delay_length_minus1 = src->au_cpb_removal_delay_length_minus1, | |
| .dpb_output_delay_length_minus1 = src->dpb_output_delay_length_minus1, | |
| /* Reserved - 3*16 bits */ | |
| .pSubLayerHrdParametersNal = sls[i].nal_hdr, | |
| .pSubLayerHrdParametersVcl = sls[i].vcl_hdr, | |
| }; | |
| memcpy(sls_hdr[i].cpb_cnt_minus1, src->cpb_cnt_minus1, | |
| STD_VIDEO_H265_SUBLAYERS_LIST_SIZE*sizeof(*sls_hdr[i].cpb_cnt_minus1)); | |
| memcpy(sls_hdr[i].elemental_duration_in_tc_minus1, src->elemental_duration_in_tc_minus1, | |
| STD_VIDEO_H265_SUBLAYERS_LIST_SIZE*sizeof(*sls_hdr[i].elemental_duration_in_tc_minus1)); | |
| memcpy(sls[i].nal_hdr, src->nal_params, HEVC_MAX_SUB_LAYERS*sizeof(*sls[i].nal_hdr)); | |
| memcpy(sls[i].vcl_hdr, src->vcl_params, HEVC_MAX_SUB_LAYERS*sizeof(*sls[i].vcl_hdr)); | |
| } | |
| *ptl = (StdVideoH265ProfileTierLevel) { | |
| .flags = (StdVideoH265ProfileTierLevelFlags) { | |
| .general_tier_flag = vps->ptl.general_ptl.tier_flag, | |
| .general_progressive_source_flag = vps->ptl.general_ptl.progressive_source_flag, | |
| .general_interlaced_source_flag = vps->ptl.general_ptl.interlaced_source_flag, | |
| .general_non_packed_constraint_flag = vps->ptl.general_ptl.non_packed_constraint_flag, | |
| .general_frame_only_constraint_flag = vps->ptl.general_ptl.frame_only_constraint_flag, | |
| }, | |
| .general_profile_idc = vps->ptl.general_ptl.profile_idc, | |
| .general_level_idc = convert_to_vk_level_idc(vps->ptl.general_ptl.level_idc), | |
| }; | |
| for (int i = 0; i < vps->vps_max_sub_layers; i++) { | |
| dpbm->max_latency_increase_plus1[i] = vps->vps_max_latency_increase[i] + 1; | |
| dpbm->max_dec_pic_buffering_minus1[i] = vps->vps_max_dec_pic_buffering[i] - 1; | |
| dpbm->max_num_reorder_pics[i] = vps->vps_num_reorder_pics[i]; | |
| } | |
| *vkvps = (StdVideoH265VideoParameterSet) { | |
| .flags = (StdVideoH265VpsFlags) { | |
| .vps_temporal_id_nesting_flag = vps->vps_temporal_id_nesting_flag, | |
| .vps_sub_layer_ordering_info_present_flag = vps->vps_sub_layer_ordering_info_present_flag, | |
| .vps_timing_info_present_flag = vps->vps_timing_info_present_flag, | |
| .vps_poc_proportional_to_timing_flag = vps->vps_poc_proportional_to_timing_flag, | |
| }, | |
| .vps_video_parameter_set_id = vps->vps_id, | |
| .vps_max_sub_layers_minus1 = vps->vps_max_sub_layers - 1, | |
| /* Reserved */ | |
| /* Reserved */ | |
| .vps_num_units_in_tick = vps->vps_num_units_in_tick, | |
| .vps_time_scale = vps->vps_time_scale, | |
| .vps_num_ticks_poc_diff_one_minus1 = vps->vps_num_ticks_poc_diff_one - 1, | |
| /* Reserved */ | |
| .pDecPicBufMgr = dpbm, | |
| .pHrdParameters = sls_hdr, | |
| .pProfileTierLevel = ptl, | |
| }; | |
| } | |
| static int vk_hevc_create_params(AVCodecContext *avctx, AVBufferRef **buf) | |
| { | |
| int err; | |
| const HEVCContext *h = avctx->priv_data; | |
| FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; | |
| FFVulkanDecodeShared *ctx = dec->shared_ctx; | |
| VkVideoDecodeH265SessionParametersAddInfoKHR h265_params_info = { | |
| .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_ADD_INFO_KHR, | |
| .stdSPSCount = 0, | |
| .stdPPSCount = 0, | |
| .stdVPSCount = 0, | |
| }; | |
| VkVideoDecodeH265SessionParametersCreateInfoKHR h265_params = { | |
| .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_KHR, | |
| .pParametersAddInfo = &h265_params_info, | |
| }; | |
| VkVideoSessionParametersCreateInfoKHR session_params_create = { | |
| .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR, | |
| .pNext = &h265_params, | |
| .videoSession = ctx->common.session, | |
| .videoSessionParametersTemplate = VK_NULL_HANDLE, | |
| }; | |
| HEVCHeaderSet *hdr; | |
| int nb_vps = 0; | |
| int vps_list_idx[HEVC_MAX_VPS_COUNT]; | |
| for (int i = 0; i < HEVC_MAX_VPS_COUNT; i++) | |
| if (h->ps.vps_list[i]) | |
| vps_list_idx[nb_vps++] = i; | |
| err = alloc_hevc_header_structs(dec, nb_vps, vps_list_idx, h->ps.vps_list); | |
| if (err < 0) | |
| return err; | |
| hdr = dec->hevc_headers; | |
| h265_params_info.pStdSPSs = hdr->sps; | |
| h265_params_info.pStdPPSs = hdr->pps; | |
| h265_params_info.pStdVPSs = hdr->vps; | |
| /* SPS list */ | |
| for (int i = 0; i < HEVC_MAX_SPS_COUNT; i++) { | |
| if (h->ps.sps_list[i]) { | |
| const HEVCSPS *sps_l = h->ps.sps_list[i]; | |
| int idx = h265_params_info.stdSPSCount++; | |
| set_sps(sps_l, i, &hdr->hsps[idx].scaling, &hdr->hsps[idx].vui_header, | |
| &hdr->hsps[idx].vui, &hdr->sps[idx], hdr->hsps[idx].nal_hdr, | |
| hdr->hsps[idx].vcl_hdr, &hdr->hsps[idx].ptl, &hdr->hsps[idx].dpbm, | |
| &hdr->hsps[idx].pal, hdr->hsps[idx].str, &hdr->hsps[idx].ltr); | |
| } | |
| } | |
| /* PPS list */ | |
| for (int i = 0; i < HEVC_MAX_PPS_COUNT; i++) { | |
| if (h->ps.pps_list[i]) { | |
| const HEVCPPS *pps_l = h->ps.pps_list[i]; | |
| const HEVCSPS *sps_l = h->ps.sps_list[pps_l->sps_id]; | |
| int idx = h265_params_info.stdPPSCount++; | |
| set_pps(pps_l, sps_l, &hdr->hpps[idx].scaling, | |
| &hdr->pps[idx], &hdr->hpps[idx].pal); | |
| } | |
| } | |
| /* VPS list */ | |
| for (int i = 0; i < nb_vps; i++) { | |
| const HEVCVPS *vps_l = h->ps.vps_list[vps_list_idx[i]]; | |
| set_vps(vps_l, &hdr->vps[i], &hdr->hvps[i].ptl, &hdr->hvps[i].dpbm, | |
| hdr->hvps[i].hdr, hdr->hvps[i].sls); | |
| h265_params_info.stdVPSCount++; | |
| } | |
| h265_params.maxStdSPSCount = h265_params_info.stdSPSCount; | |
| h265_params.maxStdPPSCount = h265_params_info.stdPPSCount; | |
| h265_params.maxStdVPSCount = h265_params_info.stdVPSCount; | |
| err = ff_vk_decode_create_params(buf, avctx, ctx, &session_params_create); | |
| if (err < 0) | |
| return err; | |
| av_log(avctx, AV_LOG_DEBUG, "Created frame parameters: %i SPS %i PPS %i VPS\n", | |
| h265_params_info.stdSPSCount, h265_params_info.stdPPSCount, | |
| h265_params_info.stdVPSCount); | |
| return 0; | |
| } | |
| static int vk_hevc_start_frame(AVCodecContext *avctx, | |
| av_unused const uint8_t *buffer, | |
| av_unused uint32_t size) | |
| { | |
| int err; | |
| HEVCContext *h = avctx->priv_data; | |
| HEVCFrame *pic = h->ref; | |
| FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; | |
| HEVCVulkanDecodePicture *hp = pic->hwaccel_picture_private; | |
| FFVulkanDecodePicture *vp = &hp->vp; | |
| const HEVCSPS *sps = h->ps.sps; | |
| const HEVCPPS *pps = h->ps.pps; | |
| int nb_refs = 0; | |
| if (!dec->session_params) { | |
| err = vk_hevc_create_params(avctx, &dec->session_params); | |
| if (err < 0) | |
| return err; | |
| } | |
| hp->h265pic = (StdVideoDecodeH265PictureInfo) { | |
| .flags = (StdVideoDecodeH265PictureInfoFlags) { | |
| .IrapPicFlag = IS_IRAP(h), | |
| .IdrPicFlag = IS_IDR(h), | |
| .IsReference = h->nal_unit_type < 16 ? h->nal_unit_type & 1 : 1, | |
| .short_term_ref_pic_set_sps_flag = h->sh.short_term_ref_pic_set_sps_flag, | |
| }, | |
| .sps_video_parameter_set_id = sps->vps_id, | |
| .pps_seq_parameter_set_id = pps->sps_id, | |
| .pps_pic_parameter_set_id = pps->pps_id, | |
| .NumDeltaPocsOfRefRpsIdx = h->sh.short_term_rps ? h->sh.short_term_rps->rps_idx_num_delta_pocs : 0, | |
| .PicOrderCntVal = h->poc, | |
| .NumBitsForSTRefPicSetInSlice = !h->sh.short_term_ref_pic_set_sps_flag ? | |
| h->sh.short_term_ref_pic_set_size : 0, | |
| }; | |
| /* Fill in references */ | |
| for (int i = 0; i < FF_ARRAY_ELEMS(h->DPB); i++) { | |
| const HEVCFrame *ref = &h->DPB[i]; | |
| int idx = nb_refs; | |
| if (!(ref->flags & (HEVC_FRAME_FLAG_SHORT_REF | HEVC_FRAME_FLAG_LONG_REF))) | |
| continue; | |
| if (ref == pic) { | |
| err = vk_hevc_fill_pict(avctx, NULL, &vp->ref_slot, &vp->ref, | |
| &hp->vkh265_ref, &hp->h265_ref, pic, 1, i); | |
| if (err < 0) | |
| return err; | |
| continue; | |
| } | |
| err = vk_hevc_fill_pict(avctx, &hp->ref_src[idx], &vp->ref_slots[idx], | |
| &vp->refs[idx], &hp->vkh265_refs[idx], | |
| &hp->h265_refs[idx], (HEVCFrame *)ref, 0, i); | |
| if (err < 0) | |
| return err; | |
| nb_refs++; | |
| } | |
| memset(hp->h265pic.RefPicSetStCurrBefore, 0xff, 8); | |
| for (int i = 0; i < h->rps[ST_CURR_BEF].nb_refs; i++) { | |
| HEVCFrame *frame = h->rps[ST_CURR_BEF].ref[i]; | |
| for (int j = 0; j < FF_ARRAY_ELEMS(h->DPB); j++) { | |
| const HEVCFrame *ref = &h->DPB[j]; | |
| if (ref == frame) { | |
| hp->h265pic.RefPicSetStCurrBefore[i] = j; | |
| break; | |
| } | |
| } | |
| } | |
| memset(hp->h265pic.RefPicSetStCurrAfter, 0xff, 8); | |
| for (int i = 0; i < h->rps[ST_CURR_AFT].nb_refs; i++) { | |
| HEVCFrame *frame = h->rps[ST_CURR_AFT].ref[i]; | |
| for (int j = 0; j < FF_ARRAY_ELEMS(h->DPB); j++) { | |
| const HEVCFrame *ref = &h->DPB[j]; | |
| if (ref == frame) { | |
| hp->h265pic.RefPicSetStCurrAfter[i] = j; | |
| break; | |
| } | |
| } | |
| } | |
| memset(hp->h265pic.RefPicSetLtCurr, 0xff, 8); | |
| for (int i = 0; i < h->rps[LT_CURR].nb_refs; i++) { | |
| HEVCFrame *frame = h->rps[LT_CURR].ref[i]; | |
| for (int j = 0; j < FF_ARRAY_ELEMS(h->DPB); j++) { | |
| const HEVCFrame *ref = &h->DPB[j]; | |
| if (ref == frame) { | |
| hp->h265pic.RefPicSetLtCurr[i] = j; | |
| break; | |
| } | |
| } | |
| } | |
| hp->h265_pic_info = (VkVideoDecodeH265PictureInfoKHR) { | |
| .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PICTURE_INFO_KHR, | |
| .pStdPictureInfo = &hp->h265pic, | |
| .sliceSegmentCount = 0, | |
| }; | |
| vp->decode_info = (VkVideoDecodeInfoKHR) { | |
| .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR, | |
| .pNext = &hp->h265_pic_info, | |
| .flags = 0x0, | |
| .pSetupReferenceSlot = &vp->ref_slot, | |
| .referenceSlotCount = nb_refs, | |
| .pReferenceSlots = vp->ref_slots, | |
| .dstPictureResource = (VkVideoPictureResourceInfoKHR) { | |
| .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR, | |
| .codedOffset = (VkOffset2D){ 0, 0 }, | |
| .codedExtent = (VkExtent2D){ pic->frame->width, pic->frame->height }, | |
| .baseArrayLayer = 0, | |
| .imageViewBinding = vp->img_view_out, | |
| }, | |
| }; | |
| return 0; | |
| } | |
| static int vk_hevc_decode_slice(AVCodecContext *avctx, | |
| const uint8_t *data, | |
| uint32_t size) | |
| { | |
| const HEVCContext *h = avctx->priv_data; | |
| HEVCVulkanDecodePicture *hp = h->ref->hwaccel_picture_private; | |
| FFVulkanDecodePicture *vp = &hp->vp; | |
| int err = ff_vk_decode_add_slice(avctx, vp, data, size, 1, | |
| &hp->h265_pic_info.sliceSegmentCount, | |
| &hp->h265_pic_info.pSliceSegmentOffsets); | |
| if (err < 0) | |
| return err; | |
| return 0; | |
| } | |
| static int vk_hevc_end_frame(AVCodecContext *avctx) | |
| { | |
| const HEVCContext *h = avctx->priv_data; | |
| FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; | |
| HEVCFrame *pic = h->ref; | |
| HEVCVulkanDecodePicture *hp = pic->hwaccel_picture_private; | |
| FFVulkanDecodePicture *vp = &hp->vp; | |
| FFVulkanDecodePicture *rvp[HEVC_MAX_REFS] = { 0 }; | |
| AVFrame *rav[HEVC_MAX_REFS] = { 0 }; | |
| int err; | |
| if (!hp->h265_pic_info.sliceSegmentCount) | |
| return 0; | |
| if (!dec->session_params) { | |
| const HEVCSPS *sps = h->ps.sps; | |
| const HEVCPPS *pps = h->ps.pps; | |
| if (!pps) { | |
| unsigned int pps_id = h->sh.pps_id; | |
| if (pps_id < HEVC_MAX_PPS_COUNT && h->ps.pps_list[pps_id] != NULL) | |
| pps = h->ps.pps_list[pps_id]; | |
| } | |
| if (!pps) { | |
| av_log(avctx, AV_LOG_ERROR, | |
| "Encountered frame without a valid active PPS reference.\n"); | |
| return AVERROR_INVALIDDATA; | |
| } | |
| err = vk_hevc_create_params(avctx, &dec->session_params); | |
| if (err < 0) | |
| return err; | |
| hp->h265pic.sps_video_parameter_set_id = sps->vps_id; | |
| hp->h265pic.pps_seq_parameter_set_id = pps->sps_id; | |
| hp->h265pic.pps_pic_parameter_set_id = pps->pps_id; | |
| } | |
| for (int i = 0; i < vp->decode_info.referenceSlotCount; i++) { | |
| HEVCVulkanDecodePicture *rfhp = hp->ref_src[i]->hwaccel_picture_private; | |
| rav[i] = hp->ref_src[i]->frame; | |
| rvp[i] = &rfhp->vp; | |
| } | |
| av_log(avctx, AV_LOG_VERBOSE, "Decoding frame, %"SIZE_SPECIFIER" bytes, %i slices\n", | |
| vp->slices_size, hp->h265_pic_info.sliceSegmentCount); | |
| return ff_vk_decode_frame(avctx, pic->frame, vp, rav, rvp); | |
| } | |
| static void vk_hevc_free_frame_priv(FFRefStructOpaque _hwctx, void *data) | |
| { | |
| AVHWDeviceContext *hwctx = _hwctx.nc; | |
| HEVCVulkanDecodePicture *hp = data; | |
| /* Free frame resources */ | |
| ff_vk_decode_free_frame(hwctx, &hp->vp); | |
| } | |
| const FFHWAccel ff_hevc_vulkan_hwaccel = { | |
| .p.name = "hevc_vulkan", | |
| .p.type = AVMEDIA_TYPE_VIDEO, | |
| .p.id = AV_CODEC_ID_HEVC, | |
| .p.pix_fmt = AV_PIX_FMT_VULKAN, | |
| .start_frame = &vk_hevc_start_frame, | |
| .decode_slice = &vk_hevc_decode_slice, | |
| .end_frame = &vk_hevc_end_frame, | |
| .free_frame_priv = &vk_hevc_free_frame_priv, | |
| .frame_priv_data_size = sizeof(HEVCVulkanDecodePicture), | |
| .init = &ff_vk_decode_init, | |
| .update_thread_context = &ff_vk_update_thread_context, | |
| .decode_params = &ff_vk_params_invalidate, | |
| .flush = &ff_vk_decode_flush, | |
| .uninit = &ff_vk_decode_uninit, | |
| .frame_params = &ff_vk_frame_params, | |
| .priv_data_size = sizeof(FFVulkanDecodeContext), | |
| .caps_internal = HWACCEL_CAP_ASYNC_SAFE | HWACCEL_CAP_THREAD_SAFE, | |
| }; |