1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2024-12-07 11:13:41 +02:00
FFmpeg/libavcodec/vulkan_hevc.c
Benjamin Cheng 27804200ef vulkan_hevc: use diagonal scan order for scaling lists
The hevc parser parses the diagonal scan order in bitstream into raster
scan order. However, the Vulkan spec wants it as specified in H265 spec,
which is diagonal scan order.

Tested on RADV.

v2: fix copy-paste typo with PPS.
2023-07-28 04:07:33 +02:00

974 lines
45 KiB
C

/*
* 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 VkExtensionProperties ff_vk_dec_hevc_ext = {
.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 get_data_set_buf(FFVulkanDecodeContext *s, AVBufferRef **data_buf,
int nb_vps, AVBufferRef * const vps_list[HEVC_MAX_VPS_COUNT])
{
uint8_t *data_ptr;
HEVCHeaderSet *hdr;
size_t base_size = sizeof(StdVideoH265SequenceParameterSet)*HEVC_MAX_SPS_COUNT +
sizeof(HEVCHeaderSPS)*HEVC_MAX_SPS_COUNT +
sizeof(StdVideoH265PictureParameterSet)*HEVC_MAX_PPS_COUNT +
sizeof(HEVCHeaderPPS)*HEVC_MAX_PPS_COUNT +
sizeof(StdVideoH265VideoParameterSet)*HEVC_MAX_VPS_COUNT +
sizeof(HEVCHeaderVPS *);
size_t vps_size = sizeof(StdVideoH265ProfileTierLevel) +
sizeof(StdVideoH265DecPicBufMgr) +
sizeof(StdVideoH265HrdParameters)*HEVC_MAX_LAYER_SETS +
sizeof(HEVCHeaderVPSSet *);
size_t buf_size = base_size + vps_size*nb_vps;
for (int i = 0; i < nb_vps; i++) {
const HEVCVPS *vps = (const HEVCVPS *)vps_list[i]->data;
buf_size += sizeof(HEVCHeaderVPSSet)*vps->vps_num_hrd_parameters;
}
if (buf_size > s->tmp_pool_ele_size) {
av_buffer_pool_uninit(&s->tmp_pool);
s->tmp_pool_ele_size = 0;
s->tmp_pool = av_buffer_pool_init(buf_size, NULL);
if (!s->tmp_pool)
return AVERROR(ENOMEM);
s->tmp_pool_ele_size = buf_size;
}
*data_buf = av_buffer_pool_get(s->tmp_pool);
if (!(*data_buf))
return AVERROR(ENOMEM);
/* Setup pointers */
data_ptr = (*data_buf)->data;
hdr = (HEVCHeaderSet *)data_ptr;
hdr->hvps = (HEVCHeaderVPS *)(data_ptr + base_size);
data_ptr += base_size + vps_size*nb_vps;
for (int i = 0; i < nb_vps; i++) {
const HEVCVPS *vps = (const HEVCVPS *)vps_list[i]->data;
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.flags.nal_hrd_parameters_present_flag,
.vcl_hrd_parameters_present_flag = sps->hdr.flags.vcl_hrd_parameters_present_flag,
.sub_pic_hrd_params_present_flag = sps->hdr.flags.sub_pic_hrd_params_present_flag,
.sub_pic_cpb_params_in_pic_timing_sei_flag = sps->hdr.flags.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->flags.nal_hrd_parameters_present_flag,
.vcl_hrd_parameters_present_flag = src->flags.vcl_hrd_parameters_present_flag,
.sub_pic_hrd_params_present_flag = src->flags.sub_pic_hrd_params_present_flag,
.sub_pic_cpb_params_in_pic_timing_sei_flag = src->flags.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;
VkResult ret;
const HEVCContext *h = avctx->priv_data;
FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
FFVulkanDecodeShared *ctx = (FFVulkanDecodeShared *)dec->shared_ref->data;
FFVulkanFunctions *vk = &ctx->s.vkfn;
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 = NULL,
};
int nb_vps = 0;
AVBufferRef *data_set;
HEVCHeaderSet *hdr;
AVBufferRef *tmp;
VkVideoSessionParametersKHR *par = av_malloc(sizeof(*par));
if (!par)
return AVERROR(ENOMEM);
for (int i = 0; h->ps.vps_list[i]; i++)
nb_vps++;
err = get_data_set_buf(dec, &data_set, nb_vps, h->ps.vps_list);
if (err < 0)
return err;
hdr = (HEVCHeaderSet *)data_set->data;
h265_params_info.pStdSPSs = hdr->sps;
h265_params_info.pStdPPSs = hdr->pps;
h265_params_info.pStdVPSs = hdr->vps;
/* SPS list */
for (int i = 0; h->ps.sps_list[i]; i++) {
const HEVCSPS *sps_l = (const HEVCSPS *)h->ps.sps_list[i]->data;
set_sps(sps_l, i, &hdr->hsps[i].scaling, &hdr->hsps[i].vui_header,
&hdr->hsps[i].vui, &hdr->sps[i], hdr->hsps[i].nal_hdr,
hdr->hsps[i].vcl_hdr, &hdr->hsps[i].ptl, &hdr->hsps[i].dpbm,
&hdr->hsps[i].pal, hdr->hsps[i].str, &hdr->hsps[i].ltr);
h265_params_info.stdSPSCount++;
}
/* PPS list */
for (int i = 0; h->ps.pps_list[i]; i++) {
const HEVCPPS *pps_l = (const HEVCPPS *)h->ps.pps_list[i]->data;
const HEVCSPS *sps_l = (const HEVCSPS *)h->ps.sps_list[pps_l->sps_id]->data;
set_pps(pps_l, sps_l, &hdr->hpps[i].scaling, &hdr->pps[i], &hdr->hpps[i].pal);
h265_params_info.stdPPSCount++;
}
/* VPS list */
for (int i = 0; i < nb_vps; i++) {
const HEVCVPS *vps_l = (const HEVCVPS *)h->ps.vps_list[i]->data;
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;
/* Create session parameters */
ret = vk->CreateVideoSessionParametersKHR(ctx->s.hwctx->act_dev, &session_params_create,
ctx->s.hwctx->alloc, par);
av_buffer_unref(&data_set);
if (ret != VK_SUCCESS) {
av_log(avctx, AV_LOG_ERROR, "Unable to create Vulkan video session parameters: %s!\n",
ff_vk_ret2str(ret));
return AVERROR_EXTERNAL;
}
tmp = av_buffer_create((uint8_t *)par, sizeof(*par), ff_vk_decode_free_params,
ctx, 0);
if (!tmp) {
ff_vk_decode_free_params(ctx, (uint8_t *)par);
return AVERROR(ENOMEM);
}
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);
*buf = tmp;
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 = (const HEVCPPS *)h->ps.pps_list[pps_id]->data;
}
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(void *_hwctx, uint8_t *data)
{
AVHWDeviceContext *hwctx = _hwctx;
HEVCVulkanDecodePicture *hp = (HEVCVulkanDecodePicture *)data;
/* Free frame resources */
ff_vk_decode_free_frame(hwctx, &hp->vp);
/* Free frame context */
av_free(hp);
}
const AVHWAccel ff_hevc_vulkan_hwaccel = {
.name = "hevc_vulkan",
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_HEVC,
.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,
};