Only three of the 226 (== AV_CODEC_ID_AV1) entries have been used. Unsparsing this table is especially important given that this array lives in .data.rel.ro. Reviewed-by: Lynne <dev@lynne.ee> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
		
			
				
	
	
		
			571 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			571 lines
		
	
	
		
			24 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 "h264dec.h"
 | 
						|
#include "h264_ps.h"
 | 
						|
 | 
						|
#include "vulkan_decode.h"
 | 
						|
 | 
						|
const FFVulkanDecodeDescriptor ff_vk_dec_h264_desc = {
 | 
						|
    .codec_id         = AV_CODEC_ID_H264,
 | 
						|
    .decode_extension = FF_VK_EXT_VIDEO_DECODE_H264,
 | 
						|
    .decode_op        = VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR,
 | 
						|
    .ext_props = {
 | 
						|
        .extensionName = VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_EXTENSION_NAME,
 | 
						|
        .specVersion   = VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_SPEC_VERSION,
 | 
						|
    },
 | 
						|
};
 | 
						|
 | 
						|
typedef struct H264VulkanDecodePicture {
 | 
						|
    FFVulkanDecodePicture           vp;
 | 
						|
 | 
						|
    /* Current picture */
 | 
						|
    StdVideoDecodeH264ReferenceInfo h264_ref;
 | 
						|
    VkVideoDecodeH264DpbSlotInfoKHR vkh264_ref;
 | 
						|
 | 
						|
    /* Picture refs */
 | 
						|
    H264Picture                    *ref_src    [H264_MAX_PICTURE_COUNT];
 | 
						|
    StdVideoDecodeH264ReferenceInfo h264_refs  [H264_MAX_PICTURE_COUNT];
 | 
						|
    VkVideoDecodeH264DpbSlotInfoKHR vkh264_refs[H264_MAX_PICTURE_COUNT];
 | 
						|
 | 
						|
    /* Current picture (contd.) */
 | 
						|
    StdVideoDecodeH264PictureInfo   h264pic;
 | 
						|
    VkVideoDecodeH264PictureInfoKHR h264_pic_info;
 | 
						|
} H264VulkanDecodePicture;
 | 
						|
 | 
						|
const static int h264_scaling_list8_order[] = { 0, 3, 1, 4, 2, 5 };
 | 
						|
 | 
						|
static int vk_h264_fill_pict(AVCodecContext *avctx, H264Picture **ref_src,
 | 
						|
                             VkVideoReferenceSlotInfoKHR *ref_slot,       /* Main structure */
 | 
						|
                             VkVideoPictureResourceInfoKHR *ref,          /* Goes in ^ */
 | 
						|
                             VkVideoDecodeH264DpbSlotInfoKHR *vkh264_ref, /* Goes in ^ */
 | 
						|
                             StdVideoDecodeH264ReferenceInfo *h264_ref,   /* Goes in ^ */
 | 
						|
                             H264Picture *pic, int is_current,
 | 
						|
                             int is_field, int picture_structure,
 | 
						|
                             int dpb_slot_index)
 | 
						|
{
 | 
						|
    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
 | 
						|
    H264VulkanDecodePicture *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;
 | 
						|
 | 
						|
    *h264_ref = (StdVideoDecodeH264ReferenceInfo) {
 | 
						|
        .FrameNum = pic->long_ref ? pic->pic_id : pic->frame_num,
 | 
						|
        .PicOrderCnt = { pic->field_poc[0], pic->field_poc[1] },
 | 
						|
        .flags = (StdVideoDecodeH264ReferenceInfoFlags) {
 | 
						|
            .top_field_flag    = is_field ? !!(picture_structure & PICT_TOP_FIELD)    : 0,
 | 
						|
            .bottom_field_flag = is_field ? !!(picture_structure & PICT_BOTTOM_FIELD) : 0,
 | 
						|
            .used_for_long_term_reference = pic->reference && pic->long_ref,
 | 
						|
            /*
 | 
						|
             * flags.is_non_existing is used to indicate whether the picture is marked as
 | 
						|
             * “non-existing” as defined in section 8.2.5.2 of the ITU-T H.264 Specification;
 | 
						|
             * 8.2.5.2 Decoding process for gaps in frame_num
 | 
						|
             * corresponds to the code in h264_slice.c:h264_field_start,
 | 
						|
             * which sets the invalid_gap flag when decoding.
 | 
						|
             */
 | 
						|
            .is_non_existing = pic->invalid_gap,
 | 
						|
        },
 | 
						|
    };
 | 
						|
 | 
						|
    *vkh264_ref = (VkVideoDecodeH264DpbSlotInfoKHR) {
 | 
						|
        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_DPB_SLOT_INFO_KHR,
 | 
						|
        .pStdReferenceInfo = h264_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 ? dpb_slot_index : 0,
 | 
						|
        .imageViewBinding = vkpic->img_view_ref,
 | 
						|
    };
 | 
						|
 | 
						|
    *ref_slot = (VkVideoReferenceSlotInfoKHR) {
 | 
						|
        .sType = VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR,
 | 
						|
        .pNext = vkh264_ref,
 | 
						|
        .slotIndex = dpb_slot_index,
 | 
						|
        .pPictureResource = ref,
 | 
						|
    };
 | 
						|
 | 
						|
    if (ref_src)
 | 
						|
        *ref_src = pic;
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
static StdVideoH264LevelIdc convert_to_vk_level_idc(int level_idc)
 | 
						|
{
 | 
						|
    switch (level_idc) {
 | 
						|
    case 10: return STD_VIDEO_H264_LEVEL_IDC_1_0;
 | 
						|
    case 11: return STD_VIDEO_H264_LEVEL_IDC_1_1;
 | 
						|
    case 12: return STD_VIDEO_H264_LEVEL_IDC_1_2;
 | 
						|
    case 13: return STD_VIDEO_H264_LEVEL_IDC_1_3;
 | 
						|
    case 20: return STD_VIDEO_H264_LEVEL_IDC_2_0;
 | 
						|
    case 21: return STD_VIDEO_H264_LEVEL_IDC_2_1;
 | 
						|
    case 22: return STD_VIDEO_H264_LEVEL_IDC_2_2;
 | 
						|
    case 30: return STD_VIDEO_H264_LEVEL_IDC_3_0;
 | 
						|
    case 31: return STD_VIDEO_H264_LEVEL_IDC_3_1;
 | 
						|
    case 32: return STD_VIDEO_H264_LEVEL_IDC_3_2;
 | 
						|
    case 40: return STD_VIDEO_H264_LEVEL_IDC_4_0;
 | 
						|
    case 41: return STD_VIDEO_H264_LEVEL_IDC_4_1;
 | 
						|
    case 42: return STD_VIDEO_H264_LEVEL_IDC_4_2;
 | 
						|
    case 50: return STD_VIDEO_H264_LEVEL_IDC_5_0;
 | 
						|
    case 51: return STD_VIDEO_H264_LEVEL_IDC_5_1;
 | 
						|
    case 52: return STD_VIDEO_H264_LEVEL_IDC_5_2;
 | 
						|
    case 60: return STD_VIDEO_H264_LEVEL_IDC_6_0;
 | 
						|
    case 61: return STD_VIDEO_H264_LEVEL_IDC_6_1;
 | 
						|
    default:
 | 
						|
    case 62: return STD_VIDEO_H264_LEVEL_IDC_6_2;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void set_sps(const SPS *sps,
 | 
						|
                    StdVideoH264ScalingLists *vksps_scaling,
 | 
						|
                    StdVideoH264HrdParameters *vksps_vui_header,
 | 
						|
                    StdVideoH264SequenceParameterSetVui *vksps_vui,
 | 
						|
                    StdVideoH264SequenceParameterSet *vksps)
 | 
						|
{
 | 
						|
    *vksps_scaling = (StdVideoH264ScalingLists) {
 | 
						|
        .scaling_list_present_mask = sps->scaling_matrix_present_mask,
 | 
						|
        .use_default_scaling_matrix_mask = 0, /* We already fill in the default matrix */
 | 
						|
    };
 | 
						|
 | 
						|
    for (int i = 0; i < STD_VIDEO_H264_SCALING_LIST_4X4_NUM_LISTS; i++)
 | 
						|
        for (int j = 0; j < STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS; j++)
 | 
						|
            vksps_scaling->ScalingList4x4[i][j] = sps->scaling_matrix4[i][ff_zigzag_scan[j]];
 | 
						|
 | 
						|
    for (int i = 0; i < STD_VIDEO_H264_SCALING_LIST_8X8_NUM_LISTS; i++)
 | 
						|
        for (int j = 0; j < STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS; j++)
 | 
						|
            vksps_scaling->ScalingList8x8[i][j] =
 | 
						|
                sps->scaling_matrix8[h264_scaling_list8_order[i]][ff_zigzag_direct[j]];
 | 
						|
 | 
						|
    *vksps_vui_header = (StdVideoH264HrdParameters) {
 | 
						|
        .cpb_cnt_minus1 = sps->cpb_cnt - 1,
 | 
						|
        .bit_rate_scale = sps->bit_rate_scale,
 | 
						|
        .initial_cpb_removal_delay_length_minus1 = sps->initial_cpb_removal_delay_length - 1,
 | 
						|
        .cpb_removal_delay_length_minus1 = sps->cpb_removal_delay_length - 1,
 | 
						|
        .dpb_output_delay_length_minus1 = sps->dpb_output_delay_length - 1,
 | 
						|
        .time_offset_length = sps->time_offset_length,
 | 
						|
    };
 | 
						|
 | 
						|
    for (int i = 0; i < sps->cpb_cnt; i++) {
 | 
						|
        vksps_vui_header->bit_rate_value_minus1[i] = sps->bit_rate_value[i] - 1;
 | 
						|
        vksps_vui_header->cpb_size_value_minus1[i] = sps->cpb_size_value[i] - 1;
 | 
						|
        vksps_vui_header->cbr_flag[i] = (sps->cpr_flag >> i) & 0x1;
 | 
						|
    }
 | 
						|
 | 
						|
    *vksps_vui = (StdVideoH264SequenceParameterSetVui) {
 | 
						|
        .aspect_ratio_idc = sps->vui.aspect_ratio_idc,
 | 
						|
        .sar_width = sps->vui.sar.num,
 | 
						|
        .sar_height = sps->vui.sar.den,
 | 
						|
        .video_format = sps->vui.video_format,
 | 
						|
        .colour_primaries = sps->vui.colour_primaries,
 | 
						|
        .transfer_characteristics = sps->vui.transfer_characteristics,
 | 
						|
        .matrix_coefficients = sps->vui.matrix_coeffs,
 | 
						|
        .num_units_in_tick = sps->num_units_in_tick,
 | 
						|
        .time_scale = sps->time_scale,
 | 
						|
        .pHrdParameters = vksps_vui_header,
 | 
						|
        .max_num_reorder_frames = sps->num_reorder_frames,
 | 
						|
        .max_dec_frame_buffering = sps->max_dec_frame_buffering,
 | 
						|
        .flags = (StdVideoH264SpsVuiFlags) {
 | 
						|
            .aspect_ratio_info_present_flag = sps->vui.aspect_ratio_info_present_flag,
 | 
						|
            .overscan_info_present_flag = sps->vui.overscan_info_present_flag,
 | 
						|
            .overscan_appropriate_flag = sps->vui.overscan_appropriate_flag,
 | 
						|
            .video_signal_type_present_flag = sps->vui.video_signal_type_present_flag,
 | 
						|
            .video_full_range_flag = sps->vui.video_full_range_flag,
 | 
						|
            .color_description_present_flag = sps->vui.colour_description_present_flag,
 | 
						|
            .chroma_loc_info_present_flag = sps->vui.chroma_location,
 | 
						|
            .timing_info_present_flag = sps->timing_info_present_flag,
 | 
						|
            .fixed_frame_rate_flag = sps->fixed_frame_rate_flag,
 | 
						|
            .bitstream_restriction_flag = sps->bitstream_restriction_flag,
 | 
						|
            .nal_hrd_parameters_present_flag = sps->nal_hrd_parameters_present_flag,
 | 
						|
            .vcl_hrd_parameters_present_flag = sps->vcl_hrd_parameters_present_flag,
 | 
						|
        },
 | 
						|
    };
 | 
						|
 | 
						|
    *vksps = (StdVideoH264SequenceParameterSet) {
 | 
						|
        .profile_idc = sps->profile_idc,
 | 
						|
        .level_idc = convert_to_vk_level_idc(sps->level_idc),
 | 
						|
        .seq_parameter_set_id = sps->sps_id,
 | 
						|
        .chroma_format_idc = sps->chroma_format_idc,
 | 
						|
        .bit_depth_luma_minus8 = sps->bit_depth_luma - 8,
 | 
						|
        .bit_depth_chroma_minus8 = sps->bit_depth_chroma - 8,
 | 
						|
        .log2_max_frame_num_minus4 = sps->log2_max_frame_num - 4,
 | 
						|
        .pic_order_cnt_type = sps->poc_type,
 | 
						|
        .log2_max_pic_order_cnt_lsb_minus4 = sps->poc_type ? 0 : sps->log2_max_poc_lsb - 4,
 | 
						|
        .offset_for_non_ref_pic = sps->offset_for_non_ref_pic,
 | 
						|
        .offset_for_top_to_bottom_field = sps->offset_for_top_to_bottom_field,
 | 
						|
        .num_ref_frames_in_pic_order_cnt_cycle = sps->poc_cycle_length,
 | 
						|
        .max_num_ref_frames = sps->ref_frame_count,
 | 
						|
        .pic_width_in_mbs_minus1 = sps->mb_width - 1,
 | 
						|
        .pic_height_in_map_units_minus1 = (sps->mb_height/(2 - sps->frame_mbs_only_flag)) - 1,
 | 
						|
        .frame_crop_left_offset = sps->crop_left,
 | 
						|
        .frame_crop_right_offset = sps->crop_right,
 | 
						|
        .frame_crop_top_offset = sps->crop_top,
 | 
						|
        .frame_crop_bottom_offset = sps->crop_bottom,
 | 
						|
        .flags = (StdVideoH264SpsFlags) {
 | 
						|
            .constraint_set0_flag = (sps->constraint_set_flags >> 0) & 0x1,
 | 
						|
            .constraint_set1_flag = (sps->constraint_set_flags >> 1) & 0x1,
 | 
						|
            .constraint_set2_flag = (sps->constraint_set_flags >> 2) & 0x1,
 | 
						|
            .constraint_set3_flag = (sps->constraint_set_flags >> 3) & 0x1,
 | 
						|
            .constraint_set4_flag = (sps->constraint_set_flags >> 4) & 0x1,
 | 
						|
            .constraint_set5_flag = (sps->constraint_set_flags >> 5) & 0x1,
 | 
						|
            .direct_8x8_inference_flag = sps->direct_8x8_inference_flag,
 | 
						|
            .mb_adaptive_frame_field_flag = sps->mb_aff,
 | 
						|
            .frame_mbs_only_flag = sps->frame_mbs_only_flag,
 | 
						|
            .delta_pic_order_always_zero_flag = sps->delta_pic_order_always_zero_flag,
 | 
						|
            .separate_colour_plane_flag = sps->residual_color_transform_flag,
 | 
						|
            .gaps_in_frame_num_value_allowed_flag = sps->gaps_in_frame_num_allowed_flag,
 | 
						|
            .qpprime_y_zero_transform_bypass_flag = sps->transform_bypass,
 | 
						|
            .frame_cropping_flag = sps->crop,
 | 
						|
            .seq_scaling_matrix_present_flag = sps->scaling_matrix_present,
 | 
						|
            .vui_parameters_present_flag = sps->vui_parameters_present_flag,
 | 
						|
        },
 | 
						|
        .pOffsetForRefFrame = sps->offset_for_ref_frame,
 | 
						|
        .pScalingLists = vksps_scaling,
 | 
						|
        .pSequenceParameterSetVui = vksps_vui,
 | 
						|
    };
 | 
						|
}
 | 
						|
 | 
						|
static void set_pps(const PPS *pps, const SPS *sps,
 | 
						|
                    StdVideoH264ScalingLists *vkpps_scaling,
 | 
						|
                    StdVideoH264PictureParameterSet *vkpps)
 | 
						|
{
 | 
						|
    *vkpps_scaling = (StdVideoH264ScalingLists) {
 | 
						|
        .scaling_list_present_mask = pps->pic_scaling_matrix_present_mask,
 | 
						|
        .use_default_scaling_matrix_mask = 0, /* We already fill in the default matrix */
 | 
						|
    };
 | 
						|
 | 
						|
    for (int i = 0; i < STD_VIDEO_H264_SCALING_LIST_4X4_NUM_LISTS; i++)
 | 
						|
        for (int j = 0; j < STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS; j++)
 | 
						|
            vkpps_scaling->ScalingList4x4[i][j] = pps->scaling_matrix4[i][ff_zigzag_scan[j]];
 | 
						|
 | 
						|
    for (int i = 0; i < STD_VIDEO_H264_SCALING_LIST_8X8_NUM_LISTS; i++)
 | 
						|
        for (int j = 0; j < STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS; j++)
 | 
						|
            vkpps_scaling->ScalingList8x8[i][j] =
 | 
						|
                pps->scaling_matrix8[h264_scaling_list8_order[i]][ff_zigzag_direct[j]];
 | 
						|
 | 
						|
    *vkpps = (StdVideoH264PictureParameterSet) {
 | 
						|
        .seq_parameter_set_id = pps->sps_id,
 | 
						|
        .pic_parameter_set_id = pps->pps_id,
 | 
						|
        .num_ref_idx_l0_default_active_minus1 = pps->ref_count[0] - 1,
 | 
						|
        .num_ref_idx_l1_default_active_minus1 = pps->ref_count[1] - 1,
 | 
						|
        .weighted_bipred_idc = pps->weighted_bipred_idc,
 | 
						|
        .pic_init_qp_minus26 = pps->init_qp - 26,
 | 
						|
        .pic_init_qs_minus26 = pps->init_qs - 26,
 | 
						|
        .chroma_qp_index_offset = pps->chroma_qp_index_offset[0],
 | 
						|
        .second_chroma_qp_index_offset = pps->chroma_qp_index_offset[1],
 | 
						|
        .flags = (StdVideoH264PpsFlags) {
 | 
						|
            .transform_8x8_mode_flag = pps->transform_8x8_mode,
 | 
						|
            .redundant_pic_cnt_present_flag = pps->redundant_pic_cnt_present,
 | 
						|
            .constrained_intra_pred_flag = pps->constrained_intra_pred,
 | 
						|
            .deblocking_filter_control_present_flag = pps->deblocking_filter_parameters_present,
 | 
						|
            .weighted_pred_flag = pps->weighted_pred,
 | 
						|
            .bottom_field_pic_order_in_frame_present_flag = pps->pic_order_present,
 | 
						|
            .entropy_coding_mode_flag = pps->cabac,
 | 
						|
            .pic_scaling_matrix_present_flag = pps->pic_scaling_matrix_present_flag,
 | 
						|
        },
 | 
						|
        .pScalingLists = vkpps_scaling,
 | 
						|
    };
 | 
						|
}
 | 
						|
 | 
						|
static int vk_h264_create_params(AVCodecContext *avctx, AVBufferRef **buf)
 | 
						|
{
 | 
						|
    int err;
 | 
						|
    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
 | 
						|
    FFVulkanDecodeShared *ctx = dec->shared_ctx;
 | 
						|
    const H264Context *h = avctx->priv_data;
 | 
						|
 | 
						|
    /* SPS */
 | 
						|
    StdVideoH264ScalingLists vksps_scaling[MAX_SPS_COUNT];
 | 
						|
    StdVideoH264HrdParameters vksps_vui_header[MAX_SPS_COUNT];
 | 
						|
    StdVideoH264SequenceParameterSetVui vksps_vui[MAX_SPS_COUNT];
 | 
						|
    StdVideoH264SequenceParameterSet vksps[MAX_SPS_COUNT];
 | 
						|
 | 
						|
    /* PPS */
 | 
						|
    StdVideoH264ScalingLists vkpps_scaling[MAX_PPS_COUNT];
 | 
						|
    StdVideoH264PictureParameterSet vkpps[MAX_PPS_COUNT];
 | 
						|
 | 
						|
    VkVideoDecodeH264SessionParametersAddInfoKHR h264_params_info = {
 | 
						|
        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_ADD_INFO_KHR,
 | 
						|
        .pStdSPSs = vksps,
 | 
						|
        .stdSPSCount = 0,
 | 
						|
        .pStdPPSs = vkpps,
 | 
						|
        .stdPPSCount = 0,
 | 
						|
    };
 | 
						|
    VkVideoDecodeH264SessionParametersCreateInfoKHR h264_params = {
 | 
						|
        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR,
 | 
						|
        .pParametersAddInfo = &h264_params_info,
 | 
						|
    };
 | 
						|
    VkVideoSessionParametersCreateInfoKHR session_params_create = {
 | 
						|
        .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR,
 | 
						|
        .pNext = &h264_params,
 | 
						|
        .videoSession = ctx->common.session,
 | 
						|
        .videoSessionParametersTemplate = VK_NULL_HANDLE,
 | 
						|
    };
 | 
						|
 | 
						|
    /* SPS list */
 | 
						|
    for (int i = 0; i < FF_ARRAY_ELEMS(h->ps.sps_list); i++) {
 | 
						|
        if (h->ps.sps_list[i]) {
 | 
						|
            const SPS *sps_l = h->ps.sps_list[i];
 | 
						|
            int idx = h264_params_info.stdSPSCount;
 | 
						|
            set_sps(sps_l, &vksps_scaling[idx], &vksps_vui_header[idx], &vksps_vui[idx], &vksps[idx]);
 | 
						|
            h264_params_info.stdSPSCount++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /* PPS list */
 | 
						|
    for (int i = 0; i < FF_ARRAY_ELEMS(h->ps.pps_list); i++) {
 | 
						|
        if (h->ps.pps_list[i]) {
 | 
						|
            const PPS *pps_l = h->ps.pps_list[i];
 | 
						|
            int idx = h264_params_info.stdPPSCount;
 | 
						|
            set_pps(pps_l, pps_l->sps, &vkpps_scaling[idx], &vkpps[idx]);
 | 
						|
            h264_params_info.stdPPSCount++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    h264_params.maxStdSPSCount = h264_params_info.stdSPSCount;
 | 
						|
    h264_params.maxStdPPSCount = h264_params_info.stdPPSCount;
 | 
						|
 | 
						|
    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\n",
 | 
						|
           h264_params_info.stdSPSCount, h264_params_info.stdPPSCount);
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
static int vk_h264_start_frame(AVCodecContext          *avctx,
 | 
						|
                               av_unused const uint8_t *buffer,
 | 
						|
                               av_unused uint32_t       size)
 | 
						|
{
 | 
						|
    int err;
 | 
						|
    int dpb_slot_index = 0;
 | 
						|
    H264Context *h = avctx->priv_data;
 | 
						|
    H264Picture *pic = h->cur_pic_ptr;
 | 
						|
    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
 | 
						|
    H264VulkanDecodePicture *hp = pic->hwaccel_picture_private;
 | 
						|
    FFVulkanDecodePicture *vp = &hp->vp;
 | 
						|
 | 
						|
    if (!dec->session_params) {
 | 
						|
        err = vk_h264_create_params(avctx, &dec->session_params);
 | 
						|
        if (err < 0)
 | 
						|
            return err;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Fill in main slot */
 | 
						|
    dpb_slot_index = 0;
 | 
						|
    for (unsigned slot = 0; slot < H264_MAX_PICTURE_COUNT; slot++) {
 | 
						|
        if (pic == &h->DPB[slot]) {
 | 
						|
            dpb_slot_index = slot;
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    err = vk_h264_fill_pict(avctx, NULL, &vp->ref_slot, &vp->ref,
 | 
						|
                            &hp->vkh264_ref, &hp->h264_ref, pic, 1,
 | 
						|
                            h->DPB[dpb_slot_index].field_picture,
 | 
						|
                            h->DPB[dpb_slot_index].reference,
 | 
						|
                            dpb_slot_index);
 | 
						|
    if (err < 0)
 | 
						|
        return err;
 | 
						|
 | 
						|
    /* Fill in short-term references */
 | 
						|
    for (int i = 0; i < h->short_ref_count; i++) {
 | 
						|
        dpb_slot_index = 0;
 | 
						|
        for (unsigned slot = 0; slot < H264_MAX_PICTURE_COUNT; slot++) {
 | 
						|
            if (h->short_ref[i] == &h->DPB[slot]) {
 | 
						|
                dpb_slot_index = slot;
 | 
						|
                break;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        err = vk_h264_fill_pict(avctx, &hp->ref_src[i], &vp->ref_slots[i],
 | 
						|
                                &vp->refs[i], &hp->vkh264_refs[i],
 | 
						|
                                &hp->h264_refs[i], h->short_ref[i], 0,
 | 
						|
                                h->DPB[dpb_slot_index].field_picture,
 | 
						|
                                h->DPB[dpb_slot_index].reference,
 | 
						|
                                dpb_slot_index);
 | 
						|
        if (err < 0)
 | 
						|
            return err;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Fill in long-term refs */
 | 
						|
    for (int r = 0, i = h->short_ref_count; r < H264_MAX_DPB_FRAMES &&
 | 
						|
         i < h->short_ref_count + h->long_ref_count; r++) {
 | 
						|
        if (!h->long_ref[r])
 | 
						|
            continue;
 | 
						|
 | 
						|
        dpb_slot_index = 0;
 | 
						|
        for (unsigned slot = 0; slot < 16; slot++) {
 | 
						|
            if (h->long_ref[r] == &h->DPB[slot]) {
 | 
						|
                dpb_slot_index = slot;
 | 
						|
                break;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        err = vk_h264_fill_pict(avctx, &hp->ref_src[i], &vp->ref_slots[i],
 | 
						|
                                &vp->refs[i], &hp->vkh264_refs[i],
 | 
						|
                                &hp->h264_refs[i], h->long_ref[r], 0,
 | 
						|
                                h->DPB[dpb_slot_index].field_picture,
 | 
						|
                                h->DPB[dpb_slot_index].reference,
 | 
						|
                                dpb_slot_index);
 | 
						|
        if (err < 0)
 | 
						|
            return err;
 | 
						|
        i++;
 | 
						|
    }
 | 
						|
 | 
						|
    hp->h264pic = (StdVideoDecodeH264PictureInfo) {
 | 
						|
        .seq_parameter_set_id = pic->pps->sps_id,
 | 
						|
        .pic_parameter_set_id = pic->pps->pps_id,
 | 
						|
        .frame_num = 0,  /* Set later */
 | 
						|
        .idr_pic_id = 0, /* Set later */
 | 
						|
        .PicOrderCnt[0] = pic->field_poc[0],
 | 
						|
        .PicOrderCnt[1] = pic->field_poc[1],
 | 
						|
        .flags = (StdVideoDecodeH264PictureInfoFlags) {
 | 
						|
            .field_pic_flag = FIELD_PICTURE(h),
 | 
						|
            .is_intra = 1, /* Set later */
 | 
						|
            .IdrPicFlag = h->picture_idr,
 | 
						|
            .bottom_field_flag = h->picture_structure != PICT_FRAME &&
 | 
						|
                                 h->picture_structure & PICT_BOTTOM_FIELD,
 | 
						|
            .is_reference = h->nal_ref_idc != 0,
 | 
						|
            .complementary_field_pair = h->first_field && FIELD_PICTURE(h),
 | 
						|
        },
 | 
						|
    };
 | 
						|
 | 
						|
    hp->h264_pic_info = (VkVideoDecodeH264PictureInfoKHR) {
 | 
						|
        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PICTURE_INFO_KHR,
 | 
						|
        .pStdPictureInfo = &hp->h264pic,
 | 
						|
    };
 | 
						|
 | 
						|
    vp->decode_info = (VkVideoDecodeInfoKHR) {
 | 
						|
        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR,
 | 
						|
        .pNext = &hp->h264_pic_info,
 | 
						|
        .flags = 0x0,
 | 
						|
        .pSetupReferenceSlot = &vp->ref_slot,
 | 
						|
        .referenceSlotCount = h->short_ref_count + h->long_ref_count,
 | 
						|
        .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_h264_decode_slice(AVCodecContext *avctx,
 | 
						|
                                const uint8_t  *data,
 | 
						|
                                uint32_t        size)
 | 
						|
{
 | 
						|
    const H264Context *h = avctx->priv_data;
 | 
						|
    const H264SliceContext *sl  = &h->slice_ctx[0];
 | 
						|
    H264VulkanDecodePicture *hp = h->cur_pic_ptr->hwaccel_picture_private;
 | 
						|
    FFVulkanDecodePicture *vp = &hp->vp;
 | 
						|
 | 
						|
    int err = ff_vk_decode_add_slice(avctx, vp, data, size, 1,
 | 
						|
                                     &hp->h264_pic_info.sliceCount,
 | 
						|
                                     &hp->h264_pic_info.pSliceOffsets);
 | 
						|
    if (err < 0)
 | 
						|
        return err;
 | 
						|
 | 
						|
    hp->h264pic.frame_num = sl->frame_num;
 | 
						|
    hp->h264pic.idr_pic_id = sl->idr_pic_id;
 | 
						|
 | 
						|
    /* Frame is only intra of all slices are marked as intra */
 | 
						|
    if (sl->slice_type != AV_PICTURE_TYPE_I && sl->slice_type != AV_PICTURE_TYPE_SI)
 | 
						|
        hp->h264pic.flags.is_intra = 0;
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
static int vk_h264_end_frame(AVCodecContext *avctx)
 | 
						|
{
 | 
						|
    const H264Context *h = avctx->priv_data;
 | 
						|
    H264Picture *pic = h->cur_pic_ptr;
 | 
						|
    H264VulkanDecodePicture *hp = pic->hwaccel_picture_private;
 | 
						|
    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
 | 
						|
    FFVulkanDecodePicture *vp = &hp->vp;
 | 
						|
    FFVulkanDecodePicture *rvp[H264_MAX_PICTURE_COUNT] = { 0 };
 | 
						|
    AVFrame *rav[H264_MAX_PICTURE_COUNT] = { 0 };
 | 
						|
 | 
						|
    if (!hp->h264_pic_info.sliceCount)
 | 
						|
        return 0;
 | 
						|
 | 
						|
    if (!vp->slices_buf)
 | 
						|
        return AVERROR(EINVAL);
 | 
						|
 | 
						|
    if (!dec->session_params) {
 | 
						|
        int err = vk_h264_create_params(avctx, &dec->session_params);
 | 
						|
        if (err < 0)
 | 
						|
            return err;
 | 
						|
 | 
						|
        hp->h264pic.seq_parameter_set_id = pic->pps->sps_id;
 | 
						|
        hp->h264pic.pic_parameter_set_id = pic->pps->pps_id;
 | 
						|
    }
 | 
						|
 | 
						|
    for (int i = 0; i < vp->decode_info.referenceSlotCount; i++) {
 | 
						|
        H264Picture *rp = hp->ref_src[i];
 | 
						|
        H264VulkanDecodePicture *rhp = rp->hwaccel_picture_private;
 | 
						|
 | 
						|
        rvp[i] = &rhp->vp;
 | 
						|
        rav[i] = hp->ref_src[i]->f;
 | 
						|
    }
 | 
						|
 | 
						|
    av_log(avctx, AV_LOG_VERBOSE, "Decoding frame, %"SIZE_SPECIFIER" bytes, %i slices\n",
 | 
						|
           vp->slices_size, hp->h264_pic_info.sliceCount);
 | 
						|
 | 
						|
    return ff_vk_decode_frame(avctx, pic->f, vp, rav, rvp);
 | 
						|
}
 | 
						|
 | 
						|
static void vk_h264_free_frame_priv(FFRefStructOpaque _hwctx, void *data)
 | 
						|
{
 | 
						|
    AVHWDeviceContext *hwctx = _hwctx.nc;
 | 
						|
    H264VulkanDecodePicture *hp = data;
 | 
						|
 | 
						|
    /* Free frame resources, this also destroys the session parameters. */
 | 
						|
    ff_vk_decode_free_frame(hwctx, &hp->vp);
 | 
						|
}
 | 
						|
 | 
						|
const FFHWAccel ff_h264_vulkan_hwaccel = {
 | 
						|
    .p.name                = "h264_vulkan",
 | 
						|
    .p.type                = AVMEDIA_TYPE_VIDEO,
 | 
						|
    .p.id                  = AV_CODEC_ID_H264,
 | 
						|
    .p.pix_fmt             = AV_PIX_FMT_VULKAN,
 | 
						|
    .start_frame           = &vk_h264_start_frame,
 | 
						|
    .decode_slice          = &vk_h264_decode_slice,
 | 
						|
    .end_frame             = &vk_h264_end_frame,
 | 
						|
    .free_frame_priv       = &vk_h264_free_frame_priv,
 | 
						|
    .frame_priv_data_size  = sizeof(H264VulkanDecodePicture),
 | 
						|
    .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,
 | 
						|
};
 |