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]
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
4a6e9d709b
Коммит
3230cca447
@@ -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("");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Ссылка в новой задаче
Block a user