From 624c3c0f0932e471a24d491c6f5b7b08fd419eaa Mon Sep 17 00:00:00 2001 From: jeffqjiangNew <142832361+jeffqjiangNew@users.noreply.github.com> Date: Mon, 27 Nov 2023 13:03:26 -0500 Subject: [PATCH] End of stream flush (#86) * * rocDecode/HEVC: Added picture output operation in DPB and display callback function. - To avoid serialization of decode submissions and/or display callback in certain cases, increased DPB buffer size by 1 and tweaked picture bumping procedure. * * rocDecode/HEVC: Added flushing of the remaining pictures from DPB at the end of decode session. * * rocDecode/HEVC: Changed output_pic_num to num_output_pics to void some confusion. Set top_field_first to 1. * * rocDecode/HEVC: Added a few return error checks. --- samples/videoDecode/videodecode.cpp | 7 +- src/parser/hevc_parser.cpp | 101 ++++++++++++++++--------- src/parser/hevc_parser.h | 7 +- utils/rocvideodecode/roc_video_dec.cpp | 25 +++--- 4 files changed, 89 insertions(+), 51 deletions(-) diff --git a/samples/videoDecode/videodecode.cpp b/samples/videoDecode/videodecode.cpp index 4f4b71463d..6aa5d59c3d 100644 --- a/samples/videoDecode/videodecode.cpp +++ b/samples/videoDecode/videodecode.cpp @@ -130,6 +130,7 @@ int main(int argc, char **argv) { int n_video_bytes = 0, n_frame_returned = 0, n_frame = 0; uint8_t *pvideo = nullptr; + int pkg_flags = 0; uint8_t *pframe = nullptr; int64_t pts = 0; OutputSurfaceInfo *surf_info; @@ -139,7 +140,11 @@ int main(int argc, char **argv) { do { auto start_time = std::chrono::high_resolution_clock::now(); demuxer.Demux(&pvideo, &n_video_bytes, &pts); - n_frame_returned = viddec.DecodeFrame(pvideo, n_video_bytes, 0, pts); + // Treat 0 bitstream size as end of stream indicator + if (n_video_bytes == 0) { + pkg_flags |= ROCDEC_PKT_ENDOFSTREAM; + } + n_frame_returned = viddec.DecodeFrame(pvideo, n_video_bytes, pkg_flags, pts); auto end_time = std::chrono::high_resolution_clock::now(); auto time_per_frame = std::chrono::duration(end_time - start_time).count(); total_dec_time += time_per_frame; diff --git a/src/parser/hevc_parser.cpp b/src/parser/hevc_parser.cpp index 9be951481e..7b563bd611 100644 --- a/src/parser/hevc_parser.cpp +++ b/src/parser/hevc_parser.cpp @@ -79,39 +79,52 @@ rocDecStatus HEVCVideoParser::UnInitialize() { rocDecStatus HEVCVideoParser::ParseVideoData(RocdecSourceDataPacket *p_data) { - // Clear DPB output/display buffer number - dpb_buffer_.output_pic_num = 0; + if (p_data->payload && p_data->payload_size) { + // Clear DPB output/display buffer number + dpb_buffer_.num_output_pics = 0; - bool status = ParseFrameData(p_data->payload, p_data->payload_size); - if (!status) { - ERR(STR("Parser failed!")); - return ROCDEC_RUNTIME_ERROR; + bool status = ParseFrameData(p_data->payload, p_data->payload_size); + if (!status) { + ERR(STR("Parser failed!")); + return ROCDEC_RUNTIME_ERROR; + } + + // Init Roc decoder for the first time or reconfigure the existing decoder + if (new_sps_activated_) { + FillSeqCallbackFn(&m_sps_[m_active_sps_id_]); + new_sps_activated_ = false; + } + + // Whenever new sei message found + if (pfn_get_sei_message_cb_ && sei_message_count_ > 0) { + FillSeiMessageCallbackFn(); + } + + // Decode the picture + if (SendPicForDecode() != PARSER_OK) { + ERR(STR("Failed to decode!")); + return ROCDEC_RUNTIME_ERROR; + } + + // Output decoded pictures from DPB if any are ready + if (pfn_display_picture_cb_ && dpb_buffer_.num_output_pics > 0) { + if (OutputDecodedPictures() != PARSER_OK) { + return ROCDEC_RUNTIME_ERROR; + } + } + + pic_count_++; + } else if (!(p_data->flags & ROCDEC_PKT_ENDOFSTREAM)) { + // If no payload and EOS is not set, treated as invalid. + return ROCDEC_INVALID_PARAMETER; } - // Init Roc decoder for the first time or reconfigure the existing decoder - if (new_sps_activated_) { - FillSeqCallbackFn(&m_sps_[m_active_sps_id_]); - new_sps_activated_ = false; + if (p_data->flags & ROCDEC_PKT_ENDOFSTREAM) { + if (FlushDpb() != PARSER_OK) { + return ROCDEC_RUNTIME_ERROR; + } } - // Whenever new sei message found - if (pfn_get_sei_message_cb_ && sei_message_count_ > 0) { - FillSeiMessageCallbackFn(); - } - - // Decode the picture - if (SendPicForDecode() != PARSER_OK) { - ERR(STR("Failed to decode!")); - return ROCDEC_RUNTIME_ERROR; - } - - // Output decoded pictures from DPB if any are ready - if (pfn_display_picture_cb_ && dpb_buffer_.output_pic_num > 0) { - OutputDecodedPictures(); - } - - pic_count_++; - return ROCDEC_SUCCESS; } @@ -513,12 +526,14 @@ 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 = 0; + disp_info.top_field_first = 1; - for (int i = 0; i < dpb_buffer_.output_pic_num; i++) { + 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_.pUserData, &disp_info); } + + dpb_buffer_.num_output_pics = 0; return PARSER_OK; } @@ -2171,7 +2186,7 @@ void HEVCVideoParser::InitDpb() { dpb_buffer_.dpb_size = 0; dpb_buffer_.dpb_fullness = 0; dpb_buffer_.num_needed_for_output = 0; - dpb_buffer_.output_pic_num = 0; + dpb_buffer_.num_output_pics = 0; } void HEVCVideoParser::EmptyDpb() { @@ -2183,7 +2198,23 @@ void HEVCVideoParser::EmptyDpb() { } dpb_buffer_.dpb_fullness = 0; dpb_buffer_.num_needed_for_output = 0; - dpb_buffer_.output_pic_num = 0; + dpb_buffer_.num_output_pics = 0; +} + +int HEVCVideoParser::FlushDpb() { + dpb_buffer_.num_output_pics = 0; + // Bump the remaining pictures + while (dpb_buffer_.num_needed_for_output) { + if (BumpPicFromDpb() != PARSER_OK) { + return PARSER_FAIL; + } + } + if (pfn_display_picture_cb_ && dpb_buffer_.num_output_pics > 0) { + if (OutputDecodedPictures() != PARSER_OK) { + return PARSER_FAIL; + } + } + return PARSER_OK; } int HEVCVideoParser::MarkOutputPictures() { @@ -2321,12 +2352,12 @@ int HEVCVideoParser::BumpPicFromDpb() { } // Insert into output/display picture list - if (dpb_buffer_.output_pic_num >= HEVC_MAX_DPB_FRAMES) { + 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_.output_pic_num] = min_poc_pic_idx; - dpb_buffer_.output_pic_num++; + dpb_buffer_.output_pic_list[dpb_buffer_.num_output_pics] = min_poc_pic_idx; + dpb_buffer_.num_output_pics++; } return PARSER_OK; diff --git a/src/parser/hevc_parser.h b/src/parser/hevc_parser.h index 5a2f9b4fcb..549800d18e 100644 --- a/src/parser/hevc_parser.h +++ b/src/parser/hevc_parser.h @@ -652,7 +652,7 @@ protected: uint32_t dpb_fullness; // number of pictures in DPB HevcPicInfo frame_buffer_list[HEVC_MAX_DPB_FRAMES]; - uint32_t output_pic_num; // number of pictures are output after the decode call + 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; @@ -877,6 +877,11 @@ protected: */ void EmptyDpb(); + /*! \brief Function to send out the remaining pictures that need for output in DPB buffer. + * \return Code in ParserResult form. + */ + int FlushDpb(); + /*! \brief Function to output and remove pictures from DPB. C.5.2.2. * \return Code in ParserResult form. */ diff --git a/utils/rocvideodecode/roc_video_dec.cpp b/utils/rocvideodecode/roc_video_dec.cpp index b675cd6479..13dec3a976 100644 --- a/utils/rocvideodecode/roc_video_dec.cpp +++ b/utils/rocvideodecode/roc_video_dec.cpp @@ -594,21 +594,18 @@ int RocVideoDecoder::GetSEIMessage(RocdecSeiMessageInfo *pSEIMessageInfo) { int RocVideoDecoder::DecodeFrame(const uint8_t *data, size_t size, int pkt_flags, int64_t pts) { - if (data && size) { - decoded_frame_cnt_ = 0, decoded_frame_cnt_ret_ = 0; - RocdecSourceDataPacket packet = { 0 }; - packet.payload = data; - packet.payload_size = size; - packet.flags = pkt_flags | ROCDEC_PKT_TIMESTAMP; - packet.pts = pts; - if (!data || size == 0) { - packet.flags |= ROCDEC_PKT_ENDOFSTREAM; - } - ROCDEC_API_CALL(rocDecParseVideoData(rocdec_parser_, &packet)); + decoded_frame_cnt_ = 0, decoded_frame_cnt_ret_ = 0; + RocdecSourceDataPacket packet = { 0 }; + packet.payload = data; + packet.payload_size = size; + packet.flags = pkt_flags | ROCDEC_PKT_TIMESTAMP; + packet.pts = pts; + if (!data || size == 0) { + packet.flags |= ROCDEC_PKT_ENDOFSTREAM; + } + ROCDEC_API_CALL(rocDecParseVideoData(rocdec_parser_, &packet)); - return decoded_frame_cnt_; - } else - return 0; + return decoded_frame_cnt_; } uint8_t* RocVideoDecoder::GetFrame(int64_t *pts) {