From 300be009dec6f0cbf701a6d716bd8867dd19f008 Mon Sep 17 00:00:00 2001 From: jeffqjiangNew <142832361+jeffqjiangNew@users.noreply.github.com> Date: Thu, 1 Feb 2024 09:58:00 -0500 Subject: [PATCH] * rocDecode/AVC: Added initial B frame support. (#214) - Basic B frames are decoded clean now. --- src/parser/avc_parser.cpp | 144 +++++++++++++++++++++++++++++++++++--- 1 file changed, 134 insertions(+), 10 deletions(-) diff --git a/src/parser/avc_parser.cpp b/src/parser/avc_parser.cpp index 0bd3294edd..12e0acdffe 100644 --- a/src/parser/avc_parser.cpp +++ b/src/parser/avc_parser.cpp @@ -1580,22 +1580,46 @@ static inline int ComparePicNumDesc(const void *p_pic_info_1, const void *p_pic_ if (pic_num_1 < pic_num_2) { return 1; - } - if (pic_num_1 > pic_num_2) { + } else if (pic_num_1 > pic_num_2) { return -1; } else { return 0; } } +static inline int ComparePocDesc(const void *p_pic_info_1, const void *p_pic_info_2) { + int poc_1 = ((AvcVideoParser::AvcPicture*)p_pic_info_1)->pic_order_cnt; + int poc_2 = ((AvcVideoParser::AvcPicture*)p_pic_info_2)->pic_order_cnt; + + if (poc_1 < poc_2) { + return 1; + } else if (poc_1 > poc_2) { + return -1; + } else { + return 0; + } +} + +static inline int ComparePocAsc(const void *p_pic_info_1, const void *p_pic_info_2) { + int poc_1 = ((AvcVideoParser::AvcPicture*)p_pic_info_1)->pic_order_cnt; + int poc_2 = ((AvcVideoParser::AvcPicture*)p_pic_info_2)->pic_order_cnt; + + if (poc_1 < poc_2) { + return -1; + } else if (poc_1 > poc_2) { + return 1; + } else { + return 0; + } +} + static inline int CompareLongTermPicNumAsc(const void *p_pic_info_1, const void *p_pic_info_2) { int long_term_pic_num_1 = ((AvcVideoParser::AvcPicture*)p_pic_info_1)->long_term_pic_num; int long_term_pic_num_2 = ((AvcVideoParser::AvcPicture*)p_pic_info_2)->long_term_pic_num; if (long_term_pic_num_1 < long_term_pic_num_2) { return -1; - } - if (long_term_pic_num_1 > long_term_pic_num_2) { + } else if (long_term_pic_num_1 > long_term_pic_num_2) { return 1; } else { return 0; @@ -1608,6 +1632,9 @@ void AvcVideoParser::SetupReflist() { AvcSliceHeader *p_slice_header = &slice_header_0_; int i; + memset(ref_list_0_, 0, sizeof(ref_list_0_)); + memset(ref_list_1_, 0, sizeof(ref_list_1_)); + // 8.2.4.1. Calculate picture numbers for (i = 0; i < AVC_MAX_DPB_FRAMES; i++) { AvcPicture *p_ref_pic = &dpb_buffer_.frame_buffer_list[i]; @@ -1641,7 +1668,7 @@ void AvcVideoParser::SetupReflist() { // 8.2.4.2 Initialisation process for reference picture lists if (p_slice_header->slice_type == kAvcSliceTypeP || p_slice_header->slice_type == kAvcSliceTypeP_5) { - if (curr_pic_.pic_structure == kFrame) { + if (curr_pic_.pic_structure == kFrame) { // 8.2.4.2.1 // Group short term ref pictures int ref_index = 0; for (i = 0; i < AVC_MAX_DPB_FRAMES; i++) { @@ -1660,23 +1687,120 @@ void AvcVideoParser::SetupReflist() { } } // Sort short term refs with descending order of pic_num - if (dpb_buffer_.num_short_term) { + if (dpb_buffer_.num_short_term > 1) { qsort((void*)ref_list_0_, dpb_buffer_.num_short_term, sizeof(AvcPicture), ComparePicNumDesc); } // Sort long term refs with ascending order of long_term_pic_num - if (dpb_buffer_.num_long_term) { + if (dpb_buffer_.num_long_term > 1) { qsort((void*)&ref_list_0_[dpb_buffer_.num_short_term], dpb_buffer_.num_long_term, sizeof(AvcPicture), CompareLongTermPicNumAsc); } - } else { + } else { // 8.2.4.2.2 std::cout << "Error!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Todo: Add P ref field list init." << std::endl; } } else { - std::cout << "Error!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Todo: Add B ref list init." << std::endl; + if (curr_pic_.pic_structure == kFrame) { // 8.2.4.2.3 + // RefPicList0 + int num_short_term_smaller = 0; + int num_short_term_greater = 0; + int num_long_term = 0; + int ref_index = 0; + // Group short term ref pictures that have smaller POC than the current picture + for (i = 0; i < AVC_MAX_DPB_FRAMES; i++) { + AvcPicture *p_ref_pic = &dpb_buffer_.frame_buffer_list[i]; + if (p_ref_pic->is_reference == kUsedForShortTerm && p_ref_pic->pic_order_cnt < curr_pic_.pic_order_cnt) { + ref_list_0_[ref_index] = *p_ref_pic; + num_short_term_smaller++; + ref_index++; + } + } + // Sort in descending order of POC + if (num_short_term_smaller > 1) { + qsort((void*)ref_list_0_, num_short_term_smaller, sizeof(AvcPicture), ComparePocDesc); + } + + // Group short term ref pictures that have greater POC than the current picture + for (i = 0; i < AVC_MAX_DPB_FRAMES; i++) { + AvcPicture *p_ref_pic = &dpb_buffer_.frame_buffer_list[i]; + if (p_ref_pic->is_reference == kUsedForShortTerm && p_ref_pic->pic_order_cnt > curr_pic_.pic_order_cnt) { + ref_list_0_[ref_index] = *p_ref_pic; + num_short_term_greater++; + ref_index++; + } + } + // Sort in ascending order of POC + if (num_short_term_greater > 1) { + qsort((void*)&ref_list_0_[num_short_term_smaller], num_short_term_greater, sizeof(AvcPicture), ComparePocAsc); + } + + // Group long term ref pictures + for (i = 0; i < AVC_MAX_DPB_FRAMES; i++) { + AvcPicture *p_ref_pic = &dpb_buffer_.frame_buffer_list[i]; + if (p_ref_pic->is_reference == kUsedForLongTerm) { + ref_list_0_[ref_index] = *p_ref_pic; + num_long_term++; + ref_index++; + } + } + // Sort long term refs with ascending order of long_term_pic_num + if (num_long_term > 1) { + qsort((void*)&ref_list_0_[num_short_term_smaller + num_short_term_greater], num_long_term, sizeof(AvcPicture), CompareLongTermPicNumAsc); + } + + // RefPicList1 + num_short_term_smaller = 0; + num_short_term_greater = 0; + num_long_term = 0; + ref_index = 0; + + // Group short term ref pictures that have greater POC than the current picture + for (i = 0; i < AVC_MAX_DPB_FRAMES; i++) { + AvcPicture *p_ref_pic = &dpb_buffer_.frame_buffer_list[i]; + if (p_ref_pic->is_reference == kUsedForShortTerm && p_ref_pic->pic_order_cnt > curr_pic_.pic_order_cnt) { + ref_list_1_[ref_index] = *p_ref_pic; + num_short_term_greater++; + ref_index++; + } + } + // Sort in ascending order of POC + if (num_short_term_greater > 1) { + qsort((void*)ref_list_1_, num_short_term_greater, sizeof(AvcPicture), ComparePocAsc); + } + + // Group short term ref pictures that have smaller POC than the current picture + for (i = 0; i < AVC_MAX_DPB_FRAMES; i++) { + AvcPicture *p_ref_pic = &dpb_buffer_.frame_buffer_list[i]; + if (p_ref_pic->is_reference == kUsedForShortTerm && p_ref_pic->pic_order_cnt < curr_pic_.pic_order_cnt) { + ref_list_1_[ref_index] = *p_ref_pic; + num_short_term_smaller++; + ref_index++; + } + } + // Sort in descending order of POC + if (num_short_term_smaller > 1) { + qsort((void*)&ref_list_1_[num_short_term_greater], num_short_term_smaller, sizeof(AvcPicture), ComparePocDesc); + } + + // Group long term ref pictures + for (i = 0; i < AVC_MAX_DPB_FRAMES; i++) { + AvcPicture *p_ref_pic = &dpb_buffer_.frame_buffer_list[i]; + if (p_ref_pic->is_reference == kUsedForLongTerm) { + ref_list_1_[ref_index] = *p_ref_pic; + num_long_term++; + ref_index++; + } + } + // Sort long term refs with ascending order of long_term_pic_num + if (num_long_term > 1) { + qsort((void*)&ref_list_1_[num_short_term_smaller + num_short_term_greater], num_long_term, sizeof(AvcPicture), CompareLongTermPicNumAsc); + } + } else { // 8.2.4.2.4 + std::cout << "Error!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Todo: Add B ref field list init." << std::endl; + } } // 8.2.4.3 Modification process for reference picture lists if (p_slice_header->ref_pic_list.ref_pic_list_modification_flag_l0 == 1) { - std::cout << "Error! Todo: Added ref list 0 modification support." << std::endl; + std::cout << "Error!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Todo: Added ref list 0 modification support." << std::endl; } if (p_slice_header->slice_type == kAvcSliceTypeB || p_slice_header->slice_type == kAvcSliceTypeB_6) {