* * 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.
Этот коммит содержится в:
jeffqjiangNew
2023-11-27 13:03:26 -05:00
коммит произвёл GitHub
родитель 8898af78a6
Коммит 624c3c0f09
4 изменённых файлов: 89 добавлений и 51 удалений
+6 -1
Просмотреть файл
@@ -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;
+66 -35
Просмотреть файл
@@ -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;
+6 -1
Просмотреть файл
@@ -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.
*/
+11 -14
Просмотреть файл
@@ -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) {