From ede21fffa0e610e92133b37b701a4bd8b82d5b02 Mon Sep 17 00:00:00 2001 From: jeffqjiangNew <142832361+jeffqjiangNew@users.noreply.github.com> Date: Tue, 18 Mar 2025 17:19:01 -0400 Subject: [PATCH] HEVC: Added DPB size change handling through decoder reconfiguration. (#531) * * rocDecode/HEVC: Added DPB size change handling through decoder reconfiguration. * * rocDecode/HEVC: Minor fix. [ROCm/rocdecode commit: 5988eb16b643bdf34326eb4253529266e629843e] --- projects/rocdecode/CHANGELOG.md | 2 +- projects/rocdecode/src/parser/hevc_parser.cpp | 5 ++-- .../rocdecode/src/parser/roc_video_parser.cpp | 1 + .../rocdecode/src/rocdecode/roc_decoder.cpp | 3 +++ .../utils/rocvideodecode/roc_video_dec.cpp | 23 ++++++++++++------- .../utils/rocvideodecode/roc_video_dec.h | 1 + 6 files changed, 24 insertions(+), 11 deletions(-) diff --git a/projects/rocdecode/CHANGELOG.md b/projects/rocdecode/CHANGELOG.md index 07f2e2c343..7d8b64a336 100644 --- a/projects/rocdecode/CHANGELOG.md +++ b/projects/rocdecode/CHANGELOG.md @@ -9,7 +9,7 @@ Full documentation for rocDecode is available at [https://rocm.docs.amd.com/proj * VP9 IVF container file parsing support in bitstream reader. * CTest for VP9 decode on bitstream reader. * HEVC stream syntax error handling. -* HEVC stream bit depth change handling through decoder reconfiguration. +* HEVC stream bit depth change handling and DPB buffer size change handling through decoder reconfiguration. * rocDecode now uses the Cmake CMAKE_PREFIX_PATH directive. ### Optimized diff --git a/projects/rocdecode/src/parser/hevc_parser.cpp b/projects/rocdecode/src/parser/hevc_parser.cpp index 228307ed0a..5a249ed604 100644 --- a/projects/rocdecode/src/parser/hevc_parser.cpp +++ b/projects/rocdecode/src/parser/hevc_parser.cpp @@ -1551,7 +1551,7 @@ 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 = &sps_list_[m_active_sps_id_]; - new_seq_activated_ = true; // Note: clear this flag after the actions are taken. + new_seq_activated_ = true; } sps_ptr = &sps_list_[m_active_sps_id_]; @@ -1570,7 +1570,7 @@ 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 - new_seq_activated_ = true; // Note: clear this flag after the actions are taken. + new_seq_activated_ = true; } // Check DPB buffer size change uint32_t max_dec_pic_buffering = sps_ptr->sps_max_dec_pic_buffering_minus1[sps_ptr->sps_max_sub_layers_minus1] + 1; @@ -1578,6 +1578,7 @@ ParserResult HevcVideoParser::ParseSliceHeader(uint8_t *nalu, size_t size, HevcS dpb_buffer_.dpb_size = max_dec_pic_buffering; dpb_buffer_.dpb_size = dpb_buffer_.dpb_size > HEVC_MAX_DPB_FRAMES ? HEVC_MAX_DPB_FRAMES : dpb_buffer_.dpb_size; CheckAndAdjustDecBufPoolSize(dpb_buffer_.dpb_size); + new_seq_activated_ = true; } // Check bit depth change if (bit_depth_luma_minus8_ != sps_ptr->bit_depth_luma_minus8 || bit_depth_chroma_minus8_ != sps_ptr->bit_depth_chroma_minus8) { diff --git a/projects/rocdecode/src/parser/roc_video_parser.cpp b/projects/rocdecode/src/parser/roc_video_parser.cpp index 695d9e52ee..b3872cb1c1 100644 --- a/projects/rocdecode/src/parser/roc_video_parser.cpp +++ b/projects/rocdecode/src/parser/roc_video_parser.cpp @@ -94,6 +94,7 @@ void RocVideoParser::InitDecBufPool() { 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 DPB size decreases, we keep the existing pool and skip reconfiguration. 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}); diff --git a/projects/rocdecode/src/rocdecode/roc_decoder.cpp b/projects/rocdecode/src/rocdecode/roc_decoder.cpp index 8e87ff8a80..8e864510f4 100644 --- a/projects/rocdecode/src/rocdecode/roc_decoder.cpp +++ b/projects/rocdecode/src/rocdecode/roc_decoder.cpp @@ -93,6 +93,9 @@ rocDecStatus RocDecoder::ReconfigureDecoder(RocdecReconfigureDecoderInfo *reconf return rocdec_status; } } + if (hip_interop_.size() != reconfig_params->num_decode_surfaces) { + hip_interop_.resize(reconfig_params->num_decode_surfaces); + } rocdec_status = va_video_decoder_.ReconfigureDecoder(reconfig_params); if (rocdec_status != ROCDEC_SUCCESS) { ERR("Reconfiguration of the decoder failed."); diff --git a/projects/rocdecode/utils/rocvideodecode/roc_video_dec.cpp b/projects/rocdecode/utils/rocvideodecode/roc_video_dec.cpp index e34a98bfa2..323e67291a 100644 --- a/projects/rocdecode/utils/rocvideodecode/roc_video_dec.cpp +++ b/projects/rocdecode/utils/rocvideodecode/roc_video_dec.cpp @@ -238,7 +238,6 @@ static void GetSurfaceStrideInternal(rocDecVideoSurfaceFormat surface_format, ui * 0: fail, 1: succeeded, > 1: override dpb size of parser (set by RocdecParserParams::max_num_decode_surfaces while creating parser) */ int RocVideoDecoder::HandleVideoSequence(RocdecVideoFormat *p_video_format) { - if (p_video_format == nullptr) { ROCDEC_THROW("Rocdec:: Invalid video format in HandleVideoSequence: ", ROCDEC_INVALID_PARAMETER); return 0; @@ -260,8 +259,6 @@ int RocVideoDecoder::HandleVideoSequence(RocdecVideoFormat *p_video_format) { ; input_video_info_str_ << std::endl; - int num_decode_surfaces = p_video_format->min_num_decode_surfaces; - RocdecDecodeCaps decode_caps; memset(&decode_caps, 0, sizeof(decode_caps)); decode_caps.codec_type = p_video_format->codec; @@ -329,6 +326,7 @@ int RocVideoDecoder::HandleVideoSequence(RocdecVideoFormat *p_video_format) { disp_rect_.right = p_video_format->display_area.right; disp_width_ = p_video_format->display_area.right - p_video_format->display_area.left; disp_height_ = p_video_format->display_area.bottom - p_video_format->display_area.top; + num_decode_surfaces_ = p_video_format->min_num_decode_surfaces; // AV1 has max width/height of sequence in sequence header if (codec_id_ == rocDecVideoCodec_AV1 && p_video_format->seqhdr_data_length > 0) { @@ -350,7 +348,7 @@ int RocVideoDecoder::HandleVideoSequence(RocdecVideoFormat *p_video_format) { videoDecodeCreateInfo.chroma_format = video_chroma_format_; videoDecodeCreateInfo.output_format = video_surface_format_; videoDecodeCreateInfo.bit_depth_minus_8 = bitdepth_minus_8_; - videoDecodeCreateInfo.num_decode_surfaces = num_decode_surfaces; + videoDecodeCreateInfo.num_decode_surfaces = num_decode_surfaces_; videoDecodeCreateInfo.width = coded_width_; videoDecodeCreateInfo.height = coded_height_; videoDecodeCreateInfo.max_width = max_width_; @@ -419,7 +417,7 @@ int RocVideoDecoder::HandleVideoSequence(RocdecVideoFormat *p_video_format) { ROCDEC_API_CALL(rocDecCreateDecoder(&roc_decoder_, &videoDecodeCreateInfo)); double elapsed_time = StopTimer(start_time); AddDecoderSessionOverHead(std::this_thread::get_id(), elapsed_time); - return num_decode_surfaces; + return num_decode_surfaces_; } /** @@ -476,13 +474,16 @@ int RocVideoDecoder::ReconfigureDecoder(RocdecVideoFormat *p_video_format) { ROCDEC_THROW("Reconfigure Not supported for chroma format change", ROCDEC_NOT_SUPPORTED); return 0; } + bool is_decode_res_changed = !(p_video_format->coded_width == coded_width_ && p_video_format->coded_height == coded_height_); bool is_display_rect_changed = !(p_video_format->display_area.bottom == disp_rect_.bottom && p_video_format->display_area.top == disp_rect_.top && p_video_format->display_area.left == disp_rect_.left && p_video_format->display_area.right == disp_rect_.right); bool is_bit_depth_changed = p_video_format->bit_depth_luma_minus8 != bitdepth_minus_8_; - if (!is_decode_res_changed && !is_display_rect_changed && !is_bit_depth_changed && !b_force_recofig_flush_) { + bool is_dec_surface_num_changed = p_video_format->min_num_decode_surfaces != num_decode_surfaces_; + + if (!is_decode_res_changed && !is_display_rect_changed && !is_bit_depth_changed && !is_dec_surface_num_changed && !b_force_recofig_flush_) { return 1; } @@ -542,6 +543,7 @@ int RocVideoDecoder::ReconfigureDecoder(RocdecVideoFormat *p_video_format) { else if (video_chroma_format_ == rocDecVideoChromaFormat_422) video_surface_format_ = bitdepth_minus_8_ ? rocDecVideoSurfaceFormat_YUV422_16Bit : rocDecVideoSurfaceFormat_YUV422; } + num_decode_surfaces_ = p_video_format->min_num_decode_surfaces; if (p_video_format->reconfig_options == ROCDEC_RECONFIG_NEW_SURFACES) { if (out_mem_type_ == OUT_SURFACE_MEM_DEV_INTERNAL || out_mem_type_ == OUT_SURFACE_MEM_NOT_MAPPED) { @@ -583,7 +585,7 @@ int RocVideoDecoder::ReconfigureDecoder(RocdecVideoFormat *p_video_format) { // If the coded_width or coded_height hasn't changed but display resolution has changed, then need to update width and height for // correct output with cropping. There is no need to reconfigure the decoder. - if (!is_decode_res_changed && is_display_rect_changed && !is_bit_depth_changed) { + if (!is_decode_res_changed && is_display_rect_changed && !is_bit_depth_changed && !is_dec_surface_num_changed) { return 1; } @@ -621,6 +623,9 @@ int RocVideoDecoder::ReconfigureDecoder(RocdecVideoFormat *p_video_format) { } if (is_bit_depth_changed) { input_video_info_str_ << "Input Video Bit Depth Changed:" << std::endl; + } + if (is_dec_surface_num_changed) { + input_video_info_str_ << "Number of decoded surfaces Changed:" << std::endl; } input_video_info_str_ << "\tCoded size : [" << p_video_format->coded_width << ", " << p_video_format->coded_height << "]" << std::endl << "\tDisplay area : [" << p_video_format->display_area.left << ", " << p_video_format->display_area.top << ", " @@ -634,7 +639,9 @@ int RocVideoDecoder::ReconfigureDecoder(RocdecVideoFormat *p_video_format) { input_video_info_str_ << std::endl; std::cout << input_video_info_str_.str(); - is_decoder_reconfigured_ = true; + if (is_decode_res_changed || is_bit_depth_changed) { + is_decoder_reconfigured_ = true; + } return 1; } diff --git a/projects/rocdecode/utils/rocvideodecode/roc_video_dec.h b/projects/rocdecode/utils/rocvideodecode/roc_video_dec.h index 3596530ece..b6700d4924 100644 --- a/projects/rocdecode/utils/rocvideodecode/roc_video_dec.h +++ b/projects/rocdecode/utils/rocvideodecode/roc_video_dec.h @@ -505,6 +505,7 @@ class RocVideoDecoder { uint32_t target_height_ = 0; int max_width_ = 0, max_height_ = 0; uint32_t chroma_height_ = 0, chroma_width_ = 0; + uint32_t num_decode_surfaces_ = 0; uint32_t num_chroma_planes_ = 0; uint32_t num_components_ = 0; uint32_t surface_stride_ = 0;