mirror of https://github.com/FFmpeg/FFmpeg.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
944 lines
44 KiB
944 lines
44 KiB
/* |
|
* 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 "libavutil/mem.h" |
|
#include "hevc/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->f, 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->f->width, pic->f->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++) { |
|
const ShortTermRPS *st_rps = &sps->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, |
|
.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. */ |
|
str[i].used_by_curr_pic_flag = st_rps->used; |
|
str[i].used_by_curr_pic_s0_flag = av_mod_uintp2(st_rps->used, str[i].num_negative_pics); |
|
str[i].used_by_curr_pic_s1_flag = st_rps->used >> str[i].num_negative_pics; |
|
|
|
for (int j = 0; j < str[i].num_negative_pics; j++) |
|
str[i].delta_poc_s0_minus1[j] = st_rps->delta_poc[j] - (j ? st_rps->delta_poc[j - 1] : 0) - 1; |
|
|
|
for (int j = 0; j < str[i].num_positive_pics; j++) |
|
str[i].delta_poc_s1_minus1[j] = st_rps->delta_poc[st_rps->num_negative_pics + j] - |
|
(j ? st_rps->delta_poc[st_rps->num_negative_pics + j - 1] : 0) - 1; |
|
} |
|
|
|
*ltr = (StdVideoH265LongTermRefPicsSps) { |
|
.used_by_curr_pic_lt_sps_flag = sps->used_by_curr_pic_lt, |
|
}; |
|
|
|
for (int i = 0; i < sps->num_long_term_ref_pics_sps; 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, |
|
.separate_colour_plane_flag = sps->separate_colour_plane, |
|
.conformance_window_flag = sps->conformance_window, |
|
.sps_sub_layer_ordering_info_present_flag = sps->sublayer_ordering_info, |
|
.scaling_list_enabled_flag = sps->scaling_list_enabled, |
|
.sps_scaling_list_data_present_flag = sps->scaling_list_enabled, |
|
.amp_enabled_flag = sps->amp_enabled, |
|
.sample_adaptive_offset_enabled_flag = sps->sao_enabled, |
|
.pcm_enabled_flag = sps->pcm_enabled, |
|
.pcm_loop_filter_disabled_flag = sps->pcm_loop_filter_disabled, |
|
.long_term_ref_pics_present_flag = sps->long_term_ref_pics_present, |
|
.sps_temporal_mvp_enabled_flag = sps->temporal_mvp_enabled, |
|
.strong_intra_smoothing_enabled_flag = sps->strong_intra_smoothing_enabled, |
|
.vui_parameters_present_flag = sps->vui_present, |
|
.sps_extension_present_flag = sps->extension_present, |
|
.sps_range_extension_flag = sps->range_extension, |
|
.transform_skip_rotation_enabled_flag = sps->transform_skip_rotation_enabled, |
|
.transform_skip_context_enabled_flag = sps->transform_skip_context_enabled, |
|
.implicit_rdpcm_enabled_flag = sps->implicit_rdpcm_enabled, |
|
.explicit_rdpcm_enabled_flag = sps->explicit_rdpcm_enabled, |
|
.extended_precision_processing_flag = sps->extended_precision_processing, |
|
.intra_smoothing_disabled_flag = sps->intra_smoothing_disabled, |
|
.high_precision_offsets_enabled_flag = sps->high_precision_offsets_enabled, |
|
.persistent_rice_adaptation_enabled_flag = sps->persistent_rice_adaptation_enabled, |
|
.cabac_bypass_alignment_enabled_flag = sps->cabac_bypass_alignment_enabled, |
|
.sps_scc_extension_flag = sps->scc_extension, |
|
.sps_curr_pic_ref_enabled_flag = sps->curr_pic_ref_enabled, |
|
.palette_mode_enabled_flag = sps->palette_mode_enabled, |
|
.sps_palette_predictor_initializers_present_flag = sps->palette_predictor_initializers_present, |
|
.intra_boundary_filtering_disabled_flag = sps->intra_boundary_filtering_disabled, |
|
}, |
|
.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->cur_frame; |
|
FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; |
|
HEVCVulkanDecodePicture *hp = pic->hwaccel_picture_private; |
|
FFVulkanDecodePicture *vp = &hp->vp; |
|
const HEVCPPS *pps = h->pps; |
|
const HEVCSPS *sps = pps->sps; |
|
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->f->width, pic->f->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->cur_frame->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->cur_frame; |
|
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 HEVCPPS *pps = h->pps; |
|
const HEVCSPS *sps = pps->sps; |
|
|
|
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]->f; |
|
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->f, 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, |
|
};
|
|
|