diff --git a/src/parser/hevc_parser.cpp b/src/parser/hevc_parser.cpp index df197078cd..07e1cf7002 100644 --- a/src/parser/hevc_parser.cpp +++ b/src/parser/hevc_parser.cpp @@ -32,7 +32,9 @@ HEVCVideoParser::HEVCVideoParser() { m_pps_ = NULL; m_sh_ = NULL; m_sh_copy_ = NULL; - m_slice_ = NULL; + + memset(&curr_pic_info_, 0, sizeof(HevcPicInfo)); + memset(&dpb_buffer_, 0, sizeof(DecodedPictureBuffer)); } rocDecStatus HEVCVideoParser::Initialize(RocdecParserParams *p_params) { @@ -86,9 +88,6 @@ HEVCVideoParser::~HEVCVideoParser() { if (m_sh_copy_) { delete m_sh_copy_; } - if (m_slice_) { - delete m_slice_; - } } HEVCVideoParser::VpsData* HEVCVideoParser::AllocVps() { @@ -127,18 +126,6 @@ HEVCVideoParser::PpsData* HEVCVideoParser::AllocPps() { return p; } -HEVCVideoParser::SliceData* HEVCVideoParser::AllocSlice() { - SliceData *p = nullptr; - try { - p = new SliceData; - } - catch(const std::exception& e) { - ERR(STR("Failed to alloc Slice Data, ") + STR(e.what())) - } - memset(p, 0, sizeof(SliceData)); - return p; -} - HEVCVideoParser::SliceHeaderData* HEVCVideoParser::AllocSliceHeader() { SliceHeaderData *p = nullptr; try { @@ -156,7 +143,6 @@ ParserResult HEVCVideoParser::Init() { m_vps_ = AllocVps(); m_sps_ = AllocSps(); m_pps_ = AllocPps(); - m_slice_ = AllocSlice(); m_sh_ = AllocSliceHeader(); m_sh_copy_ = AllocSliceHeader(); return PARSER_OK; @@ -248,7 +234,6 @@ void HEVCVideoParser::FillSeqCallbackFn(SpsData* sps_data) { bool HEVCVideoParser::ParseFrameData(const uint8_t* p_stream, uint32_t frame_data_size) { int ret = PARSER_OK; - NalUnitHeader nal_unit_header; frame_data_buffer_ptr_ = (uint8_t*)p_stream; frame_data_size_ = frame_data_size; @@ -272,8 +257,8 @@ bool HEVCVideoParser::ParseFrameData(const uint8_t* p_stream, uint32_t frame_dat // start code + NAL unit header = 5 bytes int ebsp_size = nal_unit_size_ - 5 > RBSP_BUF_SIZE ? RBSP_BUF_SIZE : nal_unit_size_ - 5; // only copy enough bytes for header parsing - nal_unit_header = ParseNalUnitHeader(&frame_data_buffer_ptr_[curr_start_code_offset_ + 3]); - switch (nal_unit_header.nal_unit_type) { + nal_unit_header_ = ParseNalUnitHeader(&frame_data_buffer_ptr_[curr_start_code_offset_ + 3]); + switch (nal_unit_header_.nal_unit_type) { case NAL_UNIT_VPS: { memcpy(m_rbsp_buf_, (frame_data_buffer_ptr_ + curr_start_code_offset_ + 5), ebsp_size); m_rbsp_size_ = EBSPtoRBSP(m_rbsp_buf_, 0, ebsp_size); @@ -315,7 +300,21 @@ bool HEVCVideoParser::ParseFrameData(const uint8_t* p_stream, uint32_t frame_dat m_rbsp_size_ = EBSPtoRBSP(m_rbsp_buf_, 0, ebsp_size); // For each picture, only parse the first slice header if (slice_num_ == 0) { - ParseSliceHeader(nal_unit_header.nal_unit_type, m_rbsp_buf_, m_rbsp_size_); + ParseSliceHeader(nal_unit_header_.nal_unit_type, m_rbsp_buf_, m_rbsp_size_); + + // Get POC + CalculateCurrPOC(); + + // Decode RPS + DeocdeRps(); + + // Construct ref lists + if(m_sh_->slice_type == HEVC_SLICE_TYPE_P || m_sh_->slice_type == HEVC_SLICE_TYPE_B) { + ConstructRefPicLists(); + } + + // Find a free buffer in DPM and mark as used + FindFreeBufAndMark(); } slice_num_++; break; @@ -1192,39 +1191,11 @@ bool HEVCVideoParser::ParseSliceHeader(uint32_t nal_unit_type, uint8_t *nalu, si if (sps_ptr->separate_colour_plane_flag) { 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) { - m_slice_->curr_poc = 0; - m_slice_->prev_poc = m_slice_->curr_poc; - m_slice_->curr_poc_lsb = 0; - m_slice_->curr_poc_msb = 0; - m_slice_->prev_poc_lsb = m_slice_->curr_poc_lsb; - m_slice_->prev_poc_msb = m_slice_->curr_poc_msb; - } - else { + + if (nal_unit_type != NAL_UNIT_CODED_SLICE_IDR_W_RADL && 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)); - //get POC - m_slice_->curr_poc_lsb = m_sh_->slice_pic_order_cnt_lsb; - m_slice_->max_poc_lsb = 1 << (sps_ptr->log2_max_pic_order_cnt_lsb_minus4 + 4); - - if (nal_unit_type >= NAL_UNIT_CODED_SLICE_BLA_W_LP && nal_unit_type < NAL_UNIT_CODED_SLICE_CRA_NUT) { - m_slice_->curr_poc_msb = 0; - } - else { - if ((m_slice_->curr_poc_lsb < m_slice_->prev_poc_lsb) && ((m_slice_->prev_poc_lsb - m_slice_->curr_poc_lsb) >= (m_slice_->max_poc_lsb / 2))) - m_slice_->curr_poc_msb = m_slice_->prev_poc_msb + m_slice_->max_poc_lsb; - else if ((m_slice_->curr_poc_lsb > m_slice_->prev_poc_lsb) && ((m_slice_->curr_poc_lsb - m_slice_->prev_poc_lsb) > (m_slice_->max_poc_lsb / 2))) - m_slice_->curr_poc_msb = m_slice_->prev_poc_msb - m_slice_->max_poc_lsb; - else - m_slice_->curr_poc_msb = m_slice_->prev_poc_msb; - } - - m_slice_->curr_poc = m_slice_->curr_poc_lsb + m_slice_->curr_poc_msb; - m_slice_->prev_poc = m_slice_->curr_poc; - m_slice_->prev_poc_lsb = m_slice_->curr_poc_lsb; - m_slice_->prev_poc_msb = m_slice_->curr_poc_msb; - m_sh_->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) { @@ -1273,7 +1244,14 @@ bool HEVCVideoParser::ParseSliceHeader(uint32_t nal_unit_type, uint8_t *nalu, si } m_sh_->delta_poc_msb_present_flag[i] = Parser::GetBit(nalu, offset); if (m_sh_->delta_poc_msb_present_flag[i]) { - m_sh_->delta_poc_msb_cycle_lt[i] = Parser::ExpGolomb::ReadUe(nalu, offset); + // Store DeltaPocMsbCycleLt in delta_poc_msb_cycle_lt for later use + int 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; + } + else { + m_sh_->delta_poc_msb_cycle_lt[i] = delta_poc_msb_cycle_lt + m_sh_->delta_poc_msb_cycle_lt[i - 1]; + } } } } @@ -1308,12 +1286,12 @@ bool HEVCVideoParser::ParseSliceHeader(uint32_t nal_unit_type, uint8_t *nalu, si // 7.3.6.2 Reference picture list modification // Calculate NumPicTotalCurr - int num_pic_total_curr = 0; + num_pic_total_curr_ = 0; H265ShortTermRPS *st_rps_ptr = &m_sh_->st_rps; // Check the combined list for (int i = 0; i < st_rps_ptr->num_of_delta_poc; i++) { if (st_rps_ptr->used_by_curr_pic[i]) { - num_pic_total_curr++; + num_pic_total_curr_++; } } @@ -1321,14 +1299,14 @@ bool HEVCVideoParser::ParseSliceHeader(uint32_t nal_unit_type, uint8_t *nalu, si // 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]) { - num_pic_total_curr++; + num_pic_total_curr_++; } } - if (pps_ptr->lists_modification_present_flag && num_pic_total_curr > 1) + if (pps_ptr->lists_modification_present_flag && num_pic_total_curr_ > 1) { int list_entry_bits = 0; - while ((1 << list_entry_bits) < num_pic_total_curr) { + while ((1 << list_entry_bits) < num_pic_total_curr_) { list_entry_bits++; } @@ -1431,6 +1409,287 @@ bool HEVCVideoParser::ParseSliceHeader(uint32_t nal_unit_type, uint8_t *nalu, si return false; } +void HEVCVideoParser::CalculateCurrPOC() { + if (nal_unit_header_.nal_unit_type == NAL_UNIT_CODED_SLICE_IDR_W_RADL || nal_unit_header_.nal_unit_type == NAL_UNIT_CODED_SLICE_IDR_N_LP) { + curr_pic_info_.pic_order_cnt = 0; + curr_pic_info_.prev_poc_lsb = 0; + curr_pic_info_.prev_poc_msb = 0; + curr_pic_info_.slice_pic_order_cnt_lsb = 0; + } + else { + 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 (nal_unit_header_.nal_unit_type >= NAL_UNIT_CODED_SLICE_BLA_W_LP && nal_unit_header_.nal_unit_type <= NAL_UNIT_RESERVED_IRAP_VCL23) { + 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))) { + 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))) { + 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_.prev_poc_lsb = m_sh_->slice_pic_order_cnt_lsb; + curr_pic_info_.prev_poc_msb = poc_msb; + curr_pic_info_.slice_pic_order_cnt_lsb = m_sh_->slice_pic_order_cnt_lsb; + } +} + +void HEVCVideoParser::DeocdeRps() { + int i, j, k; + int curr_delta_proc_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 + + // 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 (nal_unit_header_.nal_unit_type >= NAL_UNIT_CODED_SLICE_BLA_W_LP && nal_unit_header_.nal_unit_type <= NAL_UNIT_RESERVED_IRAP_VCL23) { + for (i = 0; i < HVC_MAX_DPB_FRAMES; i++) { + dpb_buffer_.frame_buffer_list[i].is_reference = kUnusedForReference; + } + } + + if (nal_unit_header_.nal_unit_type == NAL_UNIT_CODED_SLICE_IDR_W_RADL || nal_unit_header_.nal_unit_type == NAL_UNIT_CODED_SLICE_IDR_N_LP) { + num_poc_st_curr_before_ = 0; + num_poc_st_curr_after_ = 0; + num_poc_st_foll_ = 0; + num_poc_lt_curr_ = 0; + num_poc_lt_foll_ = 0; + memset(poc_st_curr_before_, 0, sizeof(int32_t) * HEVC_MAX_NUM_REF_PICS); + memset(poc_st_curr_after_, 0, sizeof(int32_t) * HEVC_MAX_NUM_REF_PICS); + memset(poc_st_foll_, 0, sizeof(int32_t) * HEVC_MAX_NUM_REF_PICS); + 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 { + H265ShortTermRPS *rps_ptr = &m_sh_->st_rps; + for (i = 0, j = 0, k = 0; i < rps_ptr->num_negative_pics; i++) { + if (rps_ptr->used_by_curr_pic[i]) { // UsedByCurrPicS0 + poc_st_curr_before_[j++] = curr_pic_info_.pic_order_cnt + rps_ptr->delta_poc[i]; // DeltaPocS0 + } + else { + poc_st_foll_[k++] = curr_pic_info_.pic_order_cnt + rps_ptr->delta_poc[i]; + } + } + num_poc_st_curr_before_ = j; + + // UsedByCurrPicS1 follows UsedByCurrPicS0 in used_by_curr_pic. DeltaPocS1 follows DeltaPocS0 in delta_poc. + for (j = 0; i < rps_ptr->num_of_delta_poc; i++ ) { + if (rps_ptr->used_by_curr_pic[i]) { // UsedByCurrPicS1 + poc_st_curr_after_[j++] = curr_pic_info_.pic_order_cnt + rps_ptr->delta_poc[i]; // DeltaPocS1 + } + else { + poc_st_foll_[k++] = curr_pic_info_.pic_order_cnt + rps_ptr->delta_poc[i]; // DeltaPocS1 + } + } + num_poc_st_curr_after_ = j; + num_poc_st_foll_ = k; + + H265LongTermRPS *lt_rps_ptr = &m_sh_->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 (lt_rps_ptr->used_by_curr_pic[i]) { + poc_lt_curr_[j] = poc_lt; + curr_delta_proc_msb_present_flag[j++] = m_sh_->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]; + } + } + num_poc_lt_curr_ = j; + num_poc_lt_foll_ = k; + + /* + * RPS derivation and picture marking + */ + // Init as "no reference picture" + for (i = 0; i < HEVC_MAX_NUM_REF_PICS; i++) { + ref_pic_set_st_curr_before_[i] = 0xFF; + ref_pic_set_st_curr_after_[i] = 0xFF; + ref_pic_set_st_foll_[i] = 0xFF; + ref_pic_set_lt_curr_[i] = 0xFF; + ref_pic_set_lt_foll_[i] = 0xFF; + } + + // Mark all in DPB as unused. We will mark them back while we go through the ref lists. The rest will be actually unused. + for (i = 0; i < HVC_MAX_DPB_FRAMES; i++) { + dpb_buffer_.frame_buffer_list[i].is_reference = kUnusedForReference; + } + + /// Short term reference pictures + for (i = 0; i < num_poc_st_curr_before_; i++) { + for (j = 0; j < HVC_MAX_DPB_FRAMES; j++) { + if (poc_st_curr_before_[i] == dpb_buffer_.frame_buffer_list[j].pic_order_cnt) { + ref_pic_set_st_curr_before_[i] = j; // RefPicSetStCurrBefore. Use DPB buffer index for now + dpb_buffer_.frame_buffer_list[j].is_reference = kUsedForShortTerm; + break; + } + } + } + + for (i = 0; i < num_poc_st_curr_after_; i++) { + for (j = 0; j < HVC_MAX_DPB_FRAMES; j++) { + if (poc_st_curr_after_[i] == dpb_buffer_.frame_buffer_list[j].pic_order_cnt) { + ref_pic_set_st_curr_after_[i] = j; // RefPicSetStCurrAfter + dpb_buffer_.frame_buffer_list[j].is_reference = kUsedForShortTerm; + break; + } + } + } + + for ( i = 0; i < num_poc_st_foll_; i++ ) { + for (j = 0; j < HVC_MAX_DPB_FRAMES; j++) { + if (poc_st_foll_[i] == dpb_buffer_.frame_buffer_list[j].pic_order_cnt) { + ref_pic_set_st_foll_[i] = j; // RefPicSetStFoll + dpb_buffer_.frame_buffer_list[j].is_reference = kUsedForShortTerm; + break; + } + } + } + + /// Long term reference pictures + for (i = 0; i < num_poc_lt_curr_; i++) { + for (j = 0; j < HVC_MAX_DPB_FRAMES; j++) { + if(!curr_delta_proc_msb_present_flag[i]) { + if (poc_lt_curr_[i] == (dpb_buffer_.frame_buffer_list[j].pic_order_cnt & (max_poc_lsb - 1))) { + ref_pic_set_lt_curr_[i] = j; // RefPicSetLtCurr + dpb_buffer_.frame_buffer_list[j].is_reference = kUsedForLongTerm; + break; + } + } + else { + if (poc_lt_curr_[i] == dpb_buffer_.frame_buffer_list[j].pic_order_cnt) { + ref_pic_set_lt_curr_[i] = j; // RefPicSetLtCurr + dpb_buffer_.frame_buffer_list[j].is_reference = kUsedForLongTerm; + break; + } + } + } + } + + for (i = 0; i < num_poc_lt_foll_; i++) { + for (j = 0; j < HVC_MAX_DPB_FRAMES; j++) { + if(!foll_delta_poc_msb_present_flag[i]) { + if (poc_lt_foll_[i] == (dpb_buffer_.frame_buffer_list[j].pic_order_cnt & (max_poc_lsb - 1))) { + ref_pic_set_lt_foll_[i] = j; // RefPicSetLtFoll + dpb_buffer_.frame_buffer_list[j].is_reference = kUsedForLongTerm; + break; + } + } + else { + if (poc_lt_foll_[i] == dpb_buffer_.frame_buffer_list[j].pic_order_cnt) { + ref_pic_set_lt_foll_[i] = j; // RefPicSetLtFoll + dpb_buffer_.frame_buffer_list[j].is_reference = kUsedForLongTerm; + break; + } + } + } + } + } +} + +void HEVCVideoParser::ConstructRefPicLists() { + + uint32_t num_rps_curr_temp_list; // NumRpsCurrTempList0 or NumRpsCurrTempList1; + int i, j; + int rIdx; + uint32_t ref_pic_list_temp[HEVC_MAX_NUM_REF_PICS]; // RefPicListTemp0 or RefPicListTemp1 + + /// List 0 + rIdx = 0; + num_rps_curr_temp_list = std::max(m_sh_->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++) { + ref_pic_list_temp[rIdx] = ref_pic_set_st_curr_before_[i]; + } + + for (i = 0; i < num_poc_st_curr_after_ && rIdx < num_rps_curr_temp_list; rIdx++, i++) { + ref_pic_list_temp[rIdx] = ref_pic_set_st_curr_after_[i]; + } + + for (i = 0; i < num_poc_lt_curr_ && rIdx < num_rps_curr_temp_list; rIdx++, i++) { + ref_pic_list_temp[rIdx] = ref_pic_set_lt_curr_[i]; + } + } + + 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]; + } + + /// List 1 + if (m_sh_->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_); + + while (rIdx < num_rps_curr_temp_list) { + for (i = 0; i < num_poc_st_curr_after_ && rIdx < num_rps_curr_temp_list; rIdx++, i++) { + ref_pic_list_temp[rIdx] = ref_pic_set_st_curr_after_[i]; + } + + for (i = 0; i < num_poc_st_curr_before_ && rIdx < num_rps_curr_temp_list; rIdx++, i++ ) { + ref_pic_list_temp[rIdx] = ref_pic_set_st_curr_before_[i]; + } + + for (i = 0; i < num_poc_lt_curr_ && rIdx < num_rps_curr_temp_list; rIdx++, i++ ) { + ref_pic_list_temp[rIdx] = ref_pic_set_lt_curr_[i]; + } + } + + 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]; + } + } +} + +int HEVCVideoParser::FindFreeBufAndMark() { + int i; + + // Clear usage flags. For now, buffers that are unused for refrence are marked as empty. + // Todo: implement HEVC DPU output policy + dpb_buffer_.dpb_fullness = 0; + for (i = 0; i < HVC_MAX_DPB_FRAMES; i++) { + if (dpb_buffer_.frame_buffer_list[i].is_reference == kUnusedForReference) { + dpb_buffer_.frame_buffer_list[i].use_status = 0; + } + else { + dpb_buffer_.frame_buffer_list[i].use_status = 3; // frame used + dpb_buffer_.dpb_fullness++; + } + } + + if (dpb_buffer_.dpb_fullness == HVC_MAX_DPB_FRAMES) { + // Buffer is full + return PARSER_NOT_FOUND; + } + else { + for (i = 0; i < HVC_MAX_DPB_FRAMES; i++) { + if (dpb_buffer_.frame_buffer_list[i].use_status == 0) { + break; + } + } + } + + dpb_buffer_.frame_buffer_list[i] = curr_pic_info_; + dpb_buffer_.frame_buffer_list[i].is_reference = kUsedForShortTerm; + dpb_buffer_.frame_buffer_list[i].use_status = 3; + dpb_buffer_.dpb_fullness++; + + return PARSER_OK; +} + size_t HEVCVideoParser::EBSPtoRBSP(uint8_t *streamBuffer,size_t begin_bytepos, size_t end_bytepos) { int count = 0; if (end_bytepos < begin_bytepos) { diff --git a/src/parser/hevc_parser.h b/src/parser/hevc_parser.h index 02e52be1bc..3436b368ef 100644 --- a/src/parser/hevc_parser.h +++ b/src/parser/hevc_parser.h @@ -41,6 +41,8 @@ extern int scaling_list_default_3[1][2][64]; #define MAX_SPS_COUNT 16 // 7.3.2.2.1 #define MAX_PPS_COUNT 64 // 7.4.3.3.1 #define RBSP_BUF_SIZE 1024 // enough to parse any parameter sets or slice headers +#define HVC_MAX_DPB_FRAMES 16 // (A-2) +#define HEVC_MAX_NUM_REF_PICS 16 class HEVCVideoParser : public RocVideoParser { @@ -248,8 +250,8 @@ protected: */ typedef struct { int32_t num_of_pics; - int32_t pocs[32]; - bool used_by_curr_pic[32]; + int32_t pocs[32]; // PocLsbLt + bool used_by_curr_pic[32]; // UsedByCurrPicLt } H265LongTermRPS; /*! \brief Structure for Sub Layer Hypothetical Reference Decoder Parameters @@ -532,18 +534,6 @@ protected: H265RbspTrailingBits rbsp_trailing_bits; } PpsData; - /*! \brief Structure for Slice Data - */ - typedef struct { - uint32_t prev_poc; - uint32_t curr_poc; - uint32_t prev_poc_lsb; - uint32_t prev_poc_msb; - uint32_t curr_poc_lsb; - uint32_t curr_poc_msb; - uint32_t max_poc_lsb; - } SliceData; - /*! \brief Structure for Slice Header Data */ typedef struct { @@ -624,6 +614,35 @@ protected: return nalu_header; } + enum HevcRefMarking { + kUnusedForReference = 0, + kUsedForShortTerm = 1, + kUsedForLongTerm = 2 + }; + + /*! \brief Picture info for decoding process + */ + typedef struct { + // POC info + int32_t pic_order_cnt; // PicOrderCnt + int32_t prev_poc_lsb; // prevPicOrderCntLsb + int32_t prev_poc_msb; // prevPicOrderCntMsb + uint32_t slice_pic_order_cnt_lsb; // for long term ref pic identification + + uint32_t is_reference; + uint32_t use_status; // 0 = empty; 1 = top used; 2 = bottom used; 3 = both fields or frame used + } HevcPicInfo; + + /*! \brief Decoded picture buffer + */ + typedef struct + { + uint32_t num_pics_not_yet_output; /// number of pictures in DPB that have not been output yet + uint32_t dpb_fullness; /// number of pictures in DPB + + HevcPicInfo frame_buffer_list[HVC_MAX_DPB_FRAMES]; + } DecodedPictureBuffer; + /*! \brief Function to convert from Encapsulated Byte Sequence Packets to Raw Byte Sequence Payload * * \param [inout] stream_buffer A pointer of uint8_t for the converted RBSP buffer. @@ -634,6 +653,7 @@ protected: size_t EBSPtoRBSP(uint8_t *stream_buffer, size_t begin_bytepos, size_t end_bytepos); // Data members of HEVC class + NalUnitHeader nal_unit_header_; int32_t m_active_vps_id_; int32_t m_active_sps_id_; int32_t m_active_pps_id_; @@ -642,13 +662,39 @@ protected: PpsData* m_pps_; SliceHeaderData* m_sh_; SliceHeaderData* m_sh_copy_; - SliceData* m_slice_; + HevcPicInfo curr_pic_info_; bool b_new_picture_; int m_packet_count_; int slice_num_; int m_rbsp_size_; uint8_t m_rbsp_buf_[RBSP_BUF_SIZE]; // to store parameter set or slice header RBSP + // DPB + DecodedPictureBuffer dpb_buffer_; + + uint32_t num_pic_total_curr_; // NumPicTotalCurr + + // Reference picture set + uint32_t num_poc_st_curr_before_; // NumPocStCurrBefore; + uint32_t num_poc_st_curr_after_; // NumPocStCurrAfter; + uint32_t num_poc_st_foll_; // NumPocStFoll; + uint32_t num_poc_lt_curr_; // NumPocLtCurr; + uint32_t num_poc_lt_foll_; // NumPocLtFoll; + + int32_t poc_st_curr_before_[HEVC_MAX_NUM_REF_PICS]; // PocStCurrBefore + int32_t poc_st_curr_after_[HEVC_MAX_NUM_REF_PICS]; // PocStCurrAfter + int32_t poc_st_foll_[HEVC_MAX_NUM_REF_PICS]; // PocStFoll + int32_t poc_lt_curr_[HEVC_MAX_NUM_REF_PICS]; // PocLtCurr + int32_t poc_lt_foll_[HEVC_MAX_NUM_REF_PICS]; // PocLtFoll + uint8_t ref_pic_set_st_curr_before_[HEVC_MAX_NUM_REF_PICS]; // RefPicSetStCurrBefore + uint8_t ref_pic_set_st_curr_after_[HEVC_MAX_NUM_REF_PICS]; // RefPicSetStCurrAfter + uint8_t ref_pic_set_st_foll_[HEVC_MAX_NUM_REF_PICS]; // RefPicSetStFoll + 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 + // Frame bit stream info uint8_t *frame_data_buffer_ptr_; // bit stream buffer pointer of the current frame from the demuxer int frame_data_size_; // bit stream size of the current frame @@ -768,6 +814,23 @@ protected: */ bool ParseSliceHeader(uint32_t nal_unit_type, uint8_t *nalu, size_t size); + /*! \brief Function to calculate the picture order count of the current picture (8.3.1) + */ + void CalculateCurrPOC(); + + /*! \brief Function to perform decoding process for reference picture set (8.3.2) + */ + void DeocdeRps(); + + /*! \brief Function to perform decoding process for reference picture lists construction (8.3.4) + */ + void ConstructRefPicLists(); + + /*! \brief Function to find a free buffer in DPM for the current picture and mark it. + * \return Code in ParserResult form. + */ + int FindFreeBufAndMark(); + /*! \brief Function to parse the data received from the demuxer. * \param [in] p_stream A pointer of uint8_t for the input stream to be parsed * \param [in] frame_data_size Size of the input stream @@ -810,11 +873,6 @@ private: */ PpsData* AllocPps(); - /*! \brief Function to allocate memory for Slice Structure - * \return Returns pointer to the allocated memory for SliceData - */ - SliceData* AllocSlice(); - /*! \brief Function to allocate memory for Slice Header Structure * \return Returns pointer to the allocated memory for SliceHeaderData */