rocDecode: Added decode buffer pool implementation for AVC and HEVC. (#355)

* * rocDecode: Initial check in for decode buffer pool.

* * rocDecode: All 135 streams pass.

* * rocDecode: Fixed a build error in debug mode.

* * rocDecode/HEVC: Removed two workaround in HEVC DPB management, after decode buffer pool implementa
tion.
 - WR 1: Conditional bumping (when max_num_reorder_pics > 0) to avoid synchronous job submission in
C.5.2.3.
 - WR 2: Add two more buffers in DPB to avoid buffer over-writing.

* * rocDecode/HEVC: Added display delay feature.

* * rocDecode/HEVC: Fixed the -z option issue within the context of the new decode buffer pool implementation.

* * rocDecode/HEVC: Removed redundent code.

* * rocDecode/AVC: Added decode buffer pool implementation for AVC.

* * rocDecode: Added a few changes.
 - Added display delay feature to AVC.
 - Removed a workaround for AVC: AVC_MAX_DPB_FRAMES was increased to 18. Now it is back to 16.
 - Removed a workaround for AVC: increased DPB buffer size by 2. Now it is back to normal.
 - Code format changes for HEVC.

* * rocDecode/AVC: Fixed the -z option issue within the context of the new decode buffer pool implementation.

* * rocDecode: Merged OutputDecodedPictures() method to upper class RocVideoParser.

* * rocDecode: Code cleanup. No functional changes.

* * rocDecode: Made decode buffer pool size adaptive.
 - Removed the hard coded decode buffer pool size set in the decoder.
 - Exposed the display delay parameter from RocVideoDecoder class to the user.
 - Now the decoder buffer pool size is determined from the DPB buffer size and display delay parameter.

* * rocDecode: Several changes based on code review.
 - Merged decode and display use status into one parameter.
 - Removed the surface index from DecodeFrameBuffer, which is now implicitly referred by the array index.
 - Changed a function name for better clarity.

* * rocDecode: Added a comment.

[ROCm/rocdecode commit: 61c8661b9c]
This commit is contained in:
jeffqjiangNew
2024-05-31 13:14:02 -04:00
committed by GitHub
parent 4a6e9d709b
commit 3230cca447
11 changed files with 418 additions and 179 deletions
@@ -32,6 +32,7 @@ make -j
-d <GPU device ID - 0:device 0 / 1:device 1/ ... [optional - default:0]>
-f <Number of decoded frames - specify the number of pictures to be decoded [optional]>
-z <force_zero_latency - Decoded frames will be flushed out for display immediately [optional]>
-disp_delay <display delay - specify the number of frames to be delayed for display [optional]>
-sei <extract SEI messages [optional]>
-md5 <generate MD5 message digest on the decoded YUV image sequence [optional]>
-md5_check MD5_File_Path <generate MD5 message digest on the decoded YUV image sequence and compare to the reference MD5 string in a file [optional]>
@@ -47,6 +47,7 @@ void ShowHelpAndExit(const char *option = NULL) {
<< "-d GPU device ID (0 for the first device, 1 for the second, etc.); optional; default: 0" << std::endl
<< "-f Number of decoded frames - specify the number of pictures to be decoded; optional" << std::endl
<< "-z force_zero_latency (force_zero_latency, Decoded frames will be flushed out for display immediately); optional;" << std::endl
<< "-disp_delay -specify the number of frames to be delayed for display; optional;" << std::endl
<< "-sei extract SEI messages; optional;" << std::endl
<< "-md5 generate MD5 message digest on the decoded YUV image sequence; optional;" << std::endl
<< "-md5_check MD5 File Path - generate MD5 message digest on the decoded YUV image sequence and compare to the reference MD5 string in a file; optional;" << std::endl
@@ -66,6 +67,7 @@ int main(int argc, char **argv) {
std::fstream ref_md5_file;
int dump_output_frames = 0;
int device_id = 0;
int disp_delay = 0;
bool b_force_zero_latency = false; // false by default: enabling this option might affect decoding performance
bool b_extract_sei_messages = false;
bool b_generate_md5 = false;
@@ -111,6 +113,13 @@ int main(int argc, char **argv) {
device_id = atoi(argv[i]);
continue;
}
if (!strcmp(argv[i], "-disp_delay")) {
if (++i == argc) {
ShowHelpAndExit("-disp_delay");
}
disp_delay = atoi(argv[i]);
continue;
}
if (!strcmp(argv[i], "-f")) {
if (++i == argc) {
ShowHelpAndExit("-d");
@@ -197,7 +206,7 @@ int main(int argc, char **argv) {
VideoDemuxer demuxer(input_file_path.c_str());
VideoSeekContext video_seek_ctx;
rocDecVideoCodec rocdec_codec_id = AVCodec2RocDecVideoCodec(demuxer.GetCodecID());
RocVideoDecoder viddec(device_id, mem_type, rocdec_codec_id, b_force_zero_latency, p_crop_rect, b_extract_sei_messages);
RocVideoDecoder viddec(device_id, mem_type, rocdec_codec_id, b_force_zero_latency, p_crop_rect, b_extract_sei_messages, disp_delay);
std::string device_name, gcn_arch_name;
int pci_bus_id, pci_domain_id, pci_device_id;
+1 -1
View File
@@ -33,7 +33,7 @@ THE SOFTWARE.
#define AVC_MAX_REF_FRAME_NUM 16
#define AVC_MAX_REF_PICTURE_NUM 32
#define AVC_MAX_DPB_FRAMES 18
#define AVC_MAX_DPB_FRAMES 16
#define AVC_MAX_DPB_FIELDS AVC_MAX_DPB_FRAMES * 2
#define AVC_MACRO_BLOCK_SIZE 16
+117 -71
View File
@@ -24,6 +24,9 @@ THE SOFTWARE.
#include "avc_parser.h"
AvcVideoParser::AvcVideoParser() {
active_sps_id_ = -1;
active_pps_id_ = -1;
prev_pic_order_cnt_msb_ = 0;
prev_pic_order_cnt_lsb_ = 0;
prev_top_field_order_cnt_ = 0;
@@ -42,6 +45,7 @@ AvcVideoParser::AvcVideoParser() {
field_pic_count_ = 0;
second_field_ = 0;
first_field_pic_idx_ = 0;
first_field_dec_buf_idx_ = 0;
InitDpb();
}
@@ -59,9 +63,6 @@ rocDecStatus AvcVideoParser::UnInitialize() {
rocDecStatus AvcVideoParser::ParseVideoData(RocdecSourceDataPacket *p_data) {
if (p_data->payload && p_data->payload_size) {
// Clear DPB output/display buffer number
dpb_buffer_.num_output_pics = 0;
if (ParsePictureData(p_data->payload, p_data->payload_size) != PARSER_OK) {
ERR(STR("Parser failed!"));
return ROCDEC_RUNTIME_ERROR;
@@ -86,8 +87,8 @@ rocDecStatus AvcVideoParser::ParseVideoData(RocdecSourceDataPacket *p_data) {
}
// Output decoded pictures from DPB if any are ready in case of frame_num gaps.
if (pfn_display_picture_cb_ && dpb_buffer_.num_output_pics > 0) {
if (OutputDecodedPictures() != PARSER_OK) {
if (pfn_display_picture_cb_ && num_output_pics_ > 0) {
if (OutputDecodedPictures(false) != PARSER_OK) {
return ROCDEC_RUNTIME_ERROR;
}
}
@@ -237,9 +238,9 @@ ParserResult AvcVideoParser::ParsePictureData(const uint8_t *p_stream, uint32_t
}
if (num_slices_ == 0) {
// Find a free buffer in DPB for the current picture. Due to the current 1-1 mapping of DPB and
// decoded buffer pool at VAAP level, we need to get a surface from DPB for the current picture to be
// decoded into.
if ((ret2 = FindFreeInDecBufPool()) != PARSER_OK) {
return ret2;
}
if ((ret2 = FindFreeBufInDpb()) != PARSER_OK) {
return ret2;
}
@@ -299,7 +300,7 @@ ParserResult AvcVideoParser::NotifyNewSps(AvcSeqParameterSet *p_sps) {
video_format_params_.bit_depth_luma_minus8 = p_sps->bit_depth_luma_minus8;
video_format_params_.bit_depth_chroma_minus8 = p_sps->bit_depth_chroma_minus8;
video_format_params_.progressive_sequence = p_sps->frame_mbs_only_flag ? 1 : 0;
video_format_params_.min_num_decode_surfaces = dpb_buffer_.dpb_size;
video_format_params_.min_num_decode_surfaces = dec_buf_pool_size_;
video_format_params_.coded_width = pic_width_;
video_format_params_.coded_height = pic_height_;
video_format_params_.chroma_format = static_cast<rocDecVideoChromaFormat>(p_sps->chroma_format_idc);
@@ -408,7 +409,7 @@ void AvcVideoParser::SendSeiMsgPayload() {
sei_message_info_params_.sei_message_count = sei_message_count_;
sei_message_info_params_.sei_message = sei_message_list_.data();
sei_message_info_params_.sei_data = (void*)sei_payload_buf_;
sei_message_info_params_.picIdx = curr_pic_.pic_idx;
sei_message_info_params_.picIdx = curr_pic_.dec_buf_idx;
// callback function with RocdecSeiMessageInfo params filled out
if (pfn_get_sei_message_cb_) pfn_get_sei_message_cb_(parser_params_.user_data, &sei_message_info_params_);
@@ -441,7 +442,7 @@ ParserResult AvcVideoParser::SendPicForDecode() {
dec_pic_params_.pic_width = pic_width_;
dec_pic_params_.pic_height = pic_height_;
dec_pic_params_.curr_pic_idx = curr_pic_.pic_idx;
dec_pic_params_.curr_pic_idx = curr_pic_.dec_buf_idx;
dec_pic_params_.field_pic_flag = p_slice_header->field_pic_flag;
dec_pic_params_.bottom_field_flag = p_slice_header->bottom_field_flag;
dec_pic_params_.second_field = second_field_;
@@ -457,7 +458,7 @@ ParserResult AvcVideoParser::SendPicForDecode() {
RocdecAvcPicParams *p_pic_param = &dec_pic_params_.pic_params.avc;
// Current picture
p_pic_param->curr_pic.pic_idx = curr_pic_.pic_idx;
p_pic_param->curr_pic.pic_idx = curr_pic_.dec_buf_idx;
if (curr_pic_.is_reference == kUsedForLongTerm) {
p_pic_param->curr_pic.frame_idx = curr_pic_.long_term_pic_num;
} else {
@@ -479,7 +480,7 @@ ParserResult AvcVideoParser::SendPicForDecode() {
if (p_slice_header->field_pic_flag == 0) { // frame picture
AvcPicture *p_ref_pic = &dpb_buffer_.frame_buffer_list[i];
if (p_ref_pic->is_reference != kUnusedForReference) {
p_pic_param->ref_frames[buf_index].pic_idx = p_ref_pic->pic_idx;
p_pic_param->ref_frames[buf_index].pic_idx = p_ref_pic->dec_buf_idx;
if ( p_ref_pic->is_reference == kUsedForLongTerm) {
p_pic_param->ref_frames[buf_index].frame_idx = p_ref_pic->long_term_pic_num;
} else {
@@ -500,7 +501,7 @@ ParserResult AvcVideoParser::SendPicForDecode() {
for (int j = 0; j < 2; j++) {
AvcPicture *p_field_pic = &dpb_buffer_.field_pic_list[i * 2 + j];
if (p_field_pic->is_reference != kUnusedForReference) {
p_ref_frame->pic_idx = p_field_pic->pic_idx;
p_ref_frame->pic_idx = p_field_pic->dec_buf_idx;
if (p_field_pic->is_reference == kUsedForLongTerm) {
p_ref_frame->frame_idx = p_field_pic->long_term_frame_idx;
} else {
@@ -611,7 +612,7 @@ ParserResult AvcVideoParser::SendPicForDecode() {
for (i = 0; i <= p_slice_info->slice_header.num_ref_idx_l0_active_minus1; i++) {
AvcPicture *p_ref_pic = &p_slice_info->ref_list_0_[i];
if (p_ref_pic->is_reference != kUnusedForReference) {
p_slice_param->ref_pic_list_0[i].pic_idx = p_ref_pic->pic_idx;
p_slice_param->ref_pic_list_0[i].pic_idx = p_ref_pic->dec_buf_idx;
if ( p_ref_pic->is_reference == kUsedForLongTerm) {
p_slice_param->ref_pic_list_0[i].frame_idx = p_ref_pic->long_term_pic_num;
} else {
@@ -632,7 +633,7 @@ ParserResult AvcVideoParser::SendPicForDecode() {
for (i = 0; i <= p_slice_info->slice_header.num_ref_idx_l1_active_minus1; i++) {
AvcPicture *p_ref_pic = &p_slice_info->ref_list_1_[i];
if (p_ref_pic->is_reference != kUnusedForReference) {
p_slice_param->ref_pic_list_1[i].pic_idx = p_ref_pic->pic_idx;
p_slice_param->ref_pic_list_1[i].pic_idx = p_ref_pic->dec_buf_idx;
if ( p_ref_pic->is_reference == kUsedForLongTerm) {
p_slice_param->ref_pic_list_1[i].frame_idx = p_ref_pic->long_term_pic_num;
} else {
@@ -709,20 +710,6 @@ ParserResult AvcVideoParser::SendPicForDecode() {
}
}
ParserResult AvcVideoParser::OutputDecodedPictures() {
RocdecParserDispInfo disp_info = {0};
disp_info.progressive_frame = sps_list_[active_sps_id_].frame_mbs_only_flag;
disp_info.top_field_first = slice_info_list_[0].slice_header.bottom_field_flag && (pic_count_ & 1);
for (int i = 0; i < dpb_buffer_.num_output_pics; i++) {
disp_info.picture_index = dpb_buffer_.frame_buffer_list[dpb_buffer_.output_pic_list[i]].pic_idx;
pfn_display_picture_cb_(parser_params_.user_data, &disp_info);
}
dpb_buffer_.num_output_pics = 0;
return PARSER_OK;
}
AvcNalUnitHeader AvcVideoParser::ParseNalUnitHeader(uint8_t header_byte) {
size_t bit_offset = 0;
AvcNalUnitHeader nal_header;
@@ -1192,7 +1179,7 @@ ParserResult AvcVideoParser::ParseSliceHeader(uint8_t *p_stream, size_t stream_s
return PARSER_WRONG_STATE;
}
// Re-set DPB size.
dpb_buffer_.dpb_size = p_sps->max_num_ref_frames + 3;
dpb_buffer_.dpb_size = p_sps->max_num_ref_frames + 1;
dpb_buffer_.dpb_size = dpb_buffer_.dpb_size > AVC_MAX_DPB_FRAMES ? AVC_MAX_DPB_FRAMES : dpb_buffer_.dpb_size;
new_sps_activated_ = true; // Note: clear this flag after the actions are taken.
}
@@ -1206,11 +1193,16 @@ ParserResult AvcVideoParser::ParseSliceHeader(uint8_t *p_stream, size_t stream_s
pic_height_ = curr_pic_height;
// Take care of the case where a new SPS replaces the old SPS with the same id but with different dimensions
// Re-set DPB size.
dpb_buffer_.dpb_size = p_sps->max_num_ref_frames + 3;
dpb_buffer_.dpb_size = p_sps->max_num_ref_frames + 1;
dpb_buffer_.dpb_size = dpb_buffer_.dpb_size > AVC_MAX_DPB_FRAMES ? AVC_MAX_DPB_FRAMES : dpb_buffer_.dpb_size;
new_sps_activated_ = true; // Note: clear this flag after the actions are taken.
}
// Check and adjust decode buffer pool size if needed
if (new_sps_activated_) {
CheckAndAdjustDecBufPoolSize(dpb_buffer_.dpb_size);
}
// Set frame rate if available
if (new_sps_activated_) {
if (p_sps->vui_seq_parameters.timing_info_present_flag) {
@@ -1626,14 +1618,14 @@ void AvcVideoParser::InitDpb() {
for (int i = 0; i < AVC_MAX_DPB_FRAMES; i++) {
dpb_buffer_.frame_buffer_list[i].pic_idx = i;
dpb_buffer_.frame_buffer_list[i].is_reference = kUnusedForReference;
dpb_buffer_.frame_buffer_list[i].use_status = 0;
dpb_buffer_.frame_buffer_list[i].use_status = kNotUsed;
dpb_buffer_.frame_buffer_list[i].pic_output_flag = 0;
dpb_buffer_.field_pic_list[i * 2].pic_idx = i;
dpb_buffer_.field_pic_list[i * 2 + 1].pic_idx = i;
dpb_buffer_.field_pic_list[i * 2].is_reference = kUnusedForReference;
dpb_buffer_.field_pic_list[i * 2 + 1].is_reference = kUnusedForReference;
dpb_buffer_.field_pic_list[i * 2].use_status = 0;
dpb_buffer_.field_pic_list[i * 2 + 1].use_status = 0;
dpb_buffer_.field_pic_list[i * 2].use_status = kNotUsed;
dpb_buffer_.field_pic_list[i * 2 + 1].use_status = kNotUsed;
dpb_buffer_.field_pic_list[i * 2].pic_output_flag = 0;
dpb_buffer_.field_pic_list[i * 2 + 1].pic_output_flag = 0;
}
@@ -1644,7 +1636,6 @@ void AvcVideoParser::InitDpb() {
dpb_buffer_.num_short_term_ref_fields = 0;
dpb_buffer_.num_long_term_ref_fields = 0;
dpb_buffer_.num_pics_needed_for_output = 0;
dpb_buffer_.num_output_pics = 0;
}
// 8.2.1 Decoding process for picture order count
@@ -1962,13 +1953,13 @@ ParserResult AvcVideoParser::DecodeFrameNumGaps() {
}
for (i = 0; i < dpb_buffer_.dpb_size; i++) {
if (dpb_buffer_.frame_buffer_list[i].use_status == 0) {
if (dpb_buffer_.frame_buffer_list[i].use_status == kNotUsed) {
break;
}
}
if (i < dpb_buffer_.dpb_size) {
non_existing_pic.pic_idx = dpb_buffer_.frame_buffer_list[i].pic_idx;
non_existing_pic.use_status = 3;
non_existing_pic.use_status = kFrameUsedForDecode;
dpb_buffer_.frame_buffer_list[i] = non_existing_pic;
dpb_buffer_.dpb_fullness++;
dpb_buffer_.num_short_term++;
@@ -2566,14 +2557,40 @@ ParserResult AvcVideoParser::CheckDpbAndOutput() {
}
}
// Output decoded pictures from DPB if any are ready
if (pfn_display_picture_cb_ && dpb_buffer_.num_output_pics > 0) {
if (OutputDecodedPictures() != PARSER_OK) {
if (pfn_display_picture_cb_ && num_output_pics_ > 0) {
if (OutputDecodedPictures(false) != PARSER_OK) {
return PARSER_FAIL;
}
}
return PARSER_OK;
}
ParserResult AvcVideoParser::FindFreeInDecBufPool() {
int dec_buf_index;
if (curr_pic_.pic_structure == kFrame || !second_field_) {
// Find a free buffer in decode buffer pool
for (dec_buf_index = 0; dec_buf_index < dec_buf_pool_size_; dec_buf_index++) {
if (decode_buffer_pool_[dec_buf_index].use_status == kNotUsed) {
break;
}
}
if (dec_buf_index == dec_buf_pool_size_) {
ERR("Could not find a free buffer in decode buffer pool.");
return PARSER_NOT_FOUND;
}
curr_pic_.dec_buf_idx = dec_buf_index;
if ( curr_pic_.pic_structure != kFrame) {
first_field_dec_buf_idx_ = dec_buf_index;
}
} else {
curr_pic_.dec_buf_idx = first_field_dec_buf_idx_;
}
return PARSER_OK;
}
ParserResult AvcVideoParser::FindFreeBufInDpb() {
int i;
if (curr_pic_.pic_structure == kFrame || !second_field_) {
@@ -2584,18 +2601,18 @@ ParserResult AvcVideoParser::FindFreeBufInDpb() {
}
for (i = 0; i < dpb_buffer_.dpb_size; i++) {
if (dpb_buffer_.frame_buffer_list[i].use_status == 0) {
if (dpb_buffer_.frame_buffer_list[i].use_status == kNotUsed) {
break;
}
}
if (i < dpb_buffer_.dpb_size) {
curr_pic_.pic_idx = dpb_buffer_.frame_buffer_list[i].pic_idx;
if (curr_pic_.pic_structure == kFrame) {
curr_pic_.use_status = 3;
curr_pic_.use_status = kFrameUsedForDecode;
} else if (curr_pic_.pic_structure == kTopField) {
curr_pic_.use_status = 1;
curr_pic_.use_status = kTopFieldUsedForDecode;
} else {
curr_pic_.use_status = 2;
curr_pic_.use_status = kBottomFieldUsedForDecode;
}
} else {
ERR("Could not find any free frame buffer in DPB.");
@@ -2608,9 +2625,9 @@ ParserResult AvcVideoParser::FindFreeBufInDpb() {
} else {
curr_pic_.pic_idx = first_field_pic_idx_;
if (curr_pic_.pic_structure == kTopField) {
curr_pic_.use_status = 1;
curr_pic_.use_status = kTopFieldUsedForDecode;
} else {
curr_pic_.use_status = 2;
curr_pic_.use_status = kBottomFieldUsedForDecode;
}
}
@@ -2982,12 +2999,14 @@ ParserResult AvcVideoParser::BumpPicFromDpb() {
if (dpb_buffer_.num_pics_needed_for_output > 0) {
dpb_buffer_.num_pics_needed_for_output--;
// Insert into output/display picture list
if (dpb_buffer_.num_output_pics >= AVC_MAX_DPB_FRAMES) {
ERR("Error! DPB output buffer list overflow!");
return PARSER_OUT_OF_RANGE;
} else {
dpb_buffer_.output_pic_list[dpb_buffer_.num_output_pics] = min_poc_pic_idx_ref;
dpb_buffer_.num_output_pics++;
if (pfn_display_picture_cb_) {
if (num_output_pics_ >= dec_buf_pool_size_) {
ERR("Error! Decode buffer pool overflow!");
return PARSER_OUT_OF_RANGE;
} else {
output_pic_list_[num_output_pics_] = dpb_buffer_.frame_buffer_list[min_poc_pic_idx_ref].dec_buf_idx;
num_output_pics_++;
}
}
}
min_poc_ref = 0x7FFFFFFF;
@@ -3008,16 +3027,19 @@ ParserResult AvcVideoParser::BumpPicFromDpb() {
}
// Insert into output/display picture list
if (dpb_buffer_.num_output_pics >= AVC_MAX_DPB_FRAMES) {
ERR("Error! DPB output buffer list overflow!");
return PARSER_OUT_OF_RANGE;
} else {
dpb_buffer_.output_pic_list[dpb_buffer_.num_output_pics] = min_poc_pic_idx_no_ref;
dpb_buffer_.num_output_pics++;
if (pfn_display_picture_cb_) {
if (num_output_pics_ >= dec_buf_pool_size_) {
ERR("Error! Decode buffer pool overflow!");
return PARSER_OUT_OF_RANGE;
} else {
output_pic_list_[num_output_pics_] = dpb_buffer_.frame_buffer_list[min_poc_pic_idx_no_ref].dec_buf_idx;
num_output_pics_++;
}
}
}
// Remove it from DPB.
dpb_buffer_.frame_buffer_list[min_poc_pic_idx_no_ref].use_status = 0;
// Remove it from DPB and mark unused for decode in decode buffer pool
dpb_buffer_.frame_buffer_list[min_poc_pic_idx_no_ref].use_status = kNotUsed;
decode_buffer_pool_[dpb_buffer_.frame_buffer_list[min_poc_pic_idx_no_ref].dec_buf_idx].use_status &= ~kFrameUsedForDecode;
if (dpb_buffer_.dpb_fullness > 0 ) {
dpb_buffer_.dpb_fullness--;
}
@@ -3069,7 +3091,7 @@ ParserResult AvcVideoParser::InsertCurrPicIntoDpb() {
}
dpb_buffer_.frame_buffer_list[i].pic_order_cnt = dpb_buffer_.frame_buffer_list[i].top_field_order_cnt <= dpb_buffer_.frame_buffer_list[i].bottom_field_order_cnt ? dpb_buffer_.frame_buffer_list[i].top_field_order_cnt : dpb_buffer_.frame_buffer_list[i].bottom_field_order_cnt;
dpb_buffer_.frame_buffer_list[i].pic_output_flag = curr_pic_.pic_output_flag;
dpb_buffer_.frame_buffer_list[i].use_status = 3;
dpb_buffer_.frame_buffer_list[i].use_status = kFrameUsedForDecode;
if (dpb_buffer_.frame_buffer_list[i].pic_output_flag) {
dpb_buffer_.num_pics_needed_for_output++;
}
@@ -3081,6 +3103,13 @@ ParserResult AvcVideoParser::InsertCurrPicIntoDpb() {
}
}
}
// Mark as used in decode buffer pool
decode_buffer_pool_[curr_pic_.dec_buf_idx].use_status |= kFrameUsedForDecode;
if (pfn_display_picture_cb_ && curr_pic_.pic_output_flag) {
decode_buffer_pool_[curr_pic_.dec_buf_idx].use_status |= kFrameUsedForDisplay;
}
decode_buffer_pool_[curr_pic_.dec_buf_idx].pic_order_cnt = curr_pic_.pic_order_cnt;
} else {
ERR("Could not find the reserved frame buffer for the current picture in DPB.");
return PARSER_FAIL;
@@ -3097,6 +3126,8 @@ ParserResult AvcVideoParser::FlushDpb() {
// Mark all reference pictures as "unused for reference
for (int i = 0; i < AVC_MAX_DPB_FRAMES; i++) {
dpb_buffer_.frame_buffer_list[i].is_reference = kUnusedForReference;
dpb_buffer_.field_pic_list[i * 2].is_reference = kUnusedForReference;
dpb_buffer_.field_pic_list[i * 2 + 1].is_reference = kUnusedForReference;
}
// Bump the remaining pictures
while (dpb_buffer_.num_pics_needed_for_output) {
@@ -3104,12 +3135,20 @@ ParserResult AvcVideoParser::FlushDpb() {
return PARSER_FAIL;
}
}
if (pfn_display_picture_cb_ && dpb_buffer_.num_output_pics > 0) {
if (OutputDecodedPictures() != PARSER_OK) {
return PARSER_FAIL;
}
}
if (pfn_display_picture_cb_ && num_output_pics_ > 0) {
if (OutputDecodedPictures(true) != PARSER_OK) {
return PARSER_FAIL;
}
}
// Empty DPB
for (int i = 0; i < AVC_MAX_DPB_FRAMES; i++) {
dpb_buffer_.frame_buffer_list[i].use_status = kNotUsed;
dpb_buffer_.field_pic_list[i * 2].use_status = kNotUsed;
dpb_buffer_.field_pic_list[i * 2 + 1].use_status = kNotUsed;
decode_buffer_pool_[dpb_buffer_.frame_buffer_list[i].dec_buf_idx].use_status = kNotUsed;
}
return PARSER_OK;
}
@@ -3340,11 +3379,10 @@ void AvcVideoParser::PrintDpb() {
MSG("second_field_ = " << second_field_);
MSG("num_pics_needed_for_output = " << dpb_buffer_.num_pics_needed_for_output);
MSG("dpb_fullness = " << dpb_buffer_.dpb_fullness);
MSG("num_output_pics = " << dpb_buffer_.num_output_pics);
MSG("Frame buffer store:");
for (i = 0; i < AVC_MAX_DPB_FRAMES; i++) {
AvcPicture *p_buf = &dpb_buffer_.frame_buffer_list[i];
MSG("Frame buffer " << i << ": pic_idx = " << p_buf->pic_idx << ", pic_structure = " << p_buf->pic_structure << ", pic_order_cnt = " << p_buf->pic_order_cnt << ", top_field_order_cnt = " << p_buf->top_field_order_cnt << ", bottom_field_order_cnt = " << p_buf->bottom_field_order_cnt << ", frame_num = " << p_buf->frame_num << ", frame_num_wrap = " << p_buf->frame_num_wrap << ", pic_num = " << p_buf->pic_num << ", long_term_pic_num = " << p_buf->long_term_pic_num << ", long_term_frame_idx = " << p_buf->long_term_frame_idx << ", is_reference = " << p_buf->is_reference << ", use_status = " << p_buf->use_status << ", pic_output_flag = " << p_buf->pic_output_flag);
MSG("Frame buffer " << i << ": pic_idx = " << p_buf->pic_idx << ", dec_buf_idx = " << p_buf->dec_buf_idx << ", pic_structure = " << p_buf->pic_structure << ", pic_order_cnt = " << p_buf->pic_order_cnt << ", top_field_order_cnt = " << p_buf->top_field_order_cnt << ", bottom_field_order_cnt = " << p_buf->bottom_field_order_cnt << ", frame_num = " << p_buf->frame_num << ", frame_num_wrap = " << p_buf->frame_num_wrap << ", pic_num = " << p_buf->pic_num << ", long_term_pic_num = " << p_buf->long_term_pic_num << ", long_term_frame_idx = " << p_buf->long_term_frame_idx << ", is_reference = " << p_buf->is_reference << ", use_status = " << p_buf->use_status << ", pic_output_flag = " << p_buf->pic_output_flag);
}
MSG("");
MSG("Field picture store:");
@@ -3353,12 +3391,20 @@ void AvcVideoParser::PrintDpb() {
MSG("Field picture " << i << ": pic_idx = " << p_buf->pic_idx << ", pic_structure = " << p_buf->pic_structure << ", pic_order_cnt = " << p_buf->pic_order_cnt << ", top_field_order_cnt = " << p_buf->top_field_order_cnt << ", bottom_field_order_cnt = " << p_buf->bottom_field_order_cnt << ", frame_num = " << p_buf->frame_num << ", frame_num_wrap = " << p_buf->frame_num_wrap << ", pic_num = " << p_buf->pic_num << ", long_term_pic_num = " << p_buf->long_term_pic_num << ", long_term_frame_idx = " << p_buf->long_term_frame_idx << ", is_reference = " << p_buf->is_reference << ", use_status = " << p_buf->use_status << ", pic_output_flag = " << p_buf->pic_output_flag);
}
MSG("");
if (dpb_buffer_.num_output_pics) {
MSG("Decode buffer pool:");
for(i = 0; i < dec_buf_pool_size_; i++) {
DecodeFrameBuffer *p_dec_buf = &decode_buffer_pool_[i];
MSG("Decode buffer " << i << ": use_status = " << p_dec_buf->use_status << ", pic_order_cnt = " << p_dec_buf->pic_order_cnt);
}
MSG("num_output_pics_ = " << num_output_pics_);
if (num_output_pics_) {
MSG("output_pic_list:");
for (i = 0; i < dpb_buffer_.num_output_pics; i++) {
MSG_NO_NEWLINE(dpb_buffer_.output_pic_list[i] << ", ");
for (i = 0; i < num_output_pics_; i++) {
MSG_NO_NEWLINE(output_pic_list_[i] << ", ");
}
MSG("");
MSG("");
}
}
+8 -6
View File
@@ -60,6 +60,7 @@ public:
typedef struct {
int pic_idx; // picture index or id
int dec_buf_idx; // frame index in decode buffer pool
PictureStructure pic_structure;
int32_t pic_order_cnt;
int32_t top_field_order_cnt;
@@ -70,7 +71,7 @@ public:
int32_t long_term_pic_num; // LongTermPicNum
uint32_t long_term_frame_idx; // LongTermFrameIdx: long term reference frame/field identifier
uint32_t is_reference;
uint32_t use_status; // 0 = empty; 1 = top used; 2 = bottom used; 3 = both fields or frame used
uint32_t use_status; // refer to FrameBufUseStatus
uint32_t pic_output_flag; // OutputFlag
} AvcPicture;
@@ -134,6 +135,7 @@ protected:
uint32_t field_pic_count_;
int second_field_;
int first_field_pic_idx_;
int first_field_dec_buf_idx_;
// DPB
AvcPicture curr_pic_;
@@ -150,11 +152,6 @@ protected:
*/
ParserResult SendPicForDecode();
/*! \brief Function to output decoded pictures from DPB for post-processing.
* \return Return code in ParserResult form
*/
ParserResult OutputDecodedPictures();
/*! \brief Callback function to send parsed SEI playload to decoder.
*/
void SendSeiMsgPayload();
@@ -263,6 +260,11 @@ protected:
*/
ParserResult CheckDpbAndOutput();
/*! \brief Function to find a free buffer in the decode buffer pool
* \return <tt>ParserResult</tt>
*/
ParserResult FindFreeInDecBufPool();
/*! \brief Function to find a free buffer in DPB for the current picture
* \return <tt>ParserResult</tt>
*/
+171 -80
View File
@@ -78,9 +78,6 @@ rocDecStatus HevcVideoParser::UnInitialize() {
rocDecStatus HevcVideoParser::ParseVideoData(RocdecSourceDataPacket *p_data) {
if (p_data->payload && p_data->payload_size) {
// Clear DPB output/display buffer number
dpb_buffer_.num_output_pics = 0;
if (ParsePictureData(p_data->payload, p_data->payload_size) != PARSER_OK) {
ERR(STR("Parser failed!"));
return ROCDEC_RUNTIME_ERROR;
@@ -111,8 +108,8 @@ rocDecStatus HevcVideoParser::ParseVideoData(RocdecSourceDataPacket *p_data) {
}
// Output decoded pictures from DPB if any are ready
if (pfn_display_picture_cb_ && dpb_buffer_.num_output_pics > 0) {
if (OutputDecodedPictures() != PARSER_OK) {
if (pfn_display_picture_cb_ && num_output_pics_ > 0) {
if (OutputDecodedPictures(false) != PARSER_OK) {
return ROCDEC_RUNTIME_ERROR;
}
}
@@ -144,7 +141,7 @@ int HevcVideoParser::FillSeqCallbackFn(HevcSeqParamSet* sps_data) {
video_format_params_.progressive_sequence = 0;
else // default value
video_format_params_.progressive_sequence = 1;
video_format_params_.min_num_decode_surfaces = dpb_buffer_.dpb_size;
video_format_params_.min_num_decode_surfaces = dec_buf_pool_size_;
video_format_params_.coded_width = sps_data->pic_width_in_luma_samples;
video_format_params_.coded_height = sps_data->pic_height_in_luma_samples;
video_format_params_.chroma_format = static_cast<rocDecVideoChromaFormat>(sps_data->chroma_format_idc);
@@ -237,7 +234,7 @@ void HevcVideoParser::SendSeiMsgPayload() {
sei_message_info_params_.sei_message_count = sei_message_count_;
sei_message_info_params_.sei_message = sei_message_list_.data();
sei_message_info_params_.sei_data = (void*)sei_payload_buf_;
sei_message_info_params_.picIdx = curr_pic_info_.pic_idx;
sei_message_info_params_.picIdx = curr_pic_info_.dec_buf_idx;
// callback function with RocdecSeiMessageInfo params filled out
if (pfn_get_sei_message_cb_) pfn_get_sei_message_cb_(parser_params_.user_data, &sei_message_info_params_);
@@ -251,7 +248,7 @@ int HevcVideoParser::SendPicForDecode() {
dec_pic_params_.pic_width = sps_ptr->pic_width_in_luma_samples;
dec_pic_params_.pic_height = sps_ptr->pic_height_in_luma_samples;
dec_pic_params_.curr_pic_idx = curr_pic_info_.pic_idx;
dec_pic_params_.curr_pic_idx = curr_pic_info_.dec_buf_idx;
dec_pic_params_.field_pic_flag = sps_ptr->profile_tier_level.general_interlaced_source_flag;
dec_pic_params_.bottom_field_flag = 0; // For now. Need to parse VUI/SEI pic_timing()
dec_pic_params_.second_field = 0; // For now. Need to parse VUI/SEI pic_timing()
@@ -270,14 +267,14 @@ int HevcVideoParser::SendPicForDecode() {
RocdecHevcPicParams *pic_param_ptr = &dec_pic_params_.pic_params.hevc;
// Current picture
pic_param_ptr->curr_pic.pic_idx = curr_pic_info_.pic_idx;
pic_param_ptr->curr_pic.pic_idx = curr_pic_info_.dec_buf_idx;
pic_param_ptr->curr_pic.poc = curr_pic_info_.pic_order_cnt;
// Reference pictures
ref_idx = 0;
for (i = 0; i < num_poc_st_curr_before_; i++) {
buf_idx = ref_pic_set_st_curr_before_[i]; // buffer index in DPB
pic_param_ptr->ref_frames[ref_idx].pic_idx = dpb_buffer_.frame_buffer_list[buf_idx].pic_idx;
pic_param_ptr->ref_frames[ref_idx].pic_idx = dpb_buffer_.frame_buffer_list[buf_idx].dec_buf_idx;
pic_param_ptr->ref_frames[ref_idx].poc = dpb_buffer_.frame_buffer_list[buf_idx].pic_order_cnt;
pic_param_ptr->ref_frames[ref_idx].flags = 0; // assume frame picture for now
pic_param_ptr->ref_frames[ref_idx].flags |= RocdecHevcPicture_RPS_ST_CURR_BEFORE;
@@ -286,7 +283,7 @@ int HevcVideoParser::SendPicForDecode() {
for (i = 0; i < num_poc_st_curr_after_; i++) {
buf_idx = ref_pic_set_st_curr_after_[i]; // buffer index in DPB
pic_param_ptr->ref_frames[ref_idx].pic_idx = dpb_buffer_.frame_buffer_list[buf_idx].pic_idx;
pic_param_ptr->ref_frames[ref_idx].pic_idx = dpb_buffer_.frame_buffer_list[buf_idx].dec_buf_idx;
pic_param_ptr->ref_frames[ref_idx].poc = dpb_buffer_.frame_buffer_list[buf_idx].pic_order_cnt;
pic_param_ptr->ref_frames[ref_idx].flags = 0; // assume frame picture for now
pic_param_ptr->ref_frames[ref_idx].flags |= RocdecHevcPicture_RPS_ST_CURR_AFTER;
@@ -295,7 +292,7 @@ int HevcVideoParser::SendPicForDecode() {
for (i = 0; i < num_poc_lt_curr_; i++) {
buf_idx = ref_pic_set_lt_curr_[i]; // buffer index in DPB
pic_param_ptr->ref_frames[ref_idx].pic_idx = dpb_buffer_.frame_buffer_list[buf_idx].pic_idx;
pic_param_ptr->ref_frames[ref_idx].pic_idx = dpb_buffer_.frame_buffer_list[buf_idx].dec_buf_idx;
pic_param_ptr->ref_frames[ref_idx].poc = dpb_buffer_.frame_buffer_list[buf_idx].pic_order_cnt;
pic_param_ptr->ref_frames[ref_idx].flags = 0; // assume frame picture for now
pic_param_ptr->ref_frames[ref_idx].flags |= RocdecHevcPicture_LONG_TERM_REFERENCE | RocdecHevcPicture_RPS_LT_CURR;
@@ -304,7 +301,7 @@ int HevcVideoParser::SendPicForDecode() {
for (i = 0; i < num_poc_st_foll_; i++) {
buf_idx = ref_pic_set_st_foll_[i]; // buffer index in DPB
pic_param_ptr->ref_frames[ref_idx].pic_idx = dpb_buffer_.frame_buffer_list[buf_idx].pic_idx;
pic_param_ptr->ref_frames[ref_idx].pic_idx = dpb_buffer_.frame_buffer_list[buf_idx].dec_buf_idx;
pic_param_ptr->ref_frames[ref_idx].poc = dpb_buffer_.frame_buffer_list[buf_idx].pic_order_cnt;
pic_param_ptr->ref_frames[ref_idx].flags = 0; // assume frame picture for now
ref_idx++;
@@ -312,7 +309,7 @@ int HevcVideoParser::SendPicForDecode() {
for (i = 0; i < num_poc_lt_foll_; i++) {
buf_idx = ref_pic_set_lt_foll_[i]; // buffer index in DPB
pic_param_ptr->ref_frames[ref_idx].pic_idx = dpb_buffer_.frame_buffer_list[buf_idx].pic_idx;
pic_param_ptr->ref_frames[ref_idx].pic_idx = dpb_buffer_.frame_buffer_list[buf_idx].dec_buf_idx;
pic_param_ptr->ref_frames[ref_idx].poc = dpb_buffer_.frame_buffer_list[buf_idx].pic_order_cnt;
pic_param_ptr->ref_frames[ref_idx].flags = 0; // assume frame picture for now
ref_idx++;
@@ -424,8 +421,9 @@ int HevcVideoParser::SendPicForDecode() {
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
int dec_buf_idx = dpb_buffer_.frame_buffer_list[idx].dec_buf_idx;
for (j = 0; j < 15; j++) {
if (pic_param_ptr->ref_frames[j].pic_idx == idx) {
if (pic_param_ptr->ref_frames[j].pic_idx == dec_buf_idx) {
break;
}
}
@@ -440,8 +438,9 @@ int HevcVideoParser::SendPicForDecode() {
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
int dec_buf_idx = dpb_buffer_.frame_buffer_list[idx].dec_buf_idx;
for (j = 0; j < 15; j++) {
if (pic_param_ptr->ref_frames[j].pic_idx == idx) {
if (pic_param_ptr->ref_frames[j].pic_idx == dec_buf_idx) {
break;
}
}
@@ -532,6 +531,10 @@ int HevcVideoParser::SendPicForDecode() {
}
}
#if DBGINFO
PrintVappiBufInfo();
#endif // DBGINFO
if (pfn_decode_picture_cb_(parser_params_.user_data, &dec_pic_params_) == 0) {
ERR("Decode error occurred.");
return PARSER_FAIL;
@@ -540,20 +543,6 @@ int HevcVideoParser::SendPicForDecode() {
}
}
int HevcVideoParser::OutputDecodedPictures() {
RocdecParserDispInfo disp_info = {0};
disp_info.progressive_frame = m_sps_[m_active_sps_id_].profile_tier_level.general_progressive_source_flag;
disp_info.top_field_first = 1;
for (int i = 0; i < dpb_buffer_.num_output_pics; i++) {
disp_info.picture_index = dpb_buffer_.frame_buffer_list[dpb_buffer_.output_pic_list[i]].pic_idx;
pfn_display_picture_cb_(parser_params_.user_data, &disp_info);
}
dpb_buffer_.num_output_pics = 0;
return PARSER_OK;
}
ParserResult HevcVideoParser::ParsePictureData(const uint8_t* p_stream, uint32_t pic_data_size) {
ParserResult ret = PARSER_OK;
ParserResult ret2;
@@ -667,6 +656,11 @@ ParserResult HevcVideoParser::ParsePictureData(const uint8_t* p_stream, uint32_t
// Get POC. 8.3.1.
CalculateCurrPoc();
// Locate a free buffer for the current picutre in decode buffer pool before output picture marking (C.5.2.2)
if (FindFreeInDecBufPool() != PARSER_OK) {
return PARSER_FAIL;
}
// Decode RPS. 8.3.2.
DecodeRps();
}
@@ -683,9 +677,13 @@ ParserResult HevcVideoParser::ParsePictureData(const uint8_t* p_stream, uint32_t
}
// C.5.2.3. Find a free buffer in DPB and mark as used. (After 8.3.2.)
if (FindFreeBufAndMark() != PARSER_OK) {
if (FindFreeInDpbAndMark() != PARSER_OK) {
return PARSER_FAIL;
}
#if DBGINFO
PrintDpb();
#endif // DBGINFO
}
num_slices_++;
break;
@@ -1552,8 +1550,8 @@ ParserResult HevcVideoParser::ParseSliceHeader(uint8_t *nalu, size_t size, HevcS
if (m_active_sps_id_ != pps_ptr->pps_seq_parameter_set_id) {
m_active_sps_id_ = pps_ptr->pps_seq_parameter_set_id;
sps_ptr = &m_sps_[m_active_sps_id_];
// Re-set DPB size. We add 2 addition buffers to avoid overwritting buffer needed for output in certain cases.
dpb_buffer_.dpb_size = sps_ptr->sps_max_dec_pic_buffering_minus1[sps_ptr->sps_max_sub_layers_minus1] + 3;
// Re-set DPB size.
dpb_buffer_.dpb_size = sps_ptr->sps_max_dec_pic_buffering_minus1[sps_ptr->sps_max_sub_layers_minus1] + 1;
dpb_buffer_.dpb_size = dpb_buffer_.dpb_size > HEVC_MAX_DPB_FRAMES ? HEVC_MAX_DPB_FRAMES : dpb_buffer_.dpb_size;
new_sps_activated_ = true; // Note: clear this flag after the actions are taken.
}
@@ -1573,12 +1571,17 @@ ParserResult HevcVideoParser::ParseSliceHeader(uint8_t *nalu, size_t size, HevcS
pic_width_ = sps_ptr->pic_width_in_luma_samples;
pic_height_ = sps_ptr->pic_height_in_luma_samples;
// Take care of the case where a new SPS replaces the old SPS with the same id but with different dimensions
// Re-set DPB size. We add 2 addition buffers to avoid overwritting buffer needed for output in certain cases.
dpb_buffer_.dpb_size = sps_ptr->sps_max_dec_pic_buffering_minus1[sps_ptr->sps_max_sub_layers_minus1] + 3;
// Re-set DPB size.
dpb_buffer_.dpb_size = sps_ptr->sps_max_dec_pic_buffering_minus1[sps_ptr->sps_max_sub_layers_minus1] + 1;
dpb_buffer_.dpb_size = dpb_buffer_.dpb_size > HEVC_MAX_DPB_FRAMES ? HEVC_MAX_DPB_FRAMES : dpb_buffer_.dpb_size;
new_sps_activated_ = true; // Note: clear this flag after the actions are taken.
}
// Check and adjust decode buffer pool size if needed
if (new_sps_activated_) {
CheckAndAdjustDecBufPoolSize(dpb_buffer_.dpb_size);
}
// Set frame rate if available
if (new_sps_activated_) {
if (m_vps_[m_active_vps_id_].vps_timing_info_present_flag) {
@@ -2130,25 +2133,23 @@ void HevcVideoParser::InitDpb() {
dpb_buffer_.frame_buffer_list[i].pic_idx = i;
dpb_buffer_.frame_buffer_list[i].is_reference = kUnusedForReference;
dpb_buffer_.frame_buffer_list[i].pic_output_flag = 0;
dpb_buffer_.frame_buffer_list[i].use_status = 0;
dpb_buffer_.output_pic_list[i] = 0xFF;
dpb_buffer_.frame_buffer_list[i].use_status = kNotUsed;
}
dpb_buffer_.dpb_size = 0;
dpb_buffer_.dpb_fullness = 0;
dpb_buffer_.num_pics_needed_for_output = 0;
dpb_buffer_.num_output_pics = 0;
}
void HevcVideoParser::EmptyDpb() {
for (int i = 0; i < HEVC_MAX_DPB_FRAMES; i++) {
dpb_buffer_.frame_buffer_list[i].is_reference = kUnusedForReference;
dpb_buffer_.frame_buffer_list[i].pic_output_flag = 0;
dpb_buffer_.frame_buffer_list[i].use_status = 0;
dpb_buffer_.output_pic_list[i] = 0xFF;
dpb_buffer_.frame_buffer_list[i].use_status = kNotUsed;
decode_buffer_pool_[dpb_buffer_.frame_buffer_list[i].dec_buf_idx].use_status = kNotUsed;
}
dpb_buffer_.dpb_fullness = 0;
dpb_buffer_.num_pics_needed_for_output = 0;
dpb_buffer_.num_output_pics = 0;
num_output_pics_ = 0;
}
int HevcVideoParser::FlushDpb() {
@@ -2159,12 +2160,13 @@ int HevcVideoParser::FlushDpb() {
return PARSER_FAIL;
}
}
if (pfn_display_picture_cb_ && dpb_buffer_.num_output_pics > 0) {
if (OutputDecodedPictures() != PARSER_OK) {
return PARSER_FAIL;
}
}
if (pfn_display_picture_cb_ && num_output_pics_ > 0) {
if (OutputDecodedPictures(true) != PARSER_OK) {
return PARSER_FAIL;
}
}
return PARSER_OK;
}
@@ -2185,11 +2187,16 @@ int HevcVideoParser::MarkOutputPictures() {
}
}
// We can still have remaining undisplayed frames due to display delay feature
if (num_output_pics_) {
OutputDecodedPictures(true);
}
EmptyDpb();
} else {
for (i = 0; i < HEVC_MAX_DPB_FRAMES; i++) {
if (dpb_buffer_.frame_buffer_list[i].is_reference == kUnusedForReference && dpb_buffer_.frame_buffer_list[i].pic_output_flag == 0 && dpb_buffer_.frame_buffer_list[i].use_status) {
dpb_buffer_.frame_buffer_list[i].use_status = 0;
dpb_buffer_.frame_buffer_list[i].use_status = kNotUsed;
decode_buffer_pool_[dpb_buffer_.frame_buffer_list[i].dec_buf_idx].use_status &= ~kFrameUsedForDecode;
if (dpb_buffer_.dpb_fullness > 0) {
dpb_buffer_.dpb_fullness--;
} else {
@@ -2222,27 +2229,34 @@ int HevcVideoParser::MarkOutputPictures() {
return PARSER_OK;
}
int HevcVideoParser::FindFreeBufAndMark() {
ParserResult HevcVideoParser::FindFreeInDecBufPool() {
int dec_buf_index;
// Find a free buffer in decode buffer pool
for (dec_buf_index = 0; dec_buf_index < dec_buf_pool_size_; dec_buf_index++) {
if (decode_buffer_pool_[dec_buf_index].use_status == kNotUsed) {
break;
}
}
if (dec_buf_index == dec_buf_pool_size_) {
ERR("Could not find a free buffer in decode buffer pool.");
return PARSER_NOT_FOUND;
}
curr_pic_info_.dec_buf_idx = dec_buf_index;
return PARSER_OK;
}
ParserResult HevcVideoParser::FindFreeInDpbAndMark() {
int i, j;
// Look for an empty buffer with longest decode history (lowest decode count)
// Look for an empty buffer in DPB with longest decode history (lowest decode count)
uint32_t min_decode_order_count = 0xFFFFFFFF;
int index = dpb_buffer_.dpb_size;
for (i = 0; i < dpb_buffer_.dpb_size; i++) {
if (dpb_buffer_.frame_buffer_list[i].use_status == 0) {
if (dpb_buffer_.frame_buffer_list[i].use_status == kNotUsed) {
if (dpb_buffer_.frame_buffer_list[i].decode_order_count < min_decode_order_count) {
// Check if this picture has been bumped to the output/display list. If yes, skip it because we do not want to
// decode the current picture into any buffers in the output list
bool is_in_output_list = false;
for (j = 0; j < dpb_buffer_.num_output_pics; j++) {
if (dpb_buffer_.output_pic_list[j] == i) {
is_in_output_list = true;
}
}
if (!is_in_output_list) {
min_decode_order_count = dpb_buffer_.frame_buffer_list[i].decode_order_count;
index = i;
}
min_decode_order_count = dpb_buffer_.frame_buffer_list[i].decode_order_count;
index = i;
}
}
}
@@ -2254,6 +2268,7 @@ int HevcVideoParser::FindFreeBufAndMark() {
curr_pic_info_.pic_idx = index;
curr_pic_info_.is_reference = kUsedForShortTerm;
// dpb_buffer_.frame_buffer_list[i].pic_idx is already set in InitDpb().
dpb_buffer_.frame_buffer_list[index].dec_buf_idx = curr_pic_info_.dec_buf_idx;
dpb_buffer_.frame_buffer_list[index].pic_order_cnt = curr_pic_info_.pic_order_cnt;
dpb_buffer_.frame_buffer_list[index].prev_poc_lsb = curr_pic_info_.prev_poc_lsb;
dpb_buffer_.frame_buffer_list[index].prev_poc_msb = curr_pic_info_.prev_poc_msb;
@@ -2261,19 +2276,25 @@ int HevcVideoParser::FindFreeBufAndMark() {
dpb_buffer_.frame_buffer_list[index].decode_order_count = curr_pic_info_.decode_order_count;
dpb_buffer_.frame_buffer_list[index].pic_output_flag = curr_pic_info_.pic_output_flag;
dpb_buffer_.frame_buffer_list[index].is_reference = kUsedForShortTerm;
dpb_buffer_.frame_buffer_list[index].use_status = 3;
dpb_buffer_.frame_buffer_list[index].use_status = kFrameUsedForDecode;
if (dpb_buffer_.frame_buffer_list[index].pic_output_flag) {
dpb_buffer_.num_pics_needed_for_output++;
}
dpb_buffer_.dpb_fullness++;
// Mark as used in decode buffer pool
decode_buffer_pool_[curr_pic_info_.dec_buf_idx].use_status |= kFrameUsedForDecode;
if (pfn_display_picture_cb_ && curr_pic_info_.pic_output_flag) {
decode_buffer_pool_[curr_pic_info_.dec_buf_idx].use_status |= kFrameUsedForDisplay;
}
decode_buffer_pool_[curr_pic_info_.dec_buf_idx].pic_order_cnt = curr_pic_info_.pic_order_cnt;
HevcSeqParamSet *sps_ptr = &m_sps_[m_active_sps_id_];
uint32_t highest_tid = sps_ptr->sps_max_sub_layers_minus1; // HighestTid
uint32_t max_num_reorder_pics = sps_ptr->sps_max_num_reorder_pics[highest_tid];
// Conditional bumping (when max_num_reorder_pics > 0) to avoid synchronous job submission while keeping in conformance with the spec.
while (max_num_reorder_pics > 0 && dpb_buffer_.num_pics_needed_for_output > max_num_reorder_pics) {
while ( dpb_buffer_.num_pics_needed_for_output > max_num_reorder_pics) {
if (BumpPicFromDpb() != PARSER_OK) {
return PARSER_FAIL;
}
@@ -2310,19 +2331,22 @@ int HevcVideoParser::BumpPicFromDpb() {
// If it is not used for reference, empty it.
if (dpb_buffer_.frame_buffer_list[min_poc_pic_idx].is_reference == kUnusedForReference) {
dpb_buffer_.frame_buffer_list[min_poc_pic_idx].use_status = 0;
dpb_buffer_.frame_buffer_list[min_poc_pic_idx].use_status = kNotUsed;
decode_buffer_pool_[dpb_buffer_.frame_buffer_list[min_poc_pic_idx].dec_buf_idx].use_status &= ~kFrameUsedForDecode;
if (dpb_buffer_.dpb_fullness > 0 ) {
dpb_buffer_.dpb_fullness--;
}
}
// Insert into output/display picture list
if (dpb_buffer_.num_output_pics >= HEVC_MAX_DPB_FRAMES) {
ERR("Error! DPB output buffer list overflow!");
return PARSER_OUT_OF_RANGE;
} else {
dpb_buffer_.output_pic_list[dpb_buffer_.num_output_pics] = min_poc_pic_idx;
dpb_buffer_.num_output_pics++;
if (pfn_display_picture_cb_) {
if (num_output_pics_ >= dec_buf_pool_size_) {
ERR("Error! Decode buffer pool overflow!");
return PARSER_OUT_OF_RANGE;
} else {
output_pic_list_[num_output_pics_] = dpb_buffer_.frame_buffer_list[min_poc_pic_idx].dec_buf_idx;
num_output_pics_++;
}
}
return PARSER_OK;
@@ -2630,7 +2654,7 @@ void HevcVideoParser::PrintSliceSegHeader(HevcSliceSegHeader *slice_header_ptr)
MSG("slice_qp_delta = " << slice_header_ptr->slice_qp_delta);
MSG("slice_cb_qp_offset = " << slice_header_ptr->slice_cb_qp_offset);
MSG("slice_cr_qp_offset = " << slice_header_ptr->slice_cr_qp_offset);
MSG("cu_chroma_qp_offset_enabled_flag = " << slice_header_ptr->cu_chroma_qp_offset_enabled_flag);
MSG("cu_chroma_qp_offset_enabled_flag = " << static_cast<uint32_t>(slice_header_ptr->cu_chroma_qp_offset_enabled_flag));
MSG("deblocking_filter_override_flag = " << slice_header_ptr->deblocking_filter_override_flag);
MSG("slice_deblocking_filter_disabled_flag = " << slice_header_ptr->slice_deblocking_filter_disabled_flag);
MSG("slice_beta_offset_div2 = " << slice_header_ptr->slice_beta_offset_div2);
@@ -2644,18 +2668,18 @@ void HevcVideoParser::PrintSliceSegHeader(HevcSliceSegHeader *slice_header_ptr)
void HevcVideoParser::PrintStRps(HevcShortTermRps *rps_ptr) {
MSG("==== Short-term reference picture set =====")
MSG("inter_ref_pic_set_prediction_flag = " << rps_ptr->inter_ref_pic_set_prediction_flag);
MSG("inter_ref_pic_set_prediction_flag = " << static_cast<uint32_t>(rps_ptr->inter_ref_pic_set_prediction_flag));
MSG("delta_idx_minus1 = " << rps_ptr->delta_idx_minus1);
MSG("delta_rps_sign = " << rps_ptr->delta_rps_sign);
MSG("delta_rps_sign = " << static_cast<uint32_t>(rps_ptr->delta_rps_sign));
MSG("abs_delta_rps_minus1 = " << rps_ptr->abs_delta_rps_minus1);
MSG_NO_NEWLINE("rps->used_by_curr_pic_flag[]:");
for(int j = 0; j < 16; j++) {
MSG_NO_NEWLINE(" " << rps_ptr->used_by_curr_pic_flag[j]);
MSG_NO_NEWLINE(" " << static_cast<uint32_t>(rps_ptr->used_by_curr_pic_flag[j]));
}
MSG("");
MSG_NO_NEWLINE("use_delta_flag[]:");
for(int j = 0; j < 16; j++) {
MSG_NO_NEWLINE(" " << rps_ptr->use_delta_flag[j]);
MSG_NO_NEWLINE(" " << static_cast<uint32_t>(rps_ptr->use_delta_flag[j]));
}
MSG("");
MSG("num_negative_pics = " << rps_ptr->num_negative_pics);
@@ -2669,7 +2693,7 @@ void HevcVideoParser::PrintStRps(HevcShortTermRps *rps_ptr) {
MSG("");
MSG_NO_NEWLINE("used_by_curr_pic_s0_flag[]:");
for(int j = 0; j < 16; j++) {
MSG_NO_NEWLINE(" " << rps_ptr->used_by_curr_pic_s0_flag[j]);
MSG_NO_NEWLINE(" " << static_cast<uint32_t>(rps_ptr->used_by_curr_pic_s0_flag[j]));
}
MSG("");
MSG_NO_NEWLINE("delta_poc_s1_minus1[]:");
@@ -2679,7 +2703,7 @@ void HevcVideoParser::PrintStRps(HevcShortTermRps *rps_ptr) {
MSG("");
MSG_NO_NEWLINE("used_by_curr_pic_s1_flag[]:");
for(int j = 0; j < 16; j++) {
MSG_NO_NEWLINE(" " << rps_ptr->used_by_curr_pic_s1_flag[j]);
MSG_NO_NEWLINE(" " << static_cast<uint32_t>(rps_ptr->used_by_curr_pic_s1_flag[j]));
}
MSG("");
@@ -2695,12 +2719,12 @@ void HevcVideoParser::PrintStRps(HevcShortTermRps *rps_ptr) {
MSG("");
MSG_NO_NEWLINE("used_by_curr_pic_s0[16]:");
for(int j = 0; j < 16; j++) {
MSG_NO_NEWLINE(" " << rps_ptr->used_by_curr_pic_s0[j]);
MSG_NO_NEWLINE(" " << static_cast<uint32_t>(rps_ptr->used_by_curr_pic_s0[j]));
}
MSG("");
MSG_NO_NEWLINE("used_by_curr_pic_s1[16]:");
for(int j = 0; j < 16; j++) {
MSG_NO_NEWLINE(" " << rps_ptr->used_by_curr_pic_s1[j]);
MSG_NO_NEWLINE(" " << static_cast<uint32_t>(rps_ptr->used_by_curr_pic_s1[j]));
}
MSG("");
}
@@ -2719,4 +2743,71 @@ void HevcVideoParser::PrintLtRefInfo(HevcLongTermRps *lt_info_ptr) {
}
MSG("");
}
void HevcVideoParser::PrintDpb() {
uint32_t i;
MSG("=======================");
MSG("DPB buffer content: ");
MSG("=======================");
MSG("dpb_size = " << dpb_buffer_.dpb_size);
MSG("num_pics_needed_for_output = " << dpb_buffer_.num_pics_needed_for_output);
MSG("dpb_fullness = " << dpb_buffer_.dpb_fullness);
MSG("Frame buffer store:");
for (i = 0; i < HEVC_MAX_DPB_FRAMES; i++) {
HevcPicInfo *p_buf = &dpb_buffer_.frame_buffer_list[i];
MSG("Frame buffer " << i << ": pic_idx = " << p_buf->pic_idx << ", dec_buf_idx = " << p_buf->dec_buf_idx << ", pic_order_cnt = " << p_buf->pic_order_cnt << ", slice_pic_order_cnt_lsb = " << p_buf->slice_pic_order_cnt_lsb << ", decode_order_count = " << p_buf->decode_order_count << ", is_reference = " << p_buf->is_reference << ", use_status = " << p_buf->use_status << ", pic_output_flag = " << p_buf->pic_output_flag);
}
MSG("");
MSG("Decode buffer pool:");
for(i = 0; i < dec_buf_pool_size_; i++) {
DecodeFrameBuffer *p_dec_buf = &decode_buffer_pool_[i];
MSG("Decode buffer " << i << ": use_status = " << p_dec_buf->use_status << ", pic_order_cnt = " << p_dec_buf->pic_order_cnt);
}
MSG("num_output_pics_ = " << num_output_pics_);
if (num_output_pics_) {
MSG("output_pic_list:");
for (i = 0; i < num_output_pics_; i++) {
MSG_NO_NEWLINE(output_pic_list_[i] << ", ");
}
MSG("");
}
}
void HevcVideoParser::PrintVappiBufInfo() {
RocdecHevcPicParams *p_pic_param = &dec_pic_params_.pic_params.hevc;
MSG("=======================");
MSG("VAAPI Buffer Info: ");
MSG("=======================");
MSG("Current buffer:");
MSG_NO_NEWLINE("pic_idx = " << p_pic_param->curr_pic.pic_idx << ", poc = " << p_pic_param->curr_pic.poc);
MSG(", flags = 0x" << std::hex << p_pic_param->curr_pic.flags);
MSG(std::dec);
MSG("Reference pictures:");
for (int i = 0; i < 15; i++) {
RocdecHevcPicture *p_ref_pic = &p_pic_param->ref_frames[i];
MSG_NO_NEWLINE("Ref pic " << i << ": " << "pic_idx = " << p_ref_pic->pic_idx << ", poc = " << p_ref_pic->poc);
MSG(", flags = 0x" << std::hex << p_ref_pic->flags);
MSG_NO_NEWLINE(std::dec);
}
MSG("Slice ref lists:")
for (int slice_index = 0; slice_index < num_slices_; slice_index++) {
RocdecHevcSliceParams *p_slice_param = &slice_param_list_[slice_index];
HevcSliceInfo *p_slice_info = &slice_info_list_[slice_index];
MSG("Slice " << slice_index << " ref list 0:");
for (int i = 0; i <= p_slice_info->slice_header.num_ref_idx_l0_active_minus1; i++) {
MSG("Index " << i << ": " << static_cast<uint32_t>(p_slice_param->ref_pic_list[0][i]));
}
if (p_slice_info->slice_header.slice_type == HEVC_SLICE_TYPE_B) {
MSG("Slice " << slice_index << " ref list 1: ");
for (int i = 0; i <= p_slice_info->slice_header.num_ref_idx_l1_active_minus1; i++) {
MSG("Index " << i << ": " << static_cast<uint32_t>(p_slice_param->ref_pic_list[1][i]));
}
}
MSG("");
}
}
#endif // DBGINFO
+11 -11
View File
@@ -98,6 +98,7 @@ protected:
*/
typedef struct {
int pic_idx; // picture index or id
int dec_buf_idx; // frame index in decode buffer pool
// POC info
int32_t pic_order_cnt; // PicOrderCnt
int32_t prev_poc_lsb; // prevPicOrderCntLsb
@@ -107,7 +108,7 @@ protected:
uint32_t pic_output_flag; // PicOutputFlag
uint32_t is_reference;
uint32_t use_status; // 0 = empty; 1 = top used; 2 = bottom used; 3 = both fields or frame used
uint32_t use_status; // refer to FrameBufUseStatus
} HevcPicInfo;
/*! \brief Decoded picture buffer
@@ -118,9 +119,6 @@ protected:
uint32_t num_pics_needed_for_output; // number of pictures in DPB that need to be output
uint32_t dpb_fullness; // number of pictures in DPB
HevcPicInfo frame_buffer_list[HEVC_MAX_DPB_FRAMES];
uint32_t num_output_pics; // number of pictures that are output after the decode call
uint32_t output_pic_list[HEVC_MAX_DPB_FRAMES]; // sorted output picuture index to frame_buffer_list[]
} DecodedPictureBuffer;
// Data members of HEVC class
@@ -308,11 +306,16 @@ protected:
*/
int MarkOutputPictures();
/*! \brief Function to find a free buffer in the decode buffer pool
* \return <tt>ParserResult</tt>
*/
ParserResult FindFreeInDecBufPool();
/*! \brief Function to find a free buffer in DPB for the current picture and mark it. Additional picture
* bumping is done if needed. C.5.2.3.
* \return Code in ParserResult form.
* \return <tt>ParserResult</tt>
*/
int FindFreeBufAndMark();
ParserResult FindFreeInDpbAndMark();
/*! \brief Function to bump one picture out of DPB. C.5.2.4.
* \return Code in ParserResult form.
@@ -333,6 +336,8 @@ protected:
void PrintSliceSegHeader(HevcSliceSegHeader *slice_header_ptr);
void PrintStRps(HevcShortTermRps *rps_ptr);
void PrintLtRefInfo(HevcLongTermRps *lt_info_ptr);
void PrintDpb();
void PrintVappiBufInfo();
#endif // DBGINFO
private:
@@ -349,11 +354,6 @@ private:
*/
int SendPicForDecode();
/*! \brief Callback function to output decoded pictures from DPB for post-processing.
* \return Return code in ParserResult form
*/
int OutputDecodedPictures();
bool IsIdrPic(HevcNalUnitHeader *nal_header_ptr);
bool IsCraPic(HevcNalUnitHeader *nal_header_ptr);
bool IsBlaPic(HevcNalUnitHeader *nal_header_ptr);
@@ -57,16 +57,65 @@ rocDecStatus RocVideoParser::Initialize(RocdecParserParams *pParams) {
return ROCDEC_NOT_INITIALIZED;
}
// Initialize callback function pointers
pfn_sequece_cb_ = pParams->pfn_sequence_callback; /**< Called before decoding frames and/or whenever there is a fmt change */
pfn_sequece_cb_ = pParams->pfn_sequence_callback; /**< Called before decoding frames and/or whenever there is a fmt change */
pfn_decode_picture_cb_ = pParams->pfn_decode_picture; /**< Called when a picture is ready to be decoded (decode order) */
pfn_display_picture_cb_ = pParams->pfn_display_picture; /**< Called whenever a picture is ready to be displayed (display order) */
pfn_get_sei_message_cb_ = pParams->pfn_get_sei_msg; /**< Called when all SEI messages are parsed for particular frame */
pfn_display_picture_cb_ = pParams->pfn_display_picture; /**< Called whenever a picture is ready to be displayed (display order) */
pfn_get_sei_message_cb_ = pParams->pfn_get_sei_msg; /**< Called when all SEI messages are parsed for particular frame */
parser_params_ = *pParams;
dec_buf_pool_size_ = parser_params_.max_num_decode_surfaces;
decode_buffer_pool_.resize(dec_buf_pool_size_, {0});
output_pic_list_.resize(dec_buf_pool_size_, 0xFF);
InitDecBufPool();
return ROCDEC_SUCCESS;
}
void RocVideoParser::InitDecBufPool() {
for (int i = 0; i < dec_buf_pool_size_; i++) {
decode_buffer_pool_[i].use_status = kNotUsed;
decode_buffer_pool_[i].pic_order_cnt = 0;
output_pic_list_[i] = 0xFF;
}
num_output_pics_ = 0;
}
void RocVideoParser::CheckAndAdjustDecBufPoolSize(int dpb_size) {
int min_dec_buf_pool_size = dpb_size + (parser_params_.max_display_delay > DECODE_BUF_POOL_EXTENSION ? parser_params_.max_display_delay : DECODE_BUF_POOL_EXTENSION);
if ( dec_buf_pool_size_ < min_dec_buf_pool_size) {
dec_buf_pool_size_ = min_dec_buf_pool_size;
decode_buffer_pool_.resize(dec_buf_pool_size_, {0});
output_pic_list_.resize(dec_buf_pool_size_, 0xFF);
InitDecBufPool();
}
}
ParserResult RocVideoParser::OutputDecodedPictures(bool no_delay) {
RocdecParserDispInfo disp_info = {0};
disp_info.progressive_frame = 1; // not used
disp_info.top_field_first = 1; // not used
int disp_delay = no_delay ? 0 : parser_params_.max_display_delay;
if (num_output_pics_ > disp_delay) {
int num_disp = num_output_pics_ - disp_delay;
for (int i = 0; i < num_disp; i++) {
disp_info.picture_index = output_pic_list_[i];
pfn_display_picture_cb_(parser_params_.user_data, &disp_info);
decode_buffer_pool_[output_pic_list_[i]].use_status &= ~kFrameUsedForDisplay;
}
num_output_pics_ = disp_delay;
// Shift the remaining frames to the top
if (num_output_pics_) {
for (int i = 0; i < num_output_pics_; i++) {
output_pic_list_[i] = output_pic_list_[i + num_disp];
}
}
}
return PARSER_OK;
}
ParserResult RocVideoParser::GetNalUnit() {
bool start_code_found = false;
@@ -78,6 +78,15 @@ typedef struct {
#define INIT_SLICE_LIST_NUM 16 // initial slice information/parameter struct list size
#define INIT_SEI_MESSAGE_COUNT 16 // initial SEI message count
#define INIT_SEI_PAYLOAD_BUF_SIZE 1024 * 1024 // initial SEI payload buffer size, 1 MB
#define DECODE_BUF_POOL_EXTENSION 2
enum {
kNotUsed = 0,
kTopFieldUsedForDecode = 1,
kBottomFieldUsedForDecode = 1 << 1,
kFrameUsedForDecode = kTopFieldUsedForDecode | kBottomFieldUsedForDecode,
kFrameUsedForDisplay = 1 << 2
} FrameBufUseStatus;
/**
* @brief Base class for video parsing
@@ -109,6 +118,21 @@ protected:
uint32_t pic_height_;
bool new_sps_activated_;
// Decoded buffer pool
typedef struct {
uint32_t use_status; // refer to FrameBufUseStatus
uint32_t pic_order_cnt;
} DecodeFrameBuffer;
uint32_t dec_buf_pool_size_; /* Number of decoded frame surfaces in the pool which are recycled. The size should be greater
than or equal to DPB size (normally greater to guarantee smooth operations). The value is
set to max_num_decode_surfaces from the decoder but parser checks and increases if needed. */
/* This array maps to VA surface array allocated at VA-API layer. A frame in the pool is identified by its index in the array, which
* is used to retrieve the VA surface Id.
*/
std::vector<DecodeFrameBuffer> decode_buffer_pool_;
uint32_t num_output_pics_; // number of pictures that are ready to be ouput
std::vector<uint32_t> output_pic_list_; // sorted output frame index to decode_buffer_pool_
Rational frame_rate_;
RocdecVideoFormat video_format_params_;
@@ -141,6 +165,17 @@ protected:
uint32_t sei_payload_buf_size_;
uint32_t sei_payload_size_; // total SEI payload size of the current frame
/*! \brief Function to check the initially set (by decoder) decode buffer pool size and adjust if needed
* \param dpb_size The DPB buffer size of the current sequence
*/
void CheckAndAdjustDecBufPoolSize(int dpb_size);
/*! \brief Callback function to output decoded pictures from DPB for post-processing.
* \param [in] no_delay Indicator to override the display delay parameter wth no delay
* \return <tt>ParserResult</tt>
*/
ParserResult OutputDecodedPictures(bool no_delay);
/*! \brief Function to get the NAL Unit data
* \return Returns OK if successful, else error code
*/
@@ -161,6 +196,10 @@ protected:
* \return No return value
*/
void ParseSeiMessage(uint8_t *nalu, size_t size);
/*! \brief Function to initialize the decoded buffer pool
*/
void InitDecBufPool();
};
// helpers
@@ -23,9 +23,9 @@ THE SOFTWARE.
#include "roc_video_dec.h"
RocVideoDecoder::RocVideoDecoder(int device_id, OutputSurfaceMemoryType out_mem_type, rocDecVideoCodec codec, bool force_zero_latency,
const Rect *p_crop_rect, bool extract_user_sei_Message, int max_width, int max_height, uint32_t clk_rate) :
const Rect *p_crop_rect, bool extract_user_sei_Message, uint32_t disp_delay, int max_width, int max_height, uint32_t clk_rate) :
device_id_{device_id}, out_mem_type_(out_mem_type), codec_id_(codec), b_force_zero_latency_(force_zero_latency),
b_extract_sei_message_(extract_user_sei_Message), max_width_ (max_width), max_height_(max_height) {
b_extract_sei_message_(extract_user_sei_Message), disp_delay_(disp_delay), max_width_ (max_width), max_height_(max_height) {
if (!InitHIP(device_id_)) {
THROW("Failed to initilize the HIP");
@@ -39,9 +39,9 @@ RocVideoDecoder::RocVideoDecoder(int device_id, OutputSurfaceMemoryType out_mem_
// create rocdec videoparser
RocdecParserParams parser_params = {};
parser_params.codec_type = codec_id_;
parser_params.max_num_decode_surfaces = 1;
parser_params.max_num_decode_surfaces = 1; // let the parser to determine the decode buffer pool size
parser_params.clock_rate = clk_rate;
parser_params.max_display_delay = 0;
parser_params.max_display_delay = disp_delay_;
parser_params.user_data = this;
parser_params.pfn_sequence_callback = HandleVideoSequenceProc;
parser_params.pfn_decode_picture = HandlePictureDecodeProc;
@@ -50,7 +50,8 @@ extern "C" {
* \brief AMD The rocDecode video decoder for AMDs GPUs.
*/
#define MAX_FRAME_NUM 16
#define MAX_FRAME_NUM 16
typedef int (ROCDECAPI *PFNRECONFIGUEFLUSHCALLBACK)(void *, uint32_t, void *);
typedef enum SeiAvcHevcPayloadType_enum {
@@ -177,7 +178,7 @@ class RocVideoDecoder {
* @param force_zero_latency
*/
RocVideoDecoder(int device_id, OutputSurfaceMemoryType out_mem_type, rocDecVideoCodec codec, bool force_zero_latency = false,
const Rect *p_crop_rect = nullptr, bool extract_user_SEI_Message = false, int max_width = 0, int max_height = 0,
const Rect *p_crop_rect = nullptr, bool extract_user_SEI_Message = false, uint32_t disp_delay = 0, int max_width = 0, int max_height = 0,
uint32_t clk_rate = 1000);
~RocVideoDecoder();
@@ -426,6 +427,7 @@ class RocVideoDecoder {
OutputSurfaceMemoryType out_mem_type_ = OUT_SURFACE_MEM_DEV_INTERNAL;
bool b_extract_sei_message_ = false;
bool b_force_zero_latency_ = false;
uint32_t disp_delay_;
ReconfigParams *p_reconfig_params_ = nullptr;
int32_t num_frames_flushed_during_reconfig_ = 0;
hipDeviceProp_t hip_dev_prop_;