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
*/