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.
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
8898af78a6
Коммит
624c3c0f09
@@ -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<double, std::milli>(end_time - start_time).count();
|
||||
total_dec_time += time_per_frame;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Ссылка в новой задаче
Block a user