From 00127f16f1fd22cda409a33139ccd9ff76c627ef Mon Sep 17 00:00:00 2001 From: jeffqjiangNew <142832361+jeffqjiangNew@users.noreply.github.com> Date: Fri, 9 Feb 2024 15:09:49 -0500 Subject: [PATCH] Implemented proper slice parameter buffer submission for multiple slice streams. (#226) * * rocDecode: Implemented proper slice parameter buffer submission for multiple slice streams. - We were submitting single slice parameter buffer for multiple slice streams. This works for other APIs but not for VAAPI, which requires to send slice parameter buffer once per slice. - At step 1, all the multi-slice structures are fixed sized (256). Will make them dynamic in the next step. - With this change, all 135 HEVC conformance streams now pass. * * rocDecode: Multiple slice change step 2: make the fixed size slice info structure lists dynamic. * * rocDecode: Minor changes in comments. No functional changes. * *rocDecode: Changed INIT_SLICE_PARAM_LIST_NUM from 256 back to 16. 256 was set during debug process. * * rocDecode: Add suggest changes from code review. * * rocDecode: Moved slice_params_buf_id_ initialization to class VaapiVideoDecoder declaration, as suggested by code review. --- api/rocdecode.h | 9 +- src/parser/avc_parser.cpp | 11 +- src/parser/hevc_parser.cpp | 468 +++++++++++---------- src/parser/hevc_parser.h | 29 +- src/parser/roc_video_parser.h | 3 +- src/rocdecode/vaapi/vaapi_videodecoder.cpp | 29 +- src/rocdecode/vaapi/vaapi_videodecoder.h | 5 +- 7 files changed, 298 insertions(+), 256 deletions(-) diff --git a/api/rocdecode.h b/api/rocdecode.h index 303e616e11..20ce732a25 100644 --- a/api/rocdecode.h +++ b/api/rocdecode.h @@ -805,8 +805,7 @@ typedef struct _RocdecPicParams { uint32_t bitstream_data_len; /**< IN: Number of bytes in bitstream data buffer */ const uint8_t *bitstream_data; /**< IN: Ptr to bitstream data for this picture (slice-layer) */ uint32_t num_slices; /**< IN: Number of slices in this picture */ - const uint32_t *slice_data_offsets; /**< IN: num_slices entries, contains offset of each slice within - the bitstream data buffer */ + int ref_pic_flag; /**< IN: This picture is a reference picture */ int intra_pic_flag; /**< IN: This picture is entirely intra coded */ uint32_t reserved[30]; /**< Reserved for future use */ @@ -821,10 +820,12 @@ typedef struct _RocdecPicParams { uint32_t codec_reserved[256]; } pic_params; + /*! \brief Variable size array. The user should allocate one slice param struct for each slice. + */ union { // Todo: Add slice params defines for other codecs. - RocdecAvcSliceParams avc; - RocdecHevcSliceParams hevc; + RocdecAvcSliceParams *avc; + RocdecHevcSliceParams *hevc; } slice_params; union { diff --git a/src/parser/avc_parser.cpp b/src/parser/avc_parser.cpp index 12e0acdffe..da153c4153 100644 --- a/src/parser/avc_parser.cpp +++ b/src/parser/avc_parser.cpp @@ -92,7 +92,7 @@ ParserResult AvcVideoParser::ParsePictureData(const uint8_t *p_stream, uint32_t curr_start_code_offset_ = 0; next_start_code_offset_ = 0; - slice_num_ = 0; + num_slices_ = 0; sei_message_count_ = 0; sei_payload_size_ = 0; @@ -132,7 +132,7 @@ ParserResult AvcVideoParser::ParsePictureData(const uint8_t *p_stream, uint32_t memcpy(rbsp_buf_, (pic_data_buffer_ptr_ + curr_start_code_offset_ + 4), ebsp_size); rbsp_size_ = EbspToRbsp(rbsp_buf_, 0, ebsp_size); // For each picture, only parse the first slice header - if (slice_num_ == 0) { + if (num_slices_ == 0) { // Save slice NAL unit header slice_nal_unit_header_ = nal_unit_header_; @@ -168,7 +168,7 @@ ParserResult AvcVideoParser::ParsePictureData(const uint8_t *p_stream, uint32_t // Find a free buffer in DPB for the current picture FindFreeBufInDpb(); } - slice_num_++; + num_slices_++; break; } @@ -334,8 +334,7 @@ ParserResult AvcVideoParser::SendPicForDecode() { dec_pic_params_.bitstream_data_len = pic_stream_data_size_; dec_pic_params_.bitstream_data = pic_stream_data_ptr_; - dec_pic_params_.num_slices = slice_num_; - dec_pic_params_.slice_data_offsets = nullptr; + dec_pic_params_.num_slices = num_slices_; dec_pic_params_.ref_pic_flag = slice_nal_unit_header_.nal_ref_idc; dec_pic_params_.intra_pic_flag = p_slice_header->slice_type == kAvcSliceTypeI || p_slice_header->slice_type == kAvcSliceTypeI_7 || p_slice_header->slice_type == kAvcSliceTypeSI || p_slice_header->slice_type == kAvcSliceTypeSI_9; @@ -423,7 +422,7 @@ ParserResult AvcVideoParser::SendPicForDecode() { p_pic_param->frame_num = p_slice_header->frame_num; // Set up slice parameters - RocdecAvcSliceParams *p_slice_param = &dec_pic_params_.slice_params.avc; + RocdecAvcSliceParams *p_slice_param = dec_pic_params_.slice_params.avc; // Todo p_slice_param->slice_data_size = pic_stream_data_size_; p_slice_param->slice_data_offset = 0; diff --git a/src/parser/hevc_parser.cpp b/src/parser/hevc_parser.cpp index a860603735..7658814fa8 100644 --- a/src/parser/hevc_parser.cpp +++ b/src/parser/hevc_parser.cpp @@ -44,8 +44,9 @@ HevcVideoParser::HevcVideoParser() { m_vps_ = AllocStruct(MAX_VPS_COUNT); m_sps_ = AllocStruct(MAX_SPS_COUNT); m_pps_ = AllocStruct(MAX_PPS_COUNT); - m_sh_ = AllocStruct(1); m_sh_copy_ = AllocStruct(1); + slice_info_list_.assign(INIT_SLICE_LIST_NUM, {0}); + slice_param_list_.assign(INIT_SLICE_LIST_NUM, {0}); sei_rbsp_buf_ = nullptr; sei_rbsp_buf_size_ = 0; @@ -134,9 +135,6 @@ HevcVideoParser::~HevcVideoParser() { if (m_pps_) { delete [] m_pps_; } - if (m_sh_) { - delete m_sh_; - } if (m_sh_copy_) { delete m_sh_copy_; } @@ -274,11 +272,10 @@ int HevcVideoParser::SendPicForDecode() { dec_pic_params_.bitstream_data_len = pic_stream_data_size_; dec_pic_params_.bitstream_data = pic_stream_data_ptr_; - dec_pic_params_.num_slices = slice_num_; - dec_pic_params_.slice_data_offsets = nullptr; // Todo: do we need this? Remove if not. + dec_pic_params_.num_slices = num_slices_; dec_pic_params_.ref_pic_flag = 1; // HEVC decoded picture is always marked as short term at first. - dec_pic_params_.intra_pic_flag = m_sh_->slice_type == HEVC_SLICE_TYPE_I ? 1 : 0; + dec_pic_params_.intra_pic_flag = slice_info_list_[0].slice_header.slice_type == HEVC_SLICE_TYPE_I ? 1 : 0; // Todo: field_pic_flag, bottom_field_flag, second_field, ref_pic_flag, and intra_pic_flag seems to be associated with AVC/H.264. // Do we need them for general purpose? Reomve if not. @@ -361,7 +358,7 @@ int HevcVideoParser::SendPicForDecode() { pic_param_ptr->pic_fields.bits.loop_filter_across_tiles_enabled_flag = pps_ptr->loop_filter_across_tiles_enabled_flag; pic_param_ptr->pic_fields.bits.pcm_loop_filter_disabled_flag = sps_ptr->pcm_loop_filter_disabled_flag; pic_param_ptr->pic_fields.bits.no_pic_reordering_flag = sps_ptr->sps_max_num_reorder_pics[0] ? 0 : 1; - pic_param_ptr->pic_fields.bits.no_bi_pred_flag = m_sh_->slice_type == HEVC_SLICE_TYPE_B ? 0 : 1; + pic_param_ptr->pic_fields.bits.no_bi_pred_flag = slice_info_list_[0].slice_header.slice_type == HEVC_SLICE_TYPE_B ? 0 : 1; pic_param_ptr->sps_max_dec_pic_buffering_minus1 = sps_ptr->sps_max_dec_pic_buffering_minus1[sps_ptr->sps_max_sub_layers_minus1]; // HighestTid pic_param_ptr->bit_depth_luma_minus8 = sps_ptr->bit_depth_luma_minus8; @@ -406,7 +403,7 @@ int HevcVideoParser::SendPicForDecode() { pic_param_ptr->slice_parsing_fields.bits.slice_segment_header_extension_present_flag = pps_ptr->slice_segment_header_extension_present_flag; pic_param_ptr->slice_parsing_fields.bits.rap_pic_flag = IsIrapPic(&slice_nal_unit_header_) ? 1 : 0; pic_param_ptr->slice_parsing_fields.bits.idr_pic_flag = IsIdrPic(&slice_nal_unit_header_) ? 1 : 0; - pic_param_ptr->slice_parsing_fields.bits.intra_pic_flag = m_sh_->slice_type == HEVC_SLICE_TYPE_I ? 1 : 0; + pic_param_ptr->slice_parsing_fields.bits.intra_pic_flag = slice_info_list_[0].slice_header.slice_type == HEVC_SLICE_TYPE_I ? 1 : 0; pic_param_ptr->log2_max_pic_order_cnt_lsb_minus4 = sps_ptr->log2_max_pic_order_cnt_lsb_minus4; pic_param_ptr->num_short_term_ref_pic_sets = sps_ptr->num_short_term_ref_pic_sets; @@ -417,104 +414,113 @@ int HevcVideoParser::SendPicForDecode() { pic_param_ptr->pps_tc_offset_div2 = pps_ptr->pps_tc_offset_div2; pic_param_ptr->num_extra_slice_header_bits = pps_ptr->num_extra_slice_header_bits; - pic_param_ptr->st_rps_bits = m_sh_->short_term_ref_pic_set_size; + pic_param_ptr->st_rps_bits = slice_info_list_[0].slice_header.short_term_ref_pic_set_size; /// Fill slice parameters - RocdecHevcSliceParams *slice_params_ptr = &dec_pic_params_.slice_params.hevc; + // Resize if needed + if (num_slices_ > slice_param_list_.size()) { + slice_param_list_.resize(num_slices_, {0}); + } + for (int slice_index = 0; slice_index < num_slices_; slice_index++) { + RocdecHevcSliceParams *slice_params_ptr = &slice_param_list_[slice_index]; + HevcSliceInfo *p_slice_info = &slice_info_list_[slice_index]; + HevcSliceSegHeader *p_slice_header = &p_slice_info->slice_header; - // We put all slices into one slice data buffer. - slice_params_ptr->slice_data_size = pic_stream_data_size_; - slice_params_ptr->slice_data_offset = 0; // point to the start code - slice_params_ptr->slice_data_flag = 0x00; // VA_SLICE_DATA_FLAG_ALL; - slice_params_ptr->slice_data_byte_offset = 0; // VCN consumes from the start code - slice_params_ptr->slice_segment_address = m_sh_->slice_segment_address; + // We put all slices into one slice data buffer. + slice_params_ptr->slice_data_size = p_slice_info->slice_data_size; + slice_params_ptr->slice_data_offset = p_slice_info->slice_data_offset; // point to the start code + slice_params_ptr->slice_data_flag = 0x00; // VA_SLICE_DATA_FLAG_ALL; + slice_params_ptr->slice_data_byte_offset = 0; // VCN consumes from the start code + slice_params_ptr->slice_segment_address = p_slice_header->slice_segment_address; - // Ref lists - memset(slice_params_ptr->ref_pic_list, 0xFF, sizeof(slice_params_ptr->ref_pic_list)); - if (m_sh_->slice_type != HEVC_SLICE_TYPE_I) { - for (i = 0; i <= m_sh_->num_ref_idx_l0_active_minus1; i++) { - int idx = ref_pic_list_0_[i]; // pic_idx of the ref pic - for (j = 0; j < 15; j++) { - if (pic_param_ptr->ref_frames[j].pic_idx == idx) { - break; - } - } - if (j == 15) { - ERR("Could not find matching pic in ref_frames list. The slice type is P/B, and the idx from the ref_pic_list_0_ is: " + TOSTR(idx)); - return PARSER_FAIL; - } else { - slice_params_ptr->ref_pic_list[0][i] = j; - } - } - - if (m_sh_->slice_type == HEVC_SLICE_TYPE_B) { - for (i = 0; i <= m_sh_->num_ref_idx_l1_active_minus1; i++) { - int idx = ref_pic_list_1_[i]; // pic_idx of the ref pic + // Ref lists + memset(slice_params_ptr->ref_pic_list, 0xFF, sizeof(slice_params_ptr->ref_pic_list)); + if (p_slice_header->slice_type != HEVC_SLICE_TYPE_I) { + for (i = 0; i <= p_slice_header->num_ref_idx_l0_active_minus1; i++) { + int idx = p_slice_info->ref_pic_list_0_[i]; // pic_idx of the ref pic for (j = 0; j < 15; j++) { if (pic_param_ptr->ref_frames[j].pic_idx == idx) { break; } } if (j == 15) { - ERR("Could not find matching pic in ref_frames list. The slice type is B, and the idx from the ref_pic_list_1_ is: " + TOSTR(idx)); + ERR("Could not find matching pic in ref_frames list. The slice type is P/B, and the idx from the ref_pic_list_0_ is: " + TOSTR(idx)); return PARSER_FAIL; } else { - slice_params_ptr->ref_pic_list[1][i] = j; + slice_params_ptr->ref_pic_list[0][i] = j; + } + } + + if (p_slice_header->slice_type == HEVC_SLICE_TYPE_B) { + for (i = 0; i <= p_slice_header->num_ref_idx_l1_active_minus1; i++) { + int idx = p_slice_info->ref_pic_list_1_[i]; // pic_idx of the ref pic + for (j = 0; j < 15; j++) { + if (pic_param_ptr->ref_frames[j].pic_idx == idx) { + break; + } + } + if (j == 15) { + ERR("Could not find matching pic in ref_frames list. The slice type is B, and the idx from the ref_pic_list_1_ is: " + TOSTR(idx)); + return PARSER_FAIL; + } else { + slice_params_ptr->ref_pic_list[1][i] = j; + } } } } - } - slice_params_ptr->long_slice_flags.fields.last_slice_of_pic = 1; - slice_params_ptr->long_slice_flags.fields.dependent_slice_segment_flag = m_sh_->dependent_slice_segment_flag; - slice_params_ptr->long_slice_flags.fields.slice_type = m_sh_->slice_type; - slice_params_ptr->long_slice_flags.fields.color_plane_id = m_sh_->colour_plane_id; - slice_params_ptr->long_slice_flags.fields.slice_sao_luma_flag = m_sh_->slice_sao_luma_flag; - slice_params_ptr->long_slice_flags.fields.slice_sao_chroma_flag = m_sh_->slice_sao_chroma_flag; - slice_params_ptr->long_slice_flags.fields.mvd_l1_zero_flag = m_sh_->mvd_l1_zero_flag; - slice_params_ptr->long_slice_flags.fields.cabac_init_flag = m_sh_->cabac_init_flag; - slice_params_ptr->long_slice_flags.fields.slice_temporal_mvp_enabled_flag = m_sh_->slice_temporal_mvp_enabled_flag; - slice_params_ptr->long_slice_flags.fields.slice_deblocking_filter_disabled_flag = m_sh_->slice_deblocking_filter_disabled_flag; - slice_params_ptr->long_slice_flags.fields.collocated_from_l0_flag = m_sh_->collocated_from_l0_flag; - slice_params_ptr->long_slice_flags.fields.slice_loop_filter_across_slices_enabled_flag = m_sh_->slice_loop_filter_across_slices_enabled_flag; + slice_params_ptr->long_slice_flags.fields.last_slice_of_pic = (slice_index == num_slices_ - 1) ? 1 : 0; + slice_params_ptr->long_slice_flags.fields.dependent_slice_segment_flag = p_slice_header->dependent_slice_segment_flag; + slice_params_ptr->long_slice_flags.fields.slice_type = p_slice_header->slice_type; + slice_params_ptr->long_slice_flags.fields.color_plane_id = p_slice_header->colour_plane_id; + slice_params_ptr->long_slice_flags.fields.slice_sao_luma_flag = p_slice_header->slice_sao_luma_flag; + slice_params_ptr->long_slice_flags.fields.slice_sao_chroma_flag = p_slice_header->slice_sao_chroma_flag; + slice_params_ptr->long_slice_flags.fields.mvd_l1_zero_flag = p_slice_header->mvd_l1_zero_flag; + slice_params_ptr->long_slice_flags.fields.cabac_init_flag = p_slice_header->cabac_init_flag; + slice_params_ptr->long_slice_flags.fields.slice_temporal_mvp_enabled_flag = p_slice_header->slice_temporal_mvp_enabled_flag; + slice_params_ptr->long_slice_flags.fields.slice_deblocking_filter_disabled_flag = p_slice_header->slice_deblocking_filter_disabled_flag; + slice_params_ptr->long_slice_flags.fields.collocated_from_l0_flag = p_slice_header->collocated_from_l0_flag; + slice_params_ptr->long_slice_flags.fields.slice_loop_filter_across_slices_enabled_flag = p_slice_header->slice_loop_filter_across_slices_enabled_flag; - slice_params_ptr->collocated_ref_idx = m_sh_->collocated_ref_idx; - slice_params_ptr->num_ref_idx_l0_active_minus1 = m_sh_->num_ref_idx_l0_active_minus1; - slice_params_ptr->num_ref_idx_l1_active_minus1 = m_sh_->num_ref_idx_l1_active_minus1; - slice_params_ptr->slice_qp_delta = m_sh_->slice_qp_delta; - slice_params_ptr->slice_cb_qp_offset = m_sh_->slice_cb_qp_offset; - slice_params_ptr->slice_cr_qp_offset = m_sh_->slice_cr_qp_offset; - slice_params_ptr->slice_beta_offset_div2 = m_sh_->slice_beta_offset_div2; - slice_params_ptr->slice_tc_offset_div2 = m_sh_->slice_tc_offset_div2; + slice_params_ptr->collocated_ref_idx = p_slice_header->collocated_ref_idx; + slice_params_ptr->num_ref_idx_l0_active_minus1 = p_slice_header->num_ref_idx_l0_active_minus1; + slice_params_ptr->num_ref_idx_l1_active_minus1 = p_slice_header->num_ref_idx_l1_active_minus1; + slice_params_ptr->slice_qp_delta = p_slice_header->slice_qp_delta; + slice_params_ptr->slice_cb_qp_offset = p_slice_header->slice_cb_qp_offset; + slice_params_ptr->slice_cr_qp_offset = p_slice_header->slice_cr_qp_offset; + slice_params_ptr->slice_beta_offset_div2 = p_slice_header->slice_beta_offset_div2; + slice_params_ptr->slice_tc_offset_div2 = p_slice_header->slice_tc_offset_div2; - if ((pps_ptr->weighted_pred_flag && m_sh_->slice_type == HEVC_SLICE_TYPE_P) || (pps_ptr->weighted_bipred_flag && m_sh_->slice_type == HEVC_SLICE_TYPE_B)) { - slice_params_ptr->luma_log2_weight_denom = m_sh_->pred_weight_table.luma_log2_weight_denom; - slice_params_ptr->delta_chroma_log2_weight_denom = m_sh_->pred_weight_table.delta_chroma_log2_weight_denom; - for (i = 0; i < m_sh_->num_ref_idx_l0_active_minus1; i++) { - slice_params_ptr->delta_luma_weight_l0[i] = m_sh_->pred_weight_table.delta_luma_weight_l0[i]; - slice_params_ptr->luma_offset_l0[i] = m_sh_->pred_weight_table.luma_offset_l0[i]; - slice_params_ptr->delta_chroma_weight_l0[i][0] = m_sh_->pred_weight_table.delta_chroma_weight_l0[i][0]; - slice_params_ptr->delta_chroma_weight_l0[i][1] = m_sh_->pred_weight_table.delta_chroma_weight_l0[i][1]; - slice_params_ptr->chroma_offset_l0[i][0] = m_sh_->pred_weight_table.chroma_offset_l0[i][0]; - slice_params_ptr->chroma_offset_l0[i][1] = m_sh_->pred_weight_table.chroma_offset_l0[i][1]; - } + if ((pps_ptr->weighted_pred_flag && p_slice_header->slice_type == HEVC_SLICE_TYPE_P) || (pps_ptr->weighted_bipred_flag && p_slice_header->slice_type == HEVC_SLICE_TYPE_B)) { + slice_params_ptr->luma_log2_weight_denom = p_slice_header->pred_weight_table.luma_log2_weight_denom; + slice_params_ptr->delta_chroma_log2_weight_denom = p_slice_header->pred_weight_table.delta_chroma_log2_weight_denom; + for (i = 0; i < p_slice_header->num_ref_idx_l0_active_minus1; i++) { + slice_params_ptr->delta_luma_weight_l0[i] = p_slice_header->pred_weight_table.delta_luma_weight_l0[i]; + slice_params_ptr->luma_offset_l0[i] = p_slice_header->pred_weight_table.luma_offset_l0[i]; + slice_params_ptr->delta_chroma_weight_l0[i][0] = p_slice_header->pred_weight_table.delta_chroma_weight_l0[i][0]; + slice_params_ptr->delta_chroma_weight_l0[i][1] = p_slice_header->pred_weight_table.delta_chroma_weight_l0[i][1]; + slice_params_ptr->chroma_offset_l0[i][0] = p_slice_header->pred_weight_table.chroma_offset_l0[i][0]; + slice_params_ptr->chroma_offset_l0[i][1] = p_slice_header->pred_weight_table.chroma_offset_l0[i][1]; + } - if (m_sh_->slice_type == HEVC_SLICE_TYPE_B) { - for (i = 0; i < m_sh_->num_ref_idx_l1_active_minus1; i++) { - slice_params_ptr->delta_luma_weight_l1[i] = m_sh_->pred_weight_table.delta_luma_weight_l1[i]; - slice_params_ptr->luma_offset_l1[i] = m_sh_->pred_weight_table.luma_offset_l1[i]; - slice_params_ptr->delta_chroma_weight_l1[i][0] = m_sh_->pred_weight_table.delta_chroma_weight_l1[i][0]; - slice_params_ptr->delta_chroma_weight_l1[i][1] = m_sh_->pred_weight_table.delta_chroma_weight_l1[i][1]; - slice_params_ptr->chroma_offset_l1[i][0] = m_sh_->pred_weight_table.chroma_offset_l1[i][0]; - slice_params_ptr->chroma_offset_l1[i][1] = m_sh_->pred_weight_table.chroma_offset_l1[i][1]; + if (p_slice_header->slice_type == HEVC_SLICE_TYPE_B) { + for (i = 0; i < p_slice_header->num_ref_idx_l1_active_minus1; i++) { + slice_params_ptr->delta_luma_weight_l1[i] = p_slice_header->pred_weight_table.delta_luma_weight_l1[i]; + slice_params_ptr->luma_offset_l1[i] = p_slice_header->pred_weight_table.luma_offset_l1[i]; + slice_params_ptr->delta_chroma_weight_l1[i][0] = p_slice_header->pred_weight_table.delta_chroma_weight_l1[i][0]; + slice_params_ptr->delta_chroma_weight_l1[i][1] = p_slice_header->pred_weight_table.delta_chroma_weight_l1[i][1]; + slice_params_ptr->chroma_offset_l1[i][0] = p_slice_header->pred_weight_table.chroma_offset_l1[i][0]; + slice_params_ptr->chroma_offset_l1[i][1] = p_slice_header->pred_weight_table.chroma_offset_l1[i][1]; + } } } - } - slice_params_ptr->five_minus_max_num_merge_cand = m_sh_->five_minus_max_num_merge_cand; - slice_params_ptr->num_entry_point_offsets = m_sh_->num_entry_point_offsets; - slice_params_ptr->entry_offset_to_subset_array = 0; // don't care - slice_params_ptr->slice_data_num_emu_prevn_bytes = 0; // don't care + slice_params_ptr->five_minus_max_num_merge_cand = p_slice_header->five_minus_max_num_merge_cand; + slice_params_ptr->num_entry_point_offsets = p_slice_header->num_entry_point_offsets; + slice_params_ptr->entry_offset_to_subset_array = 0; // don't care + slice_params_ptr->slice_data_num_emu_prevn_bytes = 0; // don't care + } + dec_pic_params_.slice_params.hevc = slice_param_list_.data(); /// Fill scaling lists if (sps_ptr->scaling_list_enabled_flag) { @@ -572,7 +578,7 @@ bool HevcVideoParser::ParsePictureData(const uint8_t* p_stream, uint32_t pic_dat curr_start_code_offset_ = 0; next_start_code_offset_ = 0; - slice_num_ = 0; + num_slices_ = 0; sei_message_count_ = 0; sei_payload_size_ = 0; @@ -627,22 +633,30 @@ bool HevcVideoParser::ParsePictureData(const uint8_t* p_stream, uint32_t pic_dat case NAL_UNIT_CODED_SLICE_RADL_R: case NAL_UNIT_CODED_SLICE_RASL_N: case NAL_UNIT_CODED_SLICE_RASL_R: { + // Save slice NAL unit header + slice_nal_unit_header_ = nal_unit_header_; + + // Resize slice info list if needed + if ((num_slices_ + 1) > slice_info_list_.size()) { + slice_info_list_.resize(num_slices_ + 1, {0}); + } + + slice_info_list_[num_slices_].slice_data_offset = curr_start_code_offset_; + slice_info_list_[num_slices_].slice_data_size = nal_unit_size_; + memcpy(rbsp_buf_, (pic_data_buffer_ptr_ + curr_start_code_offset_ + 5), ebsp_size); rbsp_size_ = EbspToRbsp(rbsp_buf_, 0, ebsp_size); - // For each picture, only parse the first slice header - if (slice_num_ == 0) { - // Save slice NAL unit header - slice_nal_unit_header_ = nal_unit_header_; + HevcSliceSegHeader *p_slice_header = &slice_info_list_[num_slices_].slice_header; + ParseSliceHeader(rbsp_buf_, rbsp_size_, p_slice_header); + // Start decode process + if (num_slices_ == 0) { // Use the data directly from demuxer without copying pic_stream_data_ptr_ = pic_data_buffer_ptr_ + curr_start_code_offset_; // Picture stream data size is calculated as the diff between the frame end and the first slice offset. // This is to consider the possibility of non-slice NAL units between slices. pic_stream_data_size_ = pic_data_size - curr_start_code_offset_; - ParseSliceHeader(rbsp_buf_, rbsp_size_); - - // Start decode process if (IsIrapPic(&slice_nal_unit_header_)) { if (IsIdrPic(&slice_nal_unit_header_) || IsBlaPic(&slice_nal_unit_header_) || pic_count_ == 0 || first_pic_after_eos_nal_unit_) { no_rasl_output_flag_ = 1; @@ -658,7 +672,7 @@ bool HevcVideoParser::ParsePictureData(const uint8_t* p_stream, uint32_t pic_dat if (IsRaslPic(&slice_nal_unit_header_) && no_rasl_output_flag_ == 1) { curr_pic_info_.pic_output_flag = 0; } else { - curr_pic_info_.pic_output_flag = m_sh_->pic_output_flag; + curr_pic_info_.pic_output_flag = p_slice_header->pic_output_flag; } // Get POC. 8.3.1. @@ -666,12 +680,14 @@ bool HevcVideoParser::ParsePictureData(const uint8_t* p_stream, uint32_t pic_dat // Decode RPS. 8.3.2. DecodeRps(); + } - // Construct ref lists. 8.3.4. - if(m_sh_->slice_type != HEVC_SLICE_TYPE_I) { - ConstructRefPicLists(); - } + // Construct ref lists. 8.3.4. + if(p_slice_header->slice_type != HEVC_SLICE_TYPE_I) { + ConstructRefPicLists(&slice_info_list_[num_slices_]); + } + if (num_slices_ == 0) { // C.5.2.2. Mark output buffers. (After 8.3.2.) if (MarkOutputPictures() != PARSER_OK) { return PARSER_FAIL; @@ -682,7 +698,7 @@ bool HevcVideoParser::ParsePictureData(const uint8_t* p_stream, uint32_t pic_dat return PARSER_FAIL; } } - slice_num_++; + num_slices_++; break; } @@ -1519,22 +1535,22 @@ void HevcVideoParser::ParsePps(uint8_t *nalu, size_t size) { #endif // DBGINFO } -bool HevcVideoParser::ParseSliceHeader(uint8_t *nalu, size_t size) { +bool HevcVideoParser::ParseSliceHeader(uint8_t *nalu, size_t size, HevcSliceSegHeader *p_slice_header) { HevcPicParamSet *pps_ptr = nullptr; HevcSeqParamSet *sps_ptr = nullptr; size_t offset = 0; HevcSliceSegHeader temp_sh; - memset(m_sh_, 0, sizeof(HevcSliceSegHeader)); + memset(p_slice_header, 0, sizeof(HevcSliceSegHeader)); memset(&temp_sh, 0, sizeof(temp_sh)); - temp_sh.first_slice_segment_in_pic_flag = m_sh_->first_slice_segment_in_pic_flag = Parser::GetBit(nalu, offset); + temp_sh.first_slice_segment_in_pic_flag = p_slice_header->first_slice_segment_in_pic_flag = Parser::GetBit(nalu, offset); if (IsIrapPic(&slice_nal_unit_header_)) { - temp_sh.no_output_of_prior_pics_flag = m_sh_->no_output_of_prior_pics_flag = Parser::GetBit(nalu, offset); + temp_sh.no_output_of_prior_pics_flag = p_slice_header->no_output_of_prior_pics_flag = Parser::GetBit(nalu, offset); } // Set active VPS, SPS and PPS for the current slice m_active_pps_id_ = Parser::ExpGolomb::ReadUe(nalu, offset); - temp_sh.slice_pic_parameter_set_id = m_sh_->slice_pic_parameter_set_id = m_active_pps_id_; + temp_sh.slice_pic_parameter_set_id = p_slice_header->slice_pic_parameter_set_id = m_active_pps_id_; pps_ptr = &m_pps_[m_active_pps_id_]; if (m_active_sps_id_ != pps_ptr->pps_seq_parameter_set_id) { m_active_sps_id_ = pps_ptr->pps_seq_parameter_set_id; @@ -1572,38 +1588,36 @@ bool HevcVideoParser::ParseSliceHeader(uint8_t *nalu, size_t size) { } } - if (!m_sh_->first_slice_segment_in_pic_flag) { + if (!p_slice_header->first_slice_segment_in_pic_flag) { if (pps_ptr->dependent_slice_segments_enabled_flag) { - temp_sh.dependent_slice_segment_flag = m_sh_->dependent_slice_segment_flag = Parser::GetBit(nalu, offset); + temp_sh.dependent_slice_segment_flag = p_slice_header->dependent_slice_segment_flag = Parser::GetBit(nalu, offset); } - int bits_slice_segment_address = (int)ceilf(log2f((float)pic_size_in_ctbs_y_)); - - temp_sh.slice_segment_address = m_sh_->slice_segment_address = Parser::ReadBits(nalu, offset, bits_slice_segment_address); + temp_sh.slice_segment_address = p_slice_header->slice_segment_address = Parser::ReadBits(nalu, offset, bits_slice_segment_address); } - if (!m_sh_->dependent_slice_segment_flag) { + if (!p_slice_header->dependent_slice_segment_flag) { for (int i = 0; i < pps_ptr->num_extra_slice_header_bits; i++) { - m_sh_->slice_reserved_flag[i] = Parser::GetBit(nalu, offset); + p_slice_header->slice_reserved_flag[i] = Parser::GetBit(nalu, offset); } - m_sh_->slice_type = Parser::ExpGolomb::ReadUe(nalu, offset); + p_slice_header->slice_type = Parser::ExpGolomb::ReadUe(nalu, offset); if (pps_ptr->output_flag_present_flag) { - m_sh_->pic_output_flag = Parser::GetBit(nalu, offset); + p_slice_header->pic_output_flag = Parser::GetBit(nalu, offset); } else { - m_sh_->pic_output_flag = 1; // default value + p_slice_header->pic_output_flag = 1; // default value } if (sps_ptr->separate_colour_plane_flag) { - m_sh_->colour_plane_id = Parser::ReadBits(nalu, offset, 2); + p_slice_header->colour_plane_id = Parser::ReadBits(nalu, offset, 2); } if (slice_nal_unit_header_.nal_unit_type != NAL_UNIT_CODED_SLICE_IDR_W_RADL && slice_nal_unit_header_.nal_unit_type != NAL_UNIT_CODED_SLICE_IDR_N_LP) { //length of slice_pic_order_cnt_lsb is log2_max_pic_order_cnt_lsb_minus4 + 4 bits. - m_sh_->slice_pic_order_cnt_lsb = Parser::ReadBits(nalu, offset, (sps_ptr->log2_max_pic_order_cnt_lsb_minus4 + 4)); + p_slice_header->slice_pic_order_cnt_lsb = Parser::ReadBits(nalu, offset, (sps_ptr->log2_max_pic_order_cnt_lsb_minus4 + 4)); - m_sh_->short_term_ref_pic_set_sps_flag = Parser::GetBit(nalu, offset); + p_slice_header->short_term_ref_pic_set_sps_flag = Parser::GetBit(nalu, offset); int32_t pos = offset; - if (!m_sh_->short_term_ref_pic_set_sps_flag) { - ParseShortTermRefPicSet(&m_sh_->st_rps, sps_ptr->num_short_term_ref_pic_sets, sps_ptr->num_short_term_ref_pic_sets, sps_ptr->st_rps, nalu, size, offset); + if (!p_slice_header->short_term_ref_pic_set_sps_flag) { + ParseShortTermRefPicSet(&p_slice_header->st_rps, sps_ptr->num_short_term_ref_pic_sets, sps_ptr->num_short_term_ref_pic_sets, sps_ptr->st_rps, nalu, size, offset); } else { if (sps_ptr->num_short_term_ref_pic_sets > 1) { int num_bits = 0; @@ -1611,88 +1625,88 @@ bool HevcVideoParser::ParseSliceHeader(uint8_t *nalu, size_t size) { num_bits++; } if (num_bits > 0) { - m_sh_->short_term_ref_pic_set_idx = Parser::ReadBits(nalu, offset, num_bits); + p_slice_header->short_term_ref_pic_set_idx = Parser::ReadBits(nalu, offset, num_bits); } } else { - m_sh_->short_term_ref_pic_set_idx = 0; + p_slice_header->short_term_ref_pic_set_idx = 0; } // Copy the SPS RPS to slice RPS - m_sh_->st_rps = sps_ptr->st_rps[m_sh_->short_term_ref_pic_set_idx]; + p_slice_header->st_rps = sps_ptr->st_rps[p_slice_header->short_term_ref_pic_set_idx]; } - m_sh_->short_term_ref_pic_set_size = offset - pos; + p_slice_header->short_term_ref_pic_set_size = offset - pos; if (sps_ptr->long_term_ref_pics_present_flag) { if (sps_ptr->num_long_term_ref_pics_sps > 0) { - m_sh_->num_long_term_sps = Parser::ExpGolomb::ReadUe(nalu, offset); + p_slice_header->num_long_term_sps = Parser::ExpGolomb::ReadUe(nalu, offset); } - m_sh_->num_long_term_pics = Parser::ExpGolomb::ReadUe(nalu, offset); + p_slice_header->num_long_term_pics = Parser::ExpGolomb::ReadUe(nalu, offset); int bits_for_ltrp_in_sps = 0; while (sps_ptr->num_long_term_ref_pics_sps > (1 << bits_for_ltrp_in_sps)) { bits_for_ltrp_in_sps++; } - m_sh_->lt_rps.num_of_pics = m_sh_->num_long_term_sps + m_sh_->num_long_term_pics; - for (int i = 0; i < (m_sh_->num_long_term_sps + m_sh_->num_long_term_pics); i++) { - if (i < m_sh_->num_long_term_sps) { + p_slice_header->lt_rps.num_of_pics = p_slice_header->num_long_term_sps + p_slice_header->num_long_term_pics; + for (int i = 0; i < (p_slice_header->num_long_term_sps + p_slice_header->num_long_term_pics); i++) { + if (i < p_slice_header->num_long_term_sps) { if (sps_ptr->num_long_term_ref_pics_sps > 1) { if( bits_for_ltrp_in_sps > 0) { - m_sh_->lt_idx_sps[i] = Parser::ReadBits(nalu, offset, bits_for_ltrp_in_sps); - m_sh_->lt_rps.pocs[i] = sps_ptr->lt_rps.pocs[m_sh_->lt_idx_sps[i]]; // PocLsbLt[] - m_sh_->lt_rps.used_by_curr_pic[i] = sps_ptr->lt_rps.used_by_curr_pic[m_sh_->lt_idx_sps[i]]; // UsedByCurrPicLt[] + p_slice_header->lt_idx_sps[i] = Parser::ReadBits(nalu, offset, bits_for_ltrp_in_sps); + p_slice_header->lt_rps.pocs[i] = sps_ptr->lt_rps.pocs[p_slice_header->lt_idx_sps[i]]; // PocLsbLt[] + p_slice_header->lt_rps.used_by_curr_pic[i] = sps_ptr->lt_rps.used_by_curr_pic[p_slice_header->lt_idx_sps[i]]; // UsedByCurrPicLt[] } } } else { - m_sh_->poc_lsb_lt[i] = Parser::ReadBits(nalu, offset, (sps_ptr->log2_max_pic_order_cnt_lsb_minus4 + 4)); - m_sh_->used_by_curr_pic_lt_flag[i] = Parser::GetBit(nalu, offset); - m_sh_->lt_rps.pocs[i] = m_sh_->poc_lsb_lt[i]; // PocLsbLt[] - m_sh_->lt_rps.used_by_curr_pic[i] = m_sh_->used_by_curr_pic_lt_flag[i]; // UsedByCurrPicLt[] + p_slice_header->poc_lsb_lt[i] = Parser::ReadBits(nalu, offset, (sps_ptr->log2_max_pic_order_cnt_lsb_minus4 + 4)); + p_slice_header->used_by_curr_pic_lt_flag[i] = Parser::GetBit(nalu, offset); + p_slice_header->lt_rps.pocs[i] = p_slice_header->poc_lsb_lt[i]; // PocLsbLt[] + p_slice_header->lt_rps.used_by_curr_pic[i] = p_slice_header->used_by_curr_pic_lt_flag[i]; // UsedByCurrPicLt[] } int delta_poc_msb_cycle_lt = 0; - m_sh_->delta_poc_msb_present_flag[i] = Parser::GetBit(nalu, offset); - if (m_sh_->delta_poc_msb_present_flag[i]) { + p_slice_header->delta_poc_msb_present_flag[i] = Parser::GetBit(nalu, offset); + if (p_slice_header->delta_poc_msb_present_flag[i]) { // Store DeltaPocMsbCycleLt in delta_poc_msb_cycle_lt for later use delta_poc_msb_cycle_lt = Parser::ExpGolomb::ReadUe(nalu, offset); } - if ( i == 0 || i == m_sh_->num_long_term_sps) { - m_sh_->delta_poc_msb_cycle_lt[i] = delta_poc_msb_cycle_lt; + if ( i == 0 || i == p_slice_header->num_long_term_sps) { + p_slice_header->delta_poc_msb_cycle_lt[i] = delta_poc_msb_cycle_lt; } else { - m_sh_->delta_poc_msb_cycle_lt[i] = delta_poc_msb_cycle_lt + m_sh_->delta_poc_msb_cycle_lt[i - 1]; + p_slice_header->delta_poc_msb_cycle_lt[i] = delta_poc_msb_cycle_lt + p_slice_header->delta_poc_msb_cycle_lt[i - 1]; } } } if (sps_ptr->sps_temporal_mvp_enabled_flag) { - m_sh_->slice_temporal_mvp_enabled_flag = Parser::GetBit(nalu, offset); + p_slice_header->slice_temporal_mvp_enabled_flag = Parser::GetBit(nalu, offset); } } int chroma_array_type = sps_ptr->separate_colour_plane_flag ? 0 : sps_ptr->chroma_format_idc; // ChromaArrayType if (sps_ptr->sample_adaptive_offset_enabled_flag) { - m_sh_->slice_sao_luma_flag = Parser::GetBit(nalu, offset); + p_slice_header->slice_sao_luma_flag = Parser::GetBit(nalu, offset); if (chroma_array_type) { - m_sh_->slice_sao_chroma_flag = Parser::GetBit(nalu, offset); + p_slice_header->slice_sao_chroma_flag = Parser::GetBit(nalu, offset); } } - if (m_sh_->slice_type != HEVC_SLICE_TYPE_I) { - m_sh_->num_ref_idx_active_override_flag = Parser::GetBit(nalu, offset); - if (m_sh_->num_ref_idx_active_override_flag) { - m_sh_->num_ref_idx_l0_active_minus1 = Parser::ExpGolomb::ReadUe(nalu, offset); - if (m_sh_->slice_type == HEVC_SLICE_TYPE_B) { - m_sh_->num_ref_idx_l1_active_minus1 = Parser::ExpGolomb::ReadUe(nalu, offset); + if (p_slice_header->slice_type != HEVC_SLICE_TYPE_I) { + p_slice_header->num_ref_idx_active_override_flag = Parser::GetBit(nalu, offset); + if (p_slice_header->num_ref_idx_active_override_flag) { + p_slice_header->num_ref_idx_l0_active_minus1 = Parser::ExpGolomb::ReadUe(nalu, offset); + if (p_slice_header->slice_type == HEVC_SLICE_TYPE_B) { + p_slice_header->num_ref_idx_l1_active_minus1 = Parser::ExpGolomb::ReadUe(nalu, offset); } } else { - m_sh_->num_ref_idx_l0_active_minus1 = pps_ptr->num_ref_idx_l0_default_active_minus1; - if (m_sh_->slice_type == HEVC_SLICE_TYPE_B) { - m_sh_->num_ref_idx_l1_active_minus1 = pps_ptr->num_ref_idx_l1_default_active_minus1; + p_slice_header->num_ref_idx_l0_active_minus1 = pps_ptr->num_ref_idx_l0_default_active_minus1; + if (p_slice_header->slice_type == HEVC_SLICE_TYPE_B) { + p_slice_header->num_ref_idx_l1_active_minus1 = pps_ptr->num_ref_idx_l1_default_active_minus1; } } // 7.3.6.2 Reference picture list modification // Calculate NumPicTotalCurr num_pic_total_curr_ = 0; - HevcShortTermRps *st_rps_ptr = &m_sh_->st_rps; + HevcShortTermRps *st_rps_ptr = &p_slice_header->st_rps; for (int i = 0; i < st_rps_ptr->num_negative_pics; i++) { if (st_rps_ptr->used_by_curr_pic_s0[i]) { num_pic_total_curr_++; @@ -1704,7 +1718,7 @@ bool HevcVideoParser::ParseSliceHeader(uint8_t *nalu, size_t size) { } } - HevcLongTermRps *lt_rps_ptr = &m_sh_->lt_rps; + HevcLongTermRps *lt_rps_ptr = &p_slice_header->lt_rps; // Check the combined list for (int i = 0; i < lt_rps_ptr->num_of_pics; i++) { if (lt_rps_ptr->used_by_curr_pic[i]) { @@ -1719,78 +1733,78 @@ bool HevcVideoParser::ParseSliceHeader(uint8_t *nalu, size_t size) { list_entry_bits++; } - m_sh_->ref_pic_list_modification_flag_l0 = Parser::GetBit(nalu, offset); - if (m_sh_->ref_pic_list_modification_flag_l0) { - for (int i = 0; i <= m_sh_->num_ref_idx_l0_active_minus1; i++) { - m_sh_->list_entry_l0[i] = Parser::ReadBits(nalu, offset, list_entry_bits); + p_slice_header->ref_pic_list_modification_flag_l0 = Parser::GetBit(nalu, offset); + if (p_slice_header->ref_pic_list_modification_flag_l0) { + for (int i = 0; i <= p_slice_header->num_ref_idx_l0_active_minus1; i++) { + p_slice_header->list_entry_l0[i] = Parser::ReadBits(nalu, offset, list_entry_bits); } } - if (m_sh_->slice_type == HEVC_SLICE_TYPE_B) { - m_sh_->ref_pic_list_modification_flag_l1 = Parser::GetBit(nalu, offset); - if (m_sh_->ref_pic_list_modification_flag_l1) { - for (int i = 0; i <= m_sh_->num_ref_idx_l1_active_minus1; i++) { - m_sh_->list_entry_l1[i] = Parser::ReadBits(nalu, offset, list_entry_bits); + if (p_slice_header->slice_type == HEVC_SLICE_TYPE_B) { + p_slice_header->ref_pic_list_modification_flag_l1 = Parser::GetBit(nalu, offset); + if (p_slice_header->ref_pic_list_modification_flag_l1) { + for (int i = 0; i <= p_slice_header->num_ref_idx_l1_active_minus1; i++) { + p_slice_header->list_entry_l1[i] = Parser::ReadBits(nalu, offset, list_entry_bits); } } } } - if (m_sh_->slice_type == HEVC_SLICE_TYPE_B) { - m_sh_->mvd_l1_zero_flag = Parser::GetBit(nalu, offset); + if (p_slice_header->slice_type == HEVC_SLICE_TYPE_B) { + p_slice_header->mvd_l1_zero_flag = Parser::GetBit(nalu, offset); } if (pps_ptr->cabac_init_present_flag) { - m_sh_->cabac_init_flag = Parser::GetBit(nalu, offset); + p_slice_header->cabac_init_flag = Parser::GetBit(nalu, offset); } - if (m_sh_->slice_temporal_mvp_enabled_flag) { - if (m_sh_->slice_type == HEVC_SLICE_TYPE_B) { - m_sh_->collocated_from_l0_flag = Parser::GetBit(nalu, offset); + if (p_slice_header->slice_temporal_mvp_enabled_flag) { + if (p_slice_header->slice_type == HEVC_SLICE_TYPE_B) { + p_slice_header->collocated_from_l0_flag = Parser::GetBit(nalu, offset); } - if ((m_sh_->collocated_from_l0_flag && m_sh_->num_ref_idx_l0_active_minus1 > 0) || (!m_sh_->collocated_from_l0_flag && m_sh_->num_ref_idx_l1_active_minus1 > 0)) { - m_sh_->collocated_ref_idx = Parser::ExpGolomb::ReadUe(nalu, offset); + if ((p_slice_header->collocated_from_l0_flag && p_slice_header->num_ref_idx_l0_active_minus1 > 0) || (!p_slice_header->collocated_from_l0_flag && p_slice_header->num_ref_idx_l1_active_minus1 > 0)) { + p_slice_header->collocated_ref_idx = Parser::ExpGolomb::ReadUe(nalu, offset); } } - if ((pps_ptr->weighted_pred_flag && m_sh_->slice_type == HEVC_SLICE_TYPE_P) || (pps_ptr->weighted_bipred_flag && m_sh_->slice_type == HEVC_SLICE_TYPE_B)) { - ParsePredWeightTable(m_sh_, chroma_array_type, nalu, offset); + if ((pps_ptr->weighted_pred_flag && p_slice_header->slice_type == HEVC_SLICE_TYPE_P) || (pps_ptr->weighted_bipred_flag && p_slice_header->slice_type == HEVC_SLICE_TYPE_B)) { + ParsePredWeightTable(p_slice_header, chroma_array_type, nalu, offset); } - m_sh_->five_minus_max_num_merge_cand = Parser::ExpGolomb::ReadUe(nalu, offset); + p_slice_header->five_minus_max_num_merge_cand = Parser::ExpGolomb::ReadUe(nalu, offset); } - m_sh_->slice_qp_delta = Parser::ExpGolomb::ReadSe(nalu, offset); + p_slice_header->slice_qp_delta = Parser::ExpGolomb::ReadSe(nalu, offset); if (pps_ptr->pps_slice_chroma_qp_offsets_present_flag) { - m_sh_->slice_cb_qp_offset = Parser::ExpGolomb::ReadSe(nalu, offset); - m_sh_->slice_cr_qp_offset = Parser::ExpGolomb::ReadSe(nalu, offset); + p_slice_header->slice_cb_qp_offset = Parser::ExpGolomb::ReadSe(nalu, offset); + p_slice_header->slice_cr_qp_offset = Parser::ExpGolomb::ReadSe(nalu, offset); } if (pps_ptr->chroma_qp_offset_list_enabled_flag) { - m_sh_->cu_chroma_qp_offset_enabled_flag = Parser::GetBit(nalu, offset); + p_slice_header->cu_chroma_qp_offset_enabled_flag = Parser::GetBit(nalu, offset); } if (pps_ptr->deblocking_filter_override_enabled_flag) { - m_sh_->deblocking_filter_override_flag = Parser::GetBit(nalu, offset); + p_slice_header->deblocking_filter_override_flag = Parser::GetBit(nalu, offset); } - if (m_sh_->deblocking_filter_override_flag) { - m_sh_->slice_deblocking_filter_disabled_flag = Parser::GetBit(nalu, offset); - if ( !m_sh_->slice_deblocking_filter_disabled_flag ) { - m_sh_->slice_beta_offset_div2 = Parser::ExpGolomb::ReadSe(nalu, offset); - m_sh_->slice_tc_offset_div2 = Parser::ExpGolomb::ReadSe(nalu, offset); + if (p_slice_header->deblocking_filter_override_flag) { + p_slice_header->slice_deblocking_filter_disabled_flag = Parser::GetBit(nalu, offset); + if ( !p_slice_header->slice_deblocking_filter_disabled_flag ) { + p_slice_header->slice_beta_offset_div2 = Parser::ExpGolomb::ReadSe(nalu, offset); + p_slice_header->slice_tc_offset_div2 = Parser::ExpGolomb::ReadSe(nalu, offset); } } - if (pps_ptr->pps_loop_filter_across_slices_enabled_flag && (m_sh_->slice_sao_luma_flag || m_sh_->slice_sao_chroma_flag || -!m_sh_->slice_deblocking_filter_disabled_flag)) { - m_sh_->slice_loop_filter_across_slices_enabled_flag = Parser::GetBit(nalu, offset); + if (pps_ptr->pps_loop_filter_across_slices_enabled_flag && (p_slice_header->slice_sao_luma_flag || p_slice_header->slice_sao_chroma_flag || +!p_slice_header->slice_deblocking_filter_disabled_flag)) { + p_slice_header->slice_loop_filter_across_slices_enabled_flag = Parser::GetBit(nalu, offset); } - memcpy(m_sh_copy_, m_sh_, sizeof(HevcSliceSegHeader)); + memcpy(m_sh_copy_, p_slice_header, sizeof(HevcSliceSegHeader)); } else { //dependant slice - memcpy(m_sh_, m_sh_copy_, sizeof(HevcSliceSegHeader)); - m_sh_->first_slice_segment_in_pic_flag = temp_sh.first_slice_segment_in_pic_flag; - m_sh_->no_output_of_prior_pics_flag = temp_sh.no_output_of_prior_pics_flag; - m_sh_->slice_pic_parameter_set_id = temp_sh.slice_pic_parameter_set_id; - m_sh_->dependent_slice_segment_flag = temp_sh.dependent_slice_segment_flag; - m_sh_->slice_segment_address = temp_sh.slice_segment_address; + memcpy(p_slice_header, m_sh_copy_, sizeof(HevcSliceSegHeader)); + p_slice_header->first_slice_segment_in_pic_flag = temp_sh.first_slice_segment_in_pic_flag; + p_slice_header->no_output_of_prior_pics_flag = temp_sh.no_output_of_prior_pics_flag; + p_slice_header->slice_pic_parameter_set_id = temp_sh.slice_pic_parameter_set_id; + p_slice_header->dependent_slice_segment_flag = temp_sh.dependent_slice_segment_flag; + p_slice_header->slice_segment_address = temp_sh.slice_segment_address; } if (pps_ptr->tiles_enabled_flag || pps_ptr->entropy_coding_sync_enabled_flag) { int max_num_entry_point_offsets; // 7.4.7.1 @@ -1801,16 +1815,16 @@ bool HevcVideoParser::ParseSliceHeader(uint8_t *nalu, size_t size) { } else { max_num_entry_point_offsets = (pps_ptr->num_tile_columns_minus1 + 1) * pic_height_in_ctbs_y_ - 1; } - m_sh_->num_entry_point_offsets = Parser::ExpGolomb::ReadUe(nalu, offset); - if (m_sh_->num_entry_point_offsets > max_num_entry_point_offsets) { - m_sh_->num_entry_point_offsets = max_num_entry_point_offsets; + p_slice_header->num_entry_point_offsets = Parser::ExpGolomb::ReadUe(nalu, offset); + if (p_slice_header->num_entry_point_offsets > max_num_entry_point_offsets) { + p_slice_header->num_entry_point_offsets = max_num_entry_point_offsets; } #if 0 // do not parse syntax parameters that are not used by HW decode - if (m_sh_->num_entry_point_offsets) { - m_sh_->offset_len_minus1 = Parser::ExpGolomb::ReadUe(nalu, offset); - for (int i = 0; i < m_sh_->num_entry_point_offsets; i++) { - m_sh_->entry_point_offset_minus1[i] = Parser::ReadBits(nalu, offset, m_sh_->offset_len_minus1 + 1); + if (p_slice_header->num_entry_point_offsets) { + p_slice_header->offset_len_minus1 = Parser::ExpGolomb::ReadUe(nalu, offset); + for (int i = 0; i < p_slice_header->num_entry_point_offsets; i++) { + p_slice_header->entry_point_offset_minus1[i] = Parser::ReadBits(nalu, offset, p_slice_header->offset_len_minus1 + 1); } } #endif @@ -1818,15 +1832,15 @@ bool HevcVideoParser::ParseSliceHeader(uint8_t *nalu, size_t size) { #if 0 // do not parse syntax parameters that are not used by HW decode if (pps_ptr->slice_segment_header_extension_present_flag) { - m_sh_->slice_segment_header_extension_length = Parser::ExpGolomb::ReadUe(nalu, offset); - for (int i = 0; i < m_sh_->slice_segment_header_extension_length; i++) { - m_sh_->slice_segment_header_extension_data_byte[i] = Parser::ReadBits(nalu, offset, 8); + p_slice_header->slice_segment_header_extension_length = Parser::ExpGolomb::ReadUe(nalu, offset); + for (int i = 0; i < p_slice_header->slice_segment_header_extension_length; i++) { + p_slice_header->slice_segment_header_extension_data_byte[i] = Parser::ReadBits(nalu, offset, 8); } } #endif #if DBGINFO - PrintSliceSegHeader(m_sh_); + PrintSliceSegHeader(p_slice_header); #endif // DBGINFO return false; @@ -1917,6 +1931,7 @@ bool HevcVideoParser::IsRefPic(HevcNalUnitHeader *nal_header_ptr) { } void HevcVideoParser::CalculateCurrPoc() { + HevcSliceSegHeader *p_slice_header = &slice_info_list_[0].slice_header; // Record decode order count curr_pic_info_.decode_order_count = pic_count_; if (IsIdrPic(&slice_nal_unit_header_)) { @@ -1931,19 +1946,19 @@ void HevcVideoParser::CalculateCurrPoc() { if (IsIrapPic(&slice_nal_unit_header_) && no_rasl_output_flag_ == 1) { poc_msb = 0; } else { - if ((m_sh_->slice_pic_order_cnt_lsb < curr_pic_info_.prev_poc_lsb) && ((curr_pic_info_.prev_poc_lsb - m_sh_->slice_pic_order_cnt_lsb) >= (max_poc_lsb / 2))) { + if ((p_slice_header->slice_pic_order_cnt_lsb < curr_pic_info_.prev_poc_lsb) && ((curr_pic_info_.prev_poc_lsb - p_slice_header->slice_pic_order_cnt_lsb) >= (max_poc_lsb / 2))) { poc_msb = curr_pic_info_.prev_poc_msb + max_poc_lsb; - } else if ((m_sh_->slice_pic_order_cnt_lsb > curr_pic_info_.prev_poc_lsb) && ((m_sh_->slice_pic_order_cnt_lsb - curr_pic_info_.prev_poc_lsb) > (max_poc_lsb / 2))) { + } else if ((p_slice_header->slice_pic_order_cnt_lsb > curr_pic_info_.prev_poc_lsb) && ((p_slice_header->slice_pic_order_cnt_lsb - curr_pic_info_.prev_poc_lsb) > (max_poc_lsb / 2))) { poc_msb = curr_pic_info_.prev_poc_msb - max_poc_lsb; } else { poc_msb = curr_pic_info_.prev_poc_msb; } } - curr_pic_info_.pic_order_cnt = poc_msb + m_sh_->slice_pic_order_cnt_lsb; - curr_pic_info_.slice_pic_order_cnt_lsb = m_sh_->slice_pic_order_cnt_lsb; + curr_pic_info_.pic_order_cnt = poc_msb + p_slice_header->slice_pic_order_cnt_lsb; + curr_pic_info_.slice_pic_order_cnt_lsb = p_slice_header->slice_pic_order_cnt_lsb; if ((slice_nal_unit_header_.nuh_temporal_id_plus1 - 1) == 0 && IsRefPic(&slice_nal_unit_header_) && !IsRaslPic(&slice_nal_unit_header_) && !IsRadlPic(&slice_nal_unit_header_)) { - curr_pic_info_.prev_poc_lsb = m_sh_->slice_pic_order_cnt_lsb; + curr_pic_info_.prev_poc_lsb = p_slice_header->slice_pic_order_cnt_lsb; curr_pic_info_.prev_poc_msb = poc_msb; } } @@ -1954,6 +1969,7 @@ void HevcVideoParser::DecodeRps() { int curr_delta_poc_msb_present_flag[HEVC_MAX_NUM_REF_PICS] = {0}; // CurrDeltaPocMsbPresentFlag int foll_delta_poc_msb_present_flag[HEVC_MAX_NUM_REF_PICS] = {0}; // FollDeltaPocMsbPresentFlag int max_poc_lsb = 1 << (m_sps_[m_active_sps_id_].log2_max_pic_order_cnt_lsb_minus4 + 4); // MaxPicOrderCntLsb + HevcSliceSegHeader *p_slice_header = &slice_info_list_[0].slice_header; // When the current picture is an IRAP picture with NoRaslOutputFlag equal to 1, all reference pictures with // nuh_layer_id equal to currPicLayerId currently in the DPB (if any) are marked as "unused for reference". @@ -1975,7 +1991,7 @@ void HevcVideoParser::DecodeRps() { memset(poc_lt_curr_, 0, sizeof(int32_t) * HEVC_MAX_NUM_REF_PICS); memset(poc_lt_foll_, 0, sizeof(int32_t) * HEVC_MAX_NUM_REF_PICS); } else { - HevcShortTermRps *rps_ptr = &m_sh_->st_rps; + HevcShortTermRps *rps_ptr = &p_slice_header->st_rps; for (i = 0, j = 0, k = 0; i < rps_ptr->num_negative_pics; i++) { if (rps_ptr->used_by_curr_pic_s0[i]) { poc_st_curr_before_[j++] = curr_pic_info_.pic_order_cnt + rps_ptr->delta_poc_s0[i]; @@ -1995,19 +2011,19 @@ void HevcVideoParser::DecodeRps() { num_poc_st_curr_after_ = j; num_poc_st_foll_ = k; - HevcLongTermRps *lt_rps_ptr = &m_sh_->lt_rps; + HevcLongTermRps *lt_rps_ptr = &p_slice_header->lt_rps; for (i = 0, j = 0, k = 0; i < lt_rps_ptr->num_of_pics; i++) { uint32_t poc_lt = lt_rps_ptr->pocs[i]; // oocLt - if (m_sh_->delta_poc_msb_present_flag[i]) { - poc_lt += curr_pic_info_.pic_order_cnt - m_sh_->delta_poc_msb_cycle_lt[i] * max_poc_lsb - (curr_pic_info_.pic_order_cnt & (max_poc_lsb - 1)); + if (p_slice_header->delta_poc_msb_present_flag[i]) { + poc_lt += curr_pic_info_.pic_order_cnt - p_slice_header->delta_poc_msb_cycle_lt[i] * max_poc_lsb - (curr_pic_info_.pic_order_cnt & (max_poc_lsb - 1)); } if (lt_rps_ptr->used_by_curr_pic[i]) { poc_lt_curr_[j] = poc_lt; - curr_delta_poc_msb_present_flag[j++] = m_sh_->delta_poc_msb_present_flag[i]; + curr_delta_poc_msb_present_flag[j++] = p_slice_header->delta_poc_msb_present_flag[i]; } else { poc_lt_foll_[k] = poc_lt; - foll_delta_poc_msb_present_flag[k++] = m_sh_->delta_poc_msb_present_flag[i]; + foll_delta_poc_msb_present_flag[k++] = p_slice_header->delta_poc_msb_present_flag[i]; } } num_poc_lt_curr_ = j; @@ -2100,8 +2116,8 @@ void HevcVideoParser::DecodeRps() { } } -void HevcVideoParser::ConstructRefPicLists() { - +void HevcVideoParser::ConstructRefPicLists(HevcSliceInfo *p_slice_info) { + HevcSliceSegHeader *p_slice_header = &p_slice_info->slice_header; uint32_t num_rps_curr_temp_list; // NumRpsCurrTempList0 or NumRpsCurrTempList1; int i, j; int rIdx; @@ -2109,7 +2125,7 @@ void HevcVideoParser::ConstructRefPicLists() { /// List 0 rIdx = 0; - num_rps_curr_temp_list = std::max(m_sh_->num_ref_idx_l0_active_minus1 + 1, num_pic_total_curr_); + num_rps_curr_temp_list = std::max(p_slice_header->num_ref_idx_l0_active_minus1 + 1, num_pic_total_curr_); while (rIdx < num_rps_curr_temp_list) { for (i = 0; i < num_poc_st_curr_before_ && rIdx < num_rps_curr_temp_list; rIdx++, i++) { @@ -2125,14 +2141,14 @@ void HevcVideoParser::ConstructRefPicLists() { } } - for( rIdx = 0; rIdx <= m_sh_->num_ref_idx_l0_active_minus1; rIdx++) { - ref_pic_list_0_[rIdx] = m_sh_->ref_pic_list_modification_flag_l0 ? ref_pic_list_temp[m_sh_->list_entry_l0[rIdx]] : ref_pic_list_temp[rIdx]; + for( rIdx = 0; rIdx <= p_slice_header->num_ref_idx_l0_active_minus1; rIdx++) { + p_slice_info->ref_pic_list_0_[rIdx] = p_slice_header->ref_pic_list_modification_flag_l0 ? ref_pic_list_temp[p_slice_header->list_entry_l0[rIdx]] : ref_pic_list_temp[rIdx]; } /// List 1 - if (m_sh_->slice_type == HEVC_SLICE_TYPE_B) { + if (p_slice_header->slice_type == HEVC_SLICE_TYPE_B) { rIdx = 0; - num_rps_curr_temp_list = std::max(m_sh_->num_ref_idx_l1_active_minus1 + 1, num_pic_total_curr_); + num_rps_curr_temp_list = std::max(p_slice_header->num_ref_idx_l1_active_minus1 + 1, num_pic_total_curr_); while (rIdx < num_rps_curr_temp_list) { for (i = 0; i < num_poc_st_curr_after_ && rIdx < num_rps_curr_temp_list; rIdx++, i++) { @@ -2148,8 +2164,8 @@ void HevcVideoParser::ConstructRefPicLists() { } } - for( rIdx = 0; rIdx <= m_sh_->num_ref_idx_l1_active_minus1; rIdx++) { - ref_pic_list_1_[rIdx] = m_sh_->ref_pic_list_modification_flag_l1 ? ref_pic_list_temp[m_sh_->list_entry_l1[rIdx]] : ref_pic_list_temp[rIdx]; + for( rIdx = 0; rIdx <= p_slice_header->num_ref_idx_l1_active_minus1; rIdx++) { + p_slice_info->ref_pic_list_1_[rIdx] = p_slice_header->ref_pic_list_modification_flag_l1 ? ref_pic_list_temp[p_slice_header->list_entry_l1[rIdx]] : ref_pic_list_temp[rIdx]; } } } @@ -2205,7 +2221,7 @@ int HevcVideoParser::MarkOutputPictures() { if (IsCraPic(&slice_nal_unit_header_)) { no_output_of_prior_pics_flag = 1; } else { - no_output_of_prior_pics_flag = m_sh_->no_output_of_prior_pics_flag; + no_output_of_prior_pics_flag = slice_info_list_[0].slice_header.no_output_of_prior_pics_flag; } if (!no_output_of_prior_pics_flag) { diff --git a/src/parser/hevc_parser.h b/src/parser/hevc_parser.h index fb6e3df6eb..362c3c7880 100644 --- a/src/parser/hevc_parser.h +++ b/src/parser/hevc_parser.h @@ -84,6 +84,16 @@ protected: return nalu_header; } + /*! \brief Slice info of a picture + */ + typedef struct { + HevcSliceSegHeader slice_header; + uint32_t slice_data_offset; // offset in the slice data buffer of this slice + uint32_t slice_data_size; // slice data size in bytes + uint8_t ref_pic_list_0_[HEVC_MAX_NUM_REF_PICS]; // RefPicList0 + uint8_t ref_pic_list_1_[HEVC_MAX_NUM_REF_PICS]; // RefPicList1 + } HevcSliceInfo; + /*! \brief Picture info for decoding process */ typedef struct { @@ -121,8 +131,9 @@ protected: HevcVideoParamSet* m_vps_ = nullptr; HevcSeqParamSet* m_sps_ = nullptr; HevcPicParamSet* m_pps_ = nullptr; - HevcSliceSegHeader* m_sh_ = nullptr; HevcSliceSegHeader* m_sh_copy_ = nullptr; + std::vector slice_info_list_; + std::vector slice_param_list_; HevcNalUnitHeader slice_nal_unit_header_; HevcPicInfo curr_pic_info_; @@ -158,9 +169,6 @@ protected: uint8_t ref_pic_set_lt_curr_[HEVC_MAX_NUM_REF_PICS]; // RefPicSetLtCurr uint8_t ref_pic_set_lt_foll_[HEVC_MAX_NUM_REF_PICS]; // RefPicSetLtFoll - uint8_t ref_pic_list_0_[HEVC_MAX_NUM_REF_PICS]; // RefPicList0 - uint8_t ref_pic_list_1_[HEVC_MAX_NUM_REF_PICS]; // RefPicList1 - /*! \brief Function to parse Video Parameter Set * \param [in] nalu A pointer of uint8_t for the input stream to be parsed * \param [in] size Size of the input stream @@ -262,12 +270,12 @@ protected: void ParsePredWeightTable(HevcSliceSegHeader *slice_header_ptr, int chroma_array_type, uint8_t *stream_ptr, size_t &offset); /*! \brief Function to parse Slice Header - * \param [in] nal_unit_type Input of uint32_t containing the enumerator value to the NAL Unit Type * \param [in] nalu A pointer of uint8_t for the input stream to be parsed * \param [in] size Size of the input stream + * \param [out] p_slice_header Pointer to the slice header struct * \return True is successful, else false */ - bool ParseSliceHeader(uint8_t *nalu, size_t size); + bool ParseSliceHeader(uint8_t *nalu, size_t size, HevcSliceSegHeader *p_slice_header); /*! \brief Function to parse Sei Message Info * \param [in] nalu A pointer of uint8_t for the input stream to be parsed @@ -276,17 +284,18 @@ protected: */ void ParseSeiMessage(uint8_t *nalu, size_t size); - /*! \brief Function to calculate the picture order count of the current picture (8.3.1) + /*! \brief Function to calculate the picture order count of the current picture. Once per picutre. (8.3.1) */ void CalculateCurrPoc(); - /*! \brief Function to perform decoding process for reference picture set (8.3.2) + /*! \brief Function to perform decoding process for reference picture set. Once per picture. (8.3.2) */ void DecodeRps(); - /*! \brief Function to perform decoding process for reference picture lists construction (8.3.4) + /*! \brief Function to perform decoding process for reference picture lists construction per slice. (8.3.4) + * \param [in] p_slice_info Pointer to the slice info struct */ - void ConstructRefPicLists(); + void ConstructRefPicLists(HevcSliceInfo *p_slice_info); /*! \brief Function to initialize DPB buffer. */ diff --git a/src/parser/roc_video_parser.h b/src/parser/roc_video_parser.h index c82cd9a810..f98acde6c4 100644 --- a/src/parser/roc_video_parser.h +++ b/src/parser/roc_video_parser.h @@ -75,6 +75,7 @@ typedef struct { #define ZEROBYTES_SHORTSTARTCODE 2 //indicates the number of zero bytes in the short start-code prefix #define RBSP_BUF_SIZE 1024 // enough to parse any parameter sets or slice headers +#define INIT_SLICE_LIST_NUM 16 // initial slice information/parameter struct list size /** * @brief Base class for video parsing @@ -126,7 +127,7 @@ protected: int rbsp_size_; uint8_t rbsp_buf_[RBSP_BUF_SIZE]; // to store parameter set or slice header RBSP - int slice_num_; + int num_slices_; uint8_t* pic_stream_data_ptr_; int pic_stream_data_size_; diff --git a/src/rocdecode/vaapi/vaapi_videodecoder.cpp b/src/rocdecode/vaapi/vaapi_videodecoder.cpp index 5a08d17605..770ef23314 100644 --- a/src/rocdecode/vaapi/vaapi_videodecoder.cpp +++ b/src/rocdecode/vaapi/vaapi_videodecoder.cpp @@ -24,7 +24,8 @@ THE SOFTWARE. VaapiVideoDecoder::VaapiVideoDecoder(RocDecoderCreateInfo &decoder_create_info) : decoder_create_info_{decoder_create_info}, drm_fd_{-1}, va_display_{0}, va_config_attrib_{{}}, va_config_id_{0}, va_profile_ {VAProfileNone}, va_context_id_{0}, va_surface_ids_{{}}, - pic_params_buf_id_{0}, iq_matrix_buf_id_{0}, slice_params_buf_id_{0}, slice_data_buf_id_{0} {}; + pic_params_buf_id_{0}, iq_matrix_buf_id_{0}, num_slices_{0}, slice_data_buf_id_{0} { +}; VaapiVideoDecoder::~VaapiVideoDecoder() { if (drm_fd_ != -1) { @@ -185,9 +186,11 @@ rocDecStatus VaapiVideoDecoder::DestroyDataBuffers() { CHECK_VAAPI(vaDestroyBuffer(va_display_, iq_matrix_buf_id_)); iq_matrix_buf_id_ = 0; } - if (slice_params_buf_id_) { - CHECK_VAAPI(vaDestroyBuffer(va_display_, slice_params_buf_id_)); - slice_params_buf_id_ = 0; + for (int i = 0; i < num_slices_; i++) { + if (slice_params_buf_id_[i]) { + CHECK_VAAPI(vaDestroyBuffer(va_display_, slice_params_buf_id_[i])); + slice_params_buf_id_[i] = 0; + } } if (slice_data_buf_id_) { CHECK_VAAPI(vaDestroyBuffer(va_display_, slice_data_buf_id_)); @@ -231,7 +234,7 @@ rocDecStatus VaapiVideoDecoder::SubmitDecode(RocdecPicParams *pPicParams) { iq_matrix_size = sizeof(RocdecHevcIQMatrix); } - slice_params_ptr = (void*)&pPicParams->slice_params.hevc; + slice_params_ptr = (void*)pPicParams->slice_params.hevc; slice_params_size = sizeof(RocdecHevcSliceParams); if ((pic_params_size != sizeof(VAPictureParameterBufferHEVC)) || (scaling_list_enabled && (iq_matrix_size != sizeof(VAIQMatrixBufferHEVC))) || @@ -260,7 +263,7 @@ rocDecStatus VaapiVideoDecoder::SubmitDecode(RocdecPicParams *pPicParams) { iq_matrix_ptr = (void*)&pPicParams->iq_matrix.avc; iq_matrix_size = sizeof(RocdecAvcIQMatrix); - slice_params_ptr = (void*)&pPicParams->slice_params.avc; + slice_params_ptr = (void*)pPicParams->slice_params.avc; slice_params_size = sizeof(RocdecAvcSliceParams); if ((pic_params_size != sizeof(VAPictureParameterBufferH264)) || (iq_matrix_size != sizeof(VAIQMatrixBufferH264)) || (slice_params_size != sizeof(VASliceParameterBufferH264))) { @@ -276,16 +279,26 @@ rocDecStatus VaapiVideoDecoder::SubmitDecode(RocdecPicParams *pPicParams) { } } + // Destroy the data buffers of the previous frame rocDecStatus rocdec_status = DestroyDataBuffers(); if (rocdec_status != ROCDEC_SUCCESS) { ERR("Failed to destroy VAAPI buffer."); return rocdec_status; } + CHECK_VAAPI(vaCreateBuffer(va_display_, va_context_id_, VAPictureParameterBufferType, pic_params_size, 1, pic_params_ptr, &pic_params_buf_id_)); if (scaling_list_enabled) { CHECK_VAAPI(vaCreateBuffer(va_display_, va_context_id_, VAIQMatrixBufferType, iq_matrix_size, 1, iq_matrix_ptr, &iq_matrix_buf_id_)); } - CHECK_VAAPI(vaCreateBuffer(va_display_, va_context_id_, VASliceParameterBufferType, slice_params_size, 1, slice_params_ptr, &slice_params_buf_id_)); + // Resize if needed + num_slices_ = pPicParams->num_slices; + if (num_slices_ > slice_params_buf_id_.size()) { + slice_params_buf_id_.resize(num_slices_, {0}); + } + for (int i = 0; i < num_slices_; i++) { + CHECK_VAAPI(vaCreateBuffer(va_display_, va_context_id_, VASliceParameterBufferType, slice_params_size, 1, slice_params_ptr, &slice_params_buf_id_[i])); + slice_params_ptr = (void*)((uint8_t*)slice_params_ptr + slice_params_size); + } CHECK_VAAPI(vaCreateBuffer(va_display_, va_context_id_, VASliceDataBufferType, pPicParams->bitstream_data_len, 1, (void*)pPicParams->bitstream_data, &slice_data_buf_id_)); // Sumbmit buffers to VAAPI driver @@ -294,7 +307,7 @@ rocDecStatus VaapiVideoDecoder::SubmitDecode(RocdecPicParams *pPicParams) { if (scaling_list_enabled) { CHECK_VAAPI(vaRenderPicture(va_display_, va_context_id_, &iq_matrix_buf_id_, 1)); } - CHECK_VAAPI(vaRenderPicture(va_display_, va_context_id_, &slice_params_buf_id_, 1)); + CHECK_VAAPI(vaRenderPicture(va_display_, va_context_id_, slice_params_buf_id_.data(), num_slices_)); CHECK_VAAPI(vaRenderPicture(va_display_, va_context_id_, &slice_data_buf_id_, 1)); CHECK_VAAPI(vaEndPicture(va_display_, va_context_id_)); diff --git a/src/rocdecode/vaapi/vaapi_videodecoder.h b/src/rocdecode/vaapi/vaapi_videodecoder.h index e667125a23..ad07121e03 100644 --- a/src/rocdecode/vaapi/vaapi_videodecoder.h +++ b/src/rocdecode/vaapi/vaapi_videodecoder.h @@ -42,6 +42,8 @@ THE SOFTWARE. }\ } +#define INIT_SLICE_PARAM_LIST_NUM 16 // initial slice parameter buffer list size + class VaapiVideoDecoder { public: VaapiVideoDecoder(RocDecoderCreateInfo &decoder_create_info); @@ -64,7 +66,8 @@ private: VABufferID pic_params_buf_id_; VABufferID iq_matrix_buf_id_; - VABufferID slice_params_buf_id_; + std::vector slice_params_buf_id_ = std::vector(INIT_SLICE_PARAM_LIST_NUM, 0); + uint32_t num_slices_; VABufferID slice_data_buf_id_; uint32_t slice_data_buf_size_;