diff --git a/src/vulkan/runtime/vk_video.c b/src/vulkan/runtime/vk_video.c index ae387d20bce..e274b1db81f 100644 --- a/src/vulkan/runtime/vk_video.c +++ b/src/vulkan/runtime/vk_video.c @@ -26,6 +26,7 @@ #include "vk_log.h" #include "vk_alloc.h" #include "vk_device.h" +#include "util/vl_rbsp.h" VkResult vk_video_session_init(struct vk_device *device, @@ -366,3 +367,401 @@ vk_video_find_h265_dec_std_pps(const struct vk_video_session_parameters *params, { return find_h265_dec_std_pps(params, id); } + +static void +h265_pred_weight_table(struct vk_video_h265_slice_params *params, + struct vl_rbsp *rbsp, + const StdVideoH265SequenceParameterSet *sps, + StdVideoH265SliceType slice_type) +{ + unsigned chroma_array_type = sps->flags.separate_colour_plane_flag ? 0 : sps->chroma_format_idc; + unsigned i, j; + + params->luma_log2_weight_denom = vl_rbsp_ue(rbsp); + + assert(params->luma_log2_weight_denom >= 0 && params->luma_log2_weight_denom < 8); + + if (chroma_array_type != 0) { + params->chroma_log2_weight_denom = params->luma_log2_weight_denom + vl_rbsp_se(rbsp); + assert(params->chroma_log2_weight_denom >= 0 && params->chroma_log2_weight_denom < 8); + } + + for (i = 0; i < params->num_ref_idx_l0_active; ++i) { + params->luma_weight_l0_flag[i] = vl_rbsp_u(rbsp, 1); + if (!params->luma_weight_l0_flag[i]) { + params->luma_weight_l0[i] = 1 << params->luma_log2_weight_denom; + params->luma_offset_l0[i] = 0; + } + } + + for (i = 0; i < params->num_ref_idx_l0_active; ++i) { + if (chroma_array_type == 0) { + params->chroma_weight_l0_flag[i] = 0; + } else { + params->chroma_weight_l0_flag[i] = vl_rbsp_u(rbsp, 1); + } + } + + for (i = 0; i < params->num_ref_idx_l0_active; ++i) { + if (params->luma_weight_l0_flag[i]) { + unsigned delta_luma_weight_l0 = vl_rbsp_se(rbsp); + params->luma_weight_l0[i] = (1 << params->luma_log2_weight_denom) + delta_luma_weight_l0; + params->luma_offset_l0[i] = vl_rbsp_se(rbsp); + } + + if (params->chroma_weight_l0_flag[i]) { + for (j = 0; j < 2; j++) { + unsigned delta_chroma_weight_l0 = vl_rbsp_se(rbsp); + unsigned delta_chroma_offset_l0 = vl_rbsp_se(rbsp); + + params->chroma_weight_l0[i][j] = (1 << params->chroma_log2_weight_denom) + delta_chroma_weight_l0; + params->chroma_offset_l0[i][j] = delta_chroma_offset_l0 - + ((128 * params->chroma_weight_l0[i][j]) >> params->chroma_log2_weight_denom) + 128; + } + } else { + for (j = 0; j < 2; j++) { + params->chroma_weight_l0[i][j] = 1 << params->chroma_log2_weight_denom; + params->chroma_offset_l0[i][j] = 0; + } + } + } + + if (slice_type == STD_VIDEO_H265_SLICE_TYPE_B) { + for (i = 0; i < params->num_ref_idx_l1_active; ++i) { + params->luma_weight_l1_flag[i] = vl_rbsp_u(rbsp, 1); + if (!params->luma_weight_l1_flag[i]) { + params->luma_weight_l1[i] = 1 << params->luma_log2_weight_denom; + params->luma_offset_l1[i] = 0; + } + } + + for (i = 0; i < params->num_ref_idx_l1_active; ++i) { + if (chroma_array_type == 0) { + params->chroma_weight_l1_flag[i] = 0; + } else { + params->chroma_weight_l1_flag[i] = vl_rbsp_u(rbsp, 1); + } + } + + for (i = 0; i < params->num_ref_idx_l1_active; ++i) { + if (params->luma_weight_l1_flag[i]) { + unsigned delta_luma_weight_l1 = vl_rbsp_se(rbsp); + params->luma_weight_l1[i] = (1 << params->luma_log2_weight_denom) + delta_luma_weight_l1; + params->luma_offset_l1[i] = vl_rbsp_se(rbsp); + } + + if (params->chroma_weight_l1_flag[i]) { + for (j = 0; j < 2; j++) { + unsigned delta_chroma_weight_l1 = vl_rbsp_se(rbsp); + unsigned delta_chroma_offset_l1 = vl_rbsp_se(rbsp); + + params->chroma_weight_l1[i][j] = (1 << params->chroma_log2_weight_denom) + delta_chroma_weight_l1; + params->chroma_offset_l1[i][j] = delta_chroma_offset_l1 - + ((128 * params->chroma_weight_l1[i][j]) >> params->chroma_log2_weight_denom) + 128; + } + } else { + for (j = 0; j < 2; j++) { + params->chroma_weight_l1[i][j] = 1 << params->chroma_log2_weight_denom; + params->chroma_offset_l1[i][j] = 0; + } + } + } + } +} + +void +vk_video_parse_h265_slice_header(const struct VkVideoDecodeInfoKHR *frame_info, + const VkVideoDecodeH265PictureInfoKHR *pic_info, + const StdVideoH265SequenceParameterSet *sps, + const StdVideoH265PictureParameterSet *pps, + void *slice_data, + uint32_t slice_size, + struct vk_video_h265_slice_params *params) +{ + struct vl_vlc vlc; + const void *slice_headers[1] = { slice_data }; + vl_vlc_init(&vlc, 1, slice_headers, &slice_size); + + assert(vl_vlc_peekbits(&vlc, 24) == 0x000001); + + vl_vlc_eatbits(&vlc, 24); + + /* forbidden_zero_bit */ + vl_vlc_eatbits(&vlc, 1); + + if (vl_vlc_valid_bits(&vlc) < 15) + vl_vlc_fillbits(&vlc); + + vl_vlc_get_uimsbf(&vlc, 6); /* nal_unit_type */ + vl_vlc_get_uimsbf(&vlc, 6); /* nuh_layer_id */ + vl_vlc_get_uimsbf(&vlc, 3); /* nuh_temporal_id_plus1 */ + + struct vl_rbsp rbsp; + vl_rbsp_init(&rbsp, &vlc, 128); + + memset(params, 0, sizeof(*params)); + + params->slice_size = slice_size; + params->first_slice_segment_in_pic_flag = vl_rbsp_u(&rbsp, 1); + + /* no_output_of_prior_pics_flag */ + if (pic_info->pStdPictureInfo->flags.IrapPicFlag) + vl_rbsp_u(&rbsp, 1); + + /* pps id */ + vl_rbsp_ue(&rbsp); + + if (!params->first_slice_segment_in_pic_flag) { + int size, num; + int bits_slice_segment_address = 0; + + if (pps->flags.dependent_slice_segments_enabled_flag) + params->dependent_slice_segment = vl_rbsp_u(&rbsp, 1); + + size = 1 << (sps->log2_min_luma_coding_block_size_minus3 + 3 + + sps->log2_diff_max_min_luma_coding_block_size); + + num = ((sps->pic_width_in_luma_samples + size - 1) / size) * + ((sps->pic_height_in_luma_samples + size - 1) / size); + + while (num > (1 << bits_slice_segment_address)) + bits_slice_segment_address++; + + /* slice_segment_address */ + params->slice_segment_address = vl_rbsp_u(&rbsp, bits_slice_segment_address); + } + + if (params->dependent_slice_segment) + return; + + for (unsigned i = 0; i < pps->num_extra_slice_header_bits; ++i) + /* slice_reserved_flag */ + vl_rbsp_u(&rbsp, 1); + + /* slice_type */ + params->slice_type = vl_rbsp_ue(&rbsp); + + if (pps->flags.output_flag_present_flag) + /* pic output flag */ + vl_rbsp_u(&rbsp, 1); + + if (sps->flags.separate_colour_plane_flag) + /* colour_plane_id */ + vl_rbsp_u(&rbsp, 2); + + if (!pic_info->pStdPictureInfo->flags.IdrPicFlag) { + /* slice_pic_order_cnt_lsb */ + params->pic_order_cnt_lsb = + vl_rbsp_u(&rbsp, sps->log2_max_pic_order_cnt_lsb_minus4 + 4); + + /* short_term_ref_pic_set_sps_flag */ + if (!vl_rbsp_u(&rbsp, 1)) { + uint8_t rps_predict = 0; + + if (sps->num_short_term_ref_pic_sets) + rps_predict = vl_rbsp_u(&rbsp, 1); + + if (rps_predict) { + /* delta_idx */ + vl_rbsp_ue(&rbsp); + /* delta_rps_sign */ + vl_rbsp_u(&rbsp, 1); + /* abs_delta_rps */ + vl_rbsp_ue(&rbsp); + + for (int i = 0 ; i <= pic_info->pStdPictureInfo->NumDeltaPocsOfRefRpsIdx; i++) { + uint8_t used = vl_rbsp_u(&rbsp, 1); + if (!used) + vl_rbsp_u(&rbsp, 1); + } + } else { + /* num_negative_pics */ + unsigned num_neg_pics = vl_rbsp_ue(&rbsp); + /* num_positive_pics */ + unsigned num_pos_pics = vl_rbsp_ue(&rbsp); + + for(unsigned i = 0 ; i < num_neg_pics; ++i) { + /* delta_poc_s0_minus1 */ + vl_rbsp_ue(&rbsp); + /* used_by_curr_pic_s0_flag */ + vl_rbsp_u(&rbsp, 1); + } + + for(unsigned i = 0; i < num_pos_pics; ++i) { + /* delta_poc_s1_minus1 */ + vl_rbsp_ue(&rbsp); + /* used_by_curr_pic_s0_flag */ + vl_rbsp_u(&rbsp, 1); + } + } + + if (sps->flags.long_term_ref_pics_present_flag) { + unsigned num_lt_sps = 0; + + if (sps->num_long_term_ref_pics_sps > 0) + num_lt_sps = vl_rbsp_ue(&rbsp); + + unsigned num_lt_pics = vl_rbsp_ue(&rbsp); + unsigned num_refs = num_lt_pics + num_lt_sps; + + for (unsigned i = 0; i < num_refs; i++) { + if (i < num_lt_sps) { + if (sps->num_long_term_ref_pics_sps > 1) + /* lt_idx_sps */ + vl_rbsp_u(&rbsp, + util_logbase2_ceil(sps->num_long_term_ref_pics_sps)); + } else { + /* poc_lsb_lt */ + vl_rbsp_u(&rbsp, sps->log2_max_pic_order_cnt_lsb_minus4 + 4); + /* used_by_curr_pic_lt_flag */ + vl_rbsp_u(&rbsp, 1); + } + + /* poc_msb_present */ + if (vl_rbsp_u(&rbsp, 1)) { + /* delta_poc_msb_cycle_lt */ + vl_rbsp_ue(&rbsp); + } + } + } + } else { + unsigned num_st_rps = sps->num_short_term_ref_pic_sets; + + int numbits = util_logbase2_ceil(num_st_rps); + if (numbits > 0) + /* short_term_ref_pic_set_idx */ + vl_rbsp_u(&rbsp, numbits); + } + + + if (sps->flags.sps_temporal_mvp_enabled_flag) + params->temporal_mvp_enable = vl_rbsp_u(&rbsp, 1); + } + + if (sps->flags.sample_adaptive_offset_enabled_flag) { + params->sao_luma_flag = vl_rbsp_u(&rbsp, 1); + if (sps->chroma_format_idc) + params->sao_chroma_flag = vl_rbsp_u(&rbsp, 1); + } + + params->max_num_merge_cand = 5; + + if (params->slice_type != STD_VIDEO_H265_SLICE_TYPE_I) { + + params->num_ref_idx_l0_active = pps->num_ref_idx_l0_default_active_minus1 + 1; + + if (params->slice_type == STD_VIDEO_H265_SLICE_TYPE_B) + params->num_ref_idx_l1_active = pps->num_ref_idx_l1_default_active_minus1 + 1; + else + params->num_ref_idx_l1_active = 0; + + /* num_ref_idx_active_override_flag */ + if (vl_rbsp_u(&rbsp, 1)) { + params->num_ref_idx_l0_active = vl_rbsp_ue(&rbsp) + 1; + if (params->slice_type == STD_VIDEO_H265_SLICE_TYPE_B) + params->num_ref_idx_l1_active = vl_rbsp_ue(&rbsp) + 1; + } + + if (pps->flags.lists_modification_present_flag) { + params->rpl_modification_flag[0] = vl_rbsp_u(&rbsp, 1); + if (params->rpl_modification_flag[0]) { + for (int i = 0; i < params->num_ref_idx_l0_active; i++) { + /* list_entry_l0 */ + vl_rbsp_u(&rbsp, + util_logbase2_ceil(params->num_ref_idx_l0_active + params->num_ref_idx_l1_active)); + } + } + + if (params->slice_type == STD_VIDEO_H265_SLICE_TYPE_B) { + params->rpl_modification_flag[1] = vl_rbsp_u(&rbsp, 1); + if (params->rpl_modification_flag[1]) { + for (int i = 0; i < params->num_ref_idx_l1_active; i++) { + /* list_entry_l1 */ + vl_rbsp_u(&rbsp, + util_logbase2_ceil(params->num_ref_idx_l0_active + params->num_ref_idx_l1_active)); + } + } + } + } + + if (params->slice_type == STD_VIDEO_H265_SLICE_TYPE_B) + params->mvd_l1_zero_flag = vl_rbsp_u(&rbsp, 1); + + if (pps->flags.cabac_init_present_flag) + /* cabac_init_flag */ + params->cabac_init_idc = vl_rbsp_u(&rbsp, 1); + + if (params->temporal_mvp_enable) { + if (params->slice_type == STD_VIDEO_H265_SLICE_TYPE_B) + params->collocated_list = !vl_rbsp_u(&rbsp, 1); + + if (params->collocated_list == 0) { + if (params->num_ref_idx_l0_active > 1) + params->collocated_ref_idx = vl_rbsp_ue(&rbsp); + } else if (params->collocated_list == 1) { + if (params->num_ref_idx_l1_active > 1) + params->collocated_ref_idx = vl_rbsp_ue(&rbsp); + } + } + + if ((pps->flags.weighted_pred_flag && params->slice_type == STD_VIDEO_H265_SLICE_TYPE_P) || + (pps->flags.weighted_bipred_flag && params->slice_type == STD_VIDEO_H265_SLICE_TYPE_B)) { + h265_pred_weight_table(params, &rbsp, sps, params->slice_type); + } + + params->max_num_merge_cand -= vl_rbsp_ue(&rbsp); + } + + params->slice_qp_delta = vl_rbsp_se(&rbsp); + + if (pps->flags.pps_slice_chroma_qp_offsets_present_flag) { + params->slice_cb_qp_offset = vl_rbsp_se(&rbsp); + params->slice_cr_qp_offset = vl_rbsp_se(&rbsp); + } + + if (pps->flags.chroma_qp_offset_list_enabled_flag) + /* cu_chroma_qp_offset_enabled_flag */ + vl_rbsp_u(&rbsp, 1); + + if (pps->flags.deblocking_filter_control_present_flag) { + if (pps->flags.deblocking_filter_override_enabled_flag) { + /* deblocking_filter_override_flag */ + if (vl_rbsp_u(&rbsp, 1)) { + params->disable_deblocking_filter_idc = vl_rbsp_u(&rbsp, 1); + + if (!params->disable_deblocking_filter_idc) { + params->beta_offset_div2 = vl_rbsp_se(&rbsp); + params->tc_offset_div2 = vl_rbsp_se(&rbsp); + } + } else { + params->disable_deblocking_filter_idc = + pps->flags.pps_deblocking_filter_disabled_flag; + } + } + } + + if (pps->flags.pps_loop_filter_across_slices_enabled_flag) + params->loop_filter_across_slices_enable = vl_rbsp_u(&rbsp, 1); + + if (pps->flags.tiles_enabled_flag || pps->flags.entropy_coding_sync_enabled_flag) { + unsigned num_entry_points_offsets = vl_rbsp_ue(&rbsp); + + if (num_entry_points_offsets > 0) { + unsigned offset_len = vl_rbsp_ue(&rbsp) + 1; + for (unsigned i = 0; i < num_entry_points_offsets; i++) { + /* entry_point_offset_minus1 */ + vl_rbsp_u(&rbsp, offset_len); + } + } + } + + if (pps->flags.pps_extension_present_flag) { + unsigned length = vl_rbsp_ue(&rbsp); + for (unsigned i = 0; i < length; i++) + /* slice_reserved_undetermined_flag */ + vl_rbsp_u(&rbsp, 1); + } + + unsigned header_bits = (slice_size * 8 - 24 /* start code */) - vl_vlc_bits_left(&rbsp.nal); + params->slice_data_bytes_offset = (header_bits + 8) / 8; +} diff --git a/src/vulkan/runtime/vk_video.h b/src/vulkan/runtime/vk_video.h index c4641a59521..19cca6adb59 100644 --- a/src/vulkan/runtime/vk_video.h +++ b/src/vulkan/runtime/vk_video.h @@ -109,6 +109,60 @@ const StdVideoH265PictureParameterSet * vk_video_find_h265_dec_std_pps(const struct vk_video_session_parameters *params, uint32_t id); +struct vk_video_h265_slice_params { + uint32_t slice_size; + + uint8_t first_slice_segment_in_pic_flag; + StdVideoH265SliceType slice_type; + uint8_t dependent_slice_segment; + uint8_t temporal_mvp_enable; + uint8_t loop_filter_across_slices_enable; + int32_t pic_order_cnt_lsb; + uint8_t sao_luma_flag; + uint8_t sao_chroma_flag; + uint8_t collocated_list; + uint32_t collocated_ref_idx; + uint8_t mvd_l1_zero_flag; + + uint8_t num_ref_idx_l0_active; + uint8_t num_ref_idx_l1_active; + uint8_t rpl_modification_flag[2]; + uint8_t cabac_init_idc; + int8_t slice_qp_delta; + int8_t slice_cb_qp_offset; + int8_t slice_cr_qp_offset; + int8_t max_num_merge_cand; + uint32_t slice_data_bytes_offset; + uint8_t disable_deblocking_filter_idc; + int8_t tc_offset_div2; + int8_t beta_offset_div2; + uint32_t slice_segment_address; + + uint8_t luma_log2_weight_denom; + uint8_t chroma_log2_weight_denom; + uint8_t luma_weight_l0_flag[16]; + int16_t luma_weight_l0[16]; + int16_t luma_offset_l0[16]; + uint8_t chroma_weight_l0_flag[16]; + int16_t chroma_weight_l0[16][2]; + int16_t chroma_offset_l0[16][2]; + uint8_t luma_weight_l1_flag[16]; + int16_t luma_weight_l1[16]; + int16_t luma_offset_l1[16]; + uint8_t chroma_weight_l1_flag[16]; + int16_t chroma_weight_l1[16][2]; + int16_t chroma_offset_l1[16][2]; +}; + +void +vk_video_parse_h265_slice_header(const struct VkVideoDecodeInfoKHR *frame_info, + const VkVideoDecodeH265PictureInfoKHR *pic_info, + const StdVideoH265SequenceParameterSet *sps, + const StdVideoH265PictureParameterSet *pps, + void *slice_data, + uint32_t slice_size, + struct vk_video_h265_slice_params *params); + #ifdef __cplusplus } #endif