From b961ebfe197681ec9f3c8ff19b93184a7a7e275b Mon Sep 17 00:00:00 2001 From: jeffqjiangNew <142832361+jeffqjiangNew@users.noreply.github.com> Date: Wed, 15 Nov 2023 16:07:18 -0500 Subject: [PATCH] IRAP POC calculation fix. (#66) * * rocDecode/HEVC: Fixed a bug in IRAP picture order count calculation. Added a few picture type check utilities. * * rocDecode/HEVC: Minor coding style changes. No functional changes. [ROCm/rocdecode commit: 69c2243c9cbca3563003cdbb322ae958ea0c0b2d] --- projects/rocdecode/src/parser/hevc_parser.cpp | 73 ++++++++++++++++--- projects/rocdecode/src/parser/hevc_parser.h | 13 +++- 2 files changed, 73 insertions(+), 13 deletions(-) diff --git a/projects/rocdecode/src/parser/hevc_parser.cpp b/projects/rocdecode/src/parser/hevc_parser.cpp index 4a52ba986f..e447a13379 100644 --- a/projects/rocdecode/src/parser/hevc_parser.cpp +++ b/projects/rocdecode/src/parser/hevc_parser.cpp @@ -23,6 +23,9 @@ THE SOFTWARE. #include "hevc_parser.h" HEVCVideoParser::HEVCVideoParser() { + pic_count_ = 0; + first_pic_after_eos_nal_unit_ = 0; + m_active_vps_id_ = -1; m_active_sps_id_ = -1; m_active_pps_id_ = -1; @@ -83,6 +86,8 @@ rocDecStatus HEVCVideoParser::ParseVideoData(RocdecSourceDataPacket *p_data) { return ROCDEC_RUNTIME_ERROR; } + pic_count_++; + return ROCDEC_SUCCESS; } @@ -405,8 +410,8 @@ int HEVCVideoParser::SendPicForDecode() { pic_param_ptr->slice_parsing_fields.bits.deblocking_filter_override_enabled_flag = pps_ptr->deblocking_filter_override_enabled_flag; pic_param_ptr->slice_parsing_fields.bits.pps_disable_deblocking_filter_flag = pps_ptr->pps_deblocking_filter_disabled_flag; 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.RapPicFlag = (slice_nal_unit_header_.nal_unit_type >= NAL_UNIT_CODED_SLICE_BLA_W_LP && slice_nal_unit_header_.nal_unit_type <= NAL_UNIT_RESERVED_IRAP_VCL23) ? 1 : 0; - pic_param_ptr->slice_parsing_fields.bits.IdrPicFlag = (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) ? 1 : 0; + pic_param_ptr->slice_parsing_fields.bits.RapPicFlag = IsIrapPic(&slice_nal_unit_header_) ? 1 : 0; + pic_param_ptr->slice_parsing_fields.bits.IdrPicFlag = IsIdrPic(&slice_nal_unit_header_) ? 1 : 0; pic_param_ptr->slice_parsing_fields.bits.IntraPicFlag = m_sh_->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; @@ -628,7 +633,21 @@ bool HEVCVideoParser::ParseFrameData(const uint8_t* p_stream, uint32_t frame_dat // This is to consider the possibility of non-slice NAL units between slices. pic_stream_data_size_ = frame_data_size - curr_start_code_offset_; - ParseSliceHeader(slice_nal_unit_header_.nal_unit_type, m_rbsp_buf_, m_rbsp_size_); + ParseSliceHeader(m_rbsp_buf_, m_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; + } + else { + no_rasl_output_flag_ = 0; + } + } + + if (first_pic_after_eos_nal_unit_) { + first_pic_after_eos_nal_unit_ = 0; // clear the flag + } // Get POC CalculateCurrPOC(); @@ -656,6 +675,16 @@ bool HEVCVideoParser::ParseFrameData(const uint8_t* p_stream, uint32_t frame_dat break; } + case NAL_UNIT_EOS: { + first_pic_after_eos_nal_unit_ = 1; + break; + } + + case NAL_UNIT_EOB: { + pic_count_ = 0; + break; + } + default: break; } @@ -1511,7 +1540,7 @@ void HEVCVideoParser::ParsePps(uint8_t *nalu, size_t size) { #endif // DBGINFO } -bool HEVCVideoParser::ParseSliceHeader(uint32_t nal_unit_type, uint8_t *nalu, size_t size) { +bool HEVCVideoParser::ParseSliceHeader(uint8_t *nalu, size_t size) { PpsData *pps_ptr = NULL; SpsData *sps_ptr = NULL; size_t offset = 0; @@ -1520,7 +1549,7 @@ bool HEVCVideoParser::ParseSliceHeader(uint32_t nal_unit_type, uint8_t *nalu, si 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); - if (nal_unit_type >= NAL_UNIT_CODED_SLICE_BLA_W_LP && nal_unit_type <= NAL_UNIT_RESERVED_IRAP_VCL23) { + 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); } @@ -1566,7 +1595,7 @@ bool HEVCVideoParser::ParseSliceHeader(uint32_t nal_unit_type, uint8_t *nalu, si m_sh_->colour_plane_id = Parser::ReadBits(nalu, offset, 2); } - if (nal_unit_type != NAL_UNIT_CODED_SLICE_IDR_W_RADL && nal_unit_type != NAL_UNIT_CODED_SLICE_IDR_N_LP) { + 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)); @@ -1815,8 +1844,28 @@ void HEVCVideoParser::ParseSeiMessage(uint8_t *nalu, size_t size) { memcpy(m_sei_data_, sei_message_ptr, sei_message_ptr->payload_size); } +bool HEVCVideoParser::IsIdrPic(NalUnitHeader *nal_header_ptr) { + return (nal_header_ptr->nal_unit_type == NAL_UNIT_CODED_SLICE_IDR_W_RADL || nal_header_ptr->nal_unit_type == NAL_UNIT_CODED_SLICE_IDR_N_LP); +} + +bool HEVCVideoParser::IsBlaPic(NalUnitHeader *nal_header_ptr) { + return (nal_header_ptr->nal_unit_type == NAL_UNIT_CODED_SLICE_BLA_W_LP || nal_header_ptr->nal_unit_type == NAL_UNIT_CODED_SLICE_BLA_W_RADL || nal_header_ptr->nal_unit_type == NAL_UNIT_CODED_SLICE_BLA_N_LP); +} + +bool HEVCVideoParser::IsCraPic(NalUnitHeader *nal_header_ptr) { + return (nal_header_ptr->nal_unit_type == NAL_UNIT_CODED_SLICE_CRA_NUT); +} + +bool HEVCVideoParser::IsRaslPic(NalUnitHeader *nal_header_ptr) { + return (nal_header_ptr->nal_unit_type == NAL_UNIT_CODED_SLICE_RASL_N || nal_header_ptr->nal_unit_type == NAL_UNIT_CODED_SLICE_RASL_R); +} + +bool HEVCVideoParser::IsIrapPic(NalUnitHeader *nal_header_ptr) { + return (nal_header_ptr->nal_unit_type >= NAL_UNIT_CODED_SLICE_BLA_W_LP && nal_header_ptr->nal_unit_type <= NAL_UNIT_RESERVED_IRAP_VCL23); +} + void HEVCVideoParser::CalculateCurrPOC() { - 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) { + if (IsIdrPic(&slice_nal_unit_header_)) { curr_pic_info_.pic_order_cnt = 0; curr_pic_info_.prev_poc_lsb = 0; curr_pic_info_.prev_poc_msb = 0; @@ -1826,7 +1875,7 @@ void HEVCVideoParser::CalculateCurrPOC() { int max_poc_lsb = 1 << (m_sps_[m_active_sps_id_].log2_max_pic_order_cnt_lsb_minus4 + 4); // MaxPicOrderCntLsb int poc_msb; // PicOrderCntMsb // If the current picture is an IRAP picture with NoRaslOutputFlag equal to 1, PicOrderCntMsb is set equal to 0. - if (slice_nal_unit_header_.nal_unit_type >= NAL_UNIT_CODED_SLICE_BLA_W_LP && slice_nal_unit_header_.nal_unit_type <= NAL_UNIT_RESERVED_IRAP_VCL23) { + if (IsIrapPic(&slice_nal_unit_header_) && no_rasl_output_flag_ == 1) { poc_msb = 0; } else { @@ -1856,13 +1905,13 @@ void HEVCVideoParser::DeocdeRps() { // 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". - if (slice_nal_unit_header_.nal_unit_type >= NAL_UNIT_CODED_SLICE_BLA_W_LP && slice_nal_unit_header_.nal_unit_type <= NAL_UNIT_RESERVED_IRAP_VCL23) { + if (IsIrapPic(&slice_nal_unit_header_) && no_rasl_output_flag_ == 1) { for (i = 0; i < HVC_MAX_DPB_FRAMES; i++) { dpb_buffer_.frame_buffer_list[i].is_reference = kUnusedForReference; } } - 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) { + if (IsIdrPic(&slice_nal_unit_header_)) { num_poc_st_curr_before_ = 0; num_poc_st_curr_after_ = 0; num_poc_st_foll_ = 0; @@ -2535,14 +2584,14 @@ void HEVCVideoParser::PrintLtRefInfo(HEVCVideoParser::H265LongTermRPS *lt_info_p MSG(""); } -void HEVCVideoParser::PrintSeiMessage(HEVCVideoParser::SeiMessageDara *sei_message_ptr) { +void HEVCVideoParser::PrintSeiMessage(HEVCVideoParser::SeiMessageData *sei_message_ptr) { MSG("=== hevc_sei_message_info ==="); MSG("payload_type = " << sei_message_ptr->payload_type); MSG("payload_size = " << sei_message_ptr->payload_size); - MSG("pic_idx = " << sei_message_ptr->pic_idx); MSG_NO_NEWLINE("reserved[3]: "); for(int i = 0; i < 3; i++) { MSG_NO_NEWLINE(" " << sei_message_ptr->reserved[i]); } MSG(""); +} #endif // DBGINFO \ No newline at end of file diff --git a/projects/rocdecode/src/parser/hevc_parser.h b/projects/rocdecode/src/parser/hevc_parser.h index 83c88403ce..dbea04c7d7 100644 --- a/projects/rocdecode/src/parser/hevc_parser.h +++ b/projects/rocdecode/src/parser/hevc_parser.h @@ -665,6 +665,8 @@ protected: size_t EBSPtoRBSP(uint8_t *stream_buffer, size_t begin_bytepos, size_t end_bytepos); // Data members of HEVC class + uint32_t pic_count_; // decoded picture count for the current bitstream + NalUnitHeader nal_unit_header_; int32_t m_active_vps_id_; int32_t m_active_sps_id_; @@ -690,6 +692,9 @@ protected: uint8_t* pic_stream_data_ptr_; int pic_stream_data_size_; + int first_pic_after_eos_nal_unit_; // to flag the first picture after EOS + int no_rasl_output_flag_; // NoRaslOutputFlag + int pic_width_in_ctbs_y_; // PicWidthInCtbsY int pic_height_in_ctbs_y_; // PicHeightInCtbsY int pic_size_in_ctbs_y_; // PicSizeInCtbsY @@ -837,7 +842,7 @@ protected: * \param [in] size Size of the input stream * \return True is successful, else false */ - bool ParseSliceHeader(uint32_t nal_unit_type, uint8_t *nalu, size_t size); + bool ParseSliceHeader(uint8_t *nalu, size_t size); /*! \brief Function to parse Sei Message Info * \param [in] nalu A pointer of uint8_t for the input stream to be parsed @@ -923,4 +928,10 @@ private: * \return Return code in ParserResult form */ int SendPicForDecode(); + + bool IsIdrPic(NalUnitHeader *nal_header_ptr); + bool IsCraPic(NalUnitHeader *nal_header_ptr); + bool IsBlaPic(NalUnitHeader *nal_header_ptr); + bool IsIrapPic(NalUnitHeader *nal_header_ptr); + bool IsRaslPic(NalUnitHeader *nal_header_ptr); }; \ No newline at end of file