diff --git a/projects/rocdecode/CHANGELOG.md b/projects/rocdecode/CHANGELOG.md index a6d995fb4b..28e5703850 100644 --- a/projects/rocdecode/CHANGELOG.md +++ b/projects/rocdecode/CHANGELOG.md @@ -2,13 +2,14 @@ Full documentation for rocDecode is available at [https://rocm.docs.amd.com/projects/rocDecode/en/latest/](https://rocm.docs.amd.com/projects/rocDecode/en/latest/) -## (Unreleased) rocDecode 0.11.0 +## (Unreleased) rocDecode 0.11.1 ### Added * 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. ### Changed diff --git a/projects/rocdecode/CMakeLists.txt b/projects/rocdecode/CMakeLists.txt index ea89dec9d4..014cf03cb9 100644 --- a/projects/rocdecode/CMakeLists.txt +++ b/projects/rocdecode/CMakeLists.txt @@ -39,7 +39,7 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED On) # NOTE: Match version with api/rocdecode_version.h -set(VERSION "0.11.0") +set(VERSION "0.11.1") # Set Project Version and Language project(rocdecode VERSION ${VERSION} LANGUAGES CXX) diff --git a/projects/rocdecode/api/rocdecode.h b/projects/rocdecode/api/rocdecode.h index 5d78538776..2151617e7e 100644 --- a/projects/rocdecode/api/rocdecode.h +++ b/projects/rocdecode/api/rocdecode.h @@ -108,7 +108,10 @@ typedef enum rocDecVideoSurfaceFormat_enum { rocDecVideoSurfaceFormat_YUV444_16Bit = 3, /**< 16 bit Planar YUV [Y plane followed by U and V planes]. Can be used for 10 bit(6LSB bits 0), 12 bit (4LSB bits 0) */ rocDecVideoSurfaceFormat_YUV420 = 4, /**< Planar YUV [Y plane followed by U and V planes in 4:2:0 format] */ - rocDecVideoSurfaceFormat_YUV420_16Bit = 5, /**< 16 bit Planar YUV [Y plane followed by U and V planes in ]. + rocDecVideoSurfaceFormat_YUV420_16Bit = 5, /**< 16 bit Planar YUV [Y plane followed by U and V planes in 4:2:0 format]. + Can be used for 10 bit(LSB), 12 bit (LSB) */ + rocDecVideoSurfaceFormat_YUV422 = 6, /**< Planar YUV [Y plane followed by U and V planes in 4:2:2 format] */ + rocDecVideoSurfaceFormat_YUV422_16Bit = 7, /**< 16 bit Planar YUV [Y plane followed by U and V planes in 4:2:2 format]. Can be used for 10 bit(LSB), 12 bit (LSB) */ } rocDecVideoSurfaceFormat; @@ -227,7 +230,8 @@ typedef struct _RocdecReconfigureDecoderInfo { uint32_t target_width; /**< IN: Post processed output width */ uint32_t target_height; /**< IN: Post Processed output height */ uint32_t num_decode_surfaces; /**< IN: Maximum number of internal decode surfaces */ - uint32_t reserved_1[12]; /**< Reserved for future use. Set to Zero */ + uint32_t bit_depth_minus_8; /**< IN: The Value "BitDepth minus 8" */ + uint32_t reserved_1[11]; /**< Reserved for future use. Set to Zero */ struct { int16_t left; int16_t top; diff --git a/projects/rocdecode/api/rocdecode_version.h b/projects/rocdecode/api/rocdecode_version.h index e756ead06e..1ac8dfb56f 100644 --- a/projects/rocdecode/api/rocdecode_version.h +++ b/projects/rocdecode/api/rocdecode_version.h @@ -36,7 +36,7 @@ extern "C" { /* NOTE: Match version with CMakeLists.txt */ #define ROCDECODE_MAJOR_VERSION 0 #define ROCDECODE_MINOR_VERSION 11 -#define ROCDECODE_MICRO_VERSION 0 +#define ROCDECODE_MICRO_VERSION 1 /** diff --git a/projects/rocdecode/src/parser/hevc_parser.cpp b/projects/rocdecode/src/parser/hevc_parser.cpp index 7720ae1dbf..228307ed0a 100644 --- a/projects/rocdecode/src/parser/hevc_parser.cpp +++ b/projects/rocdecode/src/parser/hevc_parser.cpp @@ -1566,7 +1566,7 @@ ParserResult HevcVideoParser::ParseSliceHeader(uint8_t *nalu, size_t size, HevcS } // Check video dimension change - if ( pic_width_ != sps_ptr->pic_width_in_luma_samples || pic_height_ != sps_ptr->pic_height_in_luma_samples) { + if (pic_width_ != sps_ptr->pic_width_in_luma_samples || pic_height_ != sps_ptr->pic_height_in_luma_samples) { 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 @@ -1579,6 +1579,12 @@ ParserResult HevcVideoParser::ParseSliceHeader(uint8_t *nalu, size_t size, HevcS 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); } + // 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) { + bit_depth_luma_minus8_ = sps_ptr->bit_depth_luma_minus8; + bit_depth_chroma_minus8_ = sps_ptr->bit_depth_chroma_minus8; + new_seq_activated_ = true; + } // Set frame rate if available if (new_seq_activated_) { diff --git a/projects/rocdecode/src/parser/roc_video_parser.cpp b/projects/rocdecode/src/parser/roc_video_parser.cpp index 1feff90236..695d9e52ee 100644 --- a/projects/rocdecode/src/parser/roc_video_parser.cpp +++ b/projects/rocdecode/src/parser/roc_video_parser.cpp @@ -26,6 +26,8 @@ RocVideoParser::RocVideoParser() { pic_count_ = 0; pic_width_ = 0; pic_height_ = 0; + bit_depth_luma_minus8_ = 0; + bit_depth_chroma_minus8_ = 0; new_seq_activated_ = false; frame_rate_.numerator = 0; frame_rate_.denominator = 0; diff --git a/projects/rocdecode/src/parser/roc_video_parser.h b/projects/rocdecode/src/parser/roc_video_parser.h index 0af339a3fd..d5f9b12b37 100644 --- a/projects/rocdecode/src/parser/roc_video_parser.h +++ b/projects/rocdecode/src/parser/roc_video_parser.h @@ -138,6 +138,8 @@ protected: uint32_t pic_count_; // decoded picture count for the current bitstream uint32_t pic_width_; uint32_t pic_height_; + uint32_t bit_depth_luma_minus8_; + uint32_t bit_depth_chroma_minus8_; bool new_seq_activated_; // Decoded buffer pool diff --git a/projects/rocdecode/src/rocdecode/vaapi/vaapi_videodecoder.cpp b/projects/rocdecode/src/rocdecode/vaapi/vaapi_videodecoder.cpp index 88065af40e..c937729b90 100644 --- a/projects/rocdecode/src/rocdecode/vaapi/vaapi_videodecoder.cpp +++ b/projects/rocdecode/src/rocdecode/vaapi/vaapi_videodecoder.cpp @@ -340,6 +340,11 @@ rocDecStatus VaapiVideoDecoder::ReconfigureDecoder(RocdecReconfigureDecoderInfo } CHECK_VAAPI(vaDestroySurfaces(va_display_, va_surface_ids_.data(), va_surface_ids_.size())); CHECK_VAAPI(vaDestroyContext(va_display_, va_context_id_)); + // Need to re-create VA config if bit deepth changes + bool create_va_config = decoder_create_info_.bit_depth_minus_8 != reconfig_params->bit_depth_minus_8 ? true : false; + if (create_va_config) { + CHECK_VAAPI(vaDestroyConfig(va_display_, va_config_id_)); + } va_surface_ids_.clear(); decoder_create_info_.width = reconfig_params->width; @@ -347,8 +352,17 @@ rocDecStatus VaapiVideoDecoder::ReconfigureDecoder(RocdecReconfigureDecoderInfo decoder_create_info_.num_decode_surfaces = reconfig_params->num_decode_surfaces; decoder_create_info_.target_height = reconfig_params->target_height; decoder_create_info_.target_width = reconfig_params->target_width; + decoder_create_info_.bit_depth_minus_8 = reconfig_params->bit_depth_minus_8; - rocDecStatus rocdec_status = CreateSurfaces(); + rocDecStatus rocdec_status; + if (create_va_config) { + rocdec_status = CreateDecoderConfig(); + if (rocdec_status != ROCDEC_SUCCESS) { + ERR("Failed to create a VAAPI decoder configuration."); + return rocdec_status; + } + } + rocdec_status = CreateSurfaces(); if (rocdec_status != ROCDEC_SUCCESS) { ERR("Failed to create VAAPI surfaces during the decoder reconfiguration."); return rocdec_status; diff --git a/projects/rocdecode/utils/ffmpegvideodecode/ffmpeg_video_dec.cpp b/projects/rocdecode/utils/ffmpegvideodecode/ffmpeg_video_dec.cpp index c7ed32ed7f..93720ac675 100644 --- a/projects/rocdecode/utils/ffmpegvideodecode/ffmpeg_video_dec.cpp +++ b/projects/rocdecode/utils/ffmpegvideodecode/ffmpeg_video_dec.cpp @@ -49,14 +49,14 @@ static inline float GetChromaWidthFactor(rocDecVideoSurfaceFormat surface_format switch (surface_format) { case rocDecVideoSurfaceFormat_NV12: case rocDecVideoSurfaceFormat_P016: - factor = 1.0; - break; case rocDecVideoSurfaceFormat_YUV444: case rocDecVideoSurfaceFormat_YUV444_16Bit: factor = 1.0; break; case rocDecVideoSurfaceFormat_YUV420: case rocDecVideoSurfaceFormat_YUV420_16Bit: + case rocDecVideoSurfaceFormat_YUV422: + case rocDecVideoSurfaceFormat_YUV422_16Bit: factor = 0.5; break; } diff --git a/projects/rocdecode/utils/rocvideodecode/roc_video_dec.cpp b/projects/rocdecode/utils/rocvideodecode/roc_video_dec.cpp index 31654cc822..e34a98bfa2 100644 --- a/projects/rocdecode/utils/rocvideodecode/roc_video_dec.cpp +++ b/projects/rocdecode/utils/rocvideodecode/roc_video_dec.cpp @@ -222,7 +222,14 @@ static void GetSurfaceStrideInternal(rocDecVideoSurfaceFormat surface_format, ui *pitch = align(width, 128) * 2; *vstride = align(height, 16); break; - + case rocDecVideoSurfaceFormat_YUV422: + *pitch = align(width, 256); + *vstride = align(height, 16); + break; + case rocDecVideoSurfaceFormat_YUV422_16Bit: + *pitch = align(width, 128) * 2; + *vstride = align(height, 16); + break; } return; } @@ -298,7 +305,7 @@ int RocVideoDecoder::HandleVideoSequence(RocdecVideoFormat *p_video_format) { else if (video_chroma_format_ == rocDecVideoChromaFormat_444) video_surface_format_ = bitdepth_minus_8_ ? rocDecVideoSurfaceFormat_YUV444_16Bit : rocDecVideoSurfaceFormat_YUV444; else if (video_chroma_format_ == rocDecVideoChromaFormat_422) - video_surface_format_ = rocDecVideoSurfaceFormat_NV12; + video_surface_format_ = bitdepth_minus_8_ ? rocDecVideoSurfaceFormat_YUV422_16Bit : rocDecVideoSurfaceFormat_YUV422; // Check if output format supported. If not, check falback options if (!(decode_caps.output_format_mask & (1 << video_surface_format_))){ @@ -469,17 +476,13 @@ int RocVideoDecoder::ReconfigureDecoder(RocdecVideoFormat *p_video_format) { ROCDEC_THROW("Reconfigure Not supported for chroma format change", ROCDEC_NOT_SUPPORTED); return 0; } - if (p_video_format->bit_depth_luma_minus8 != bitdepth_minus_8_){ - ROCDEC_THROW("Reconfigure Not supported for bit depth 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); - - if (!is_decode_res_changed && !is_display_rect_changed && !b_force_recofig_flush_) { + 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_) { return 1; } @@ -527,6 +530,18 @@ int RocVideoDecoder::ReconfigureDecoder(RocdecVideoFormat *p_video_format) { target_height_ = (crop_rect_.bottom - crop_rect_.top + 1) & ~1; } } + if (is_bit_depth_changed) { + bitdepth_minus_8_ = p_video_format->bit_depth_luma_minus8; + byte_per_pixel_ = bitdepth_minus_8_ > 0 ? 2 : 1; + + // Set the output surface format same as chroma format + if (video_chroma_format_ == rocDecVideoChromaFormat_420 || video_chroma_format_ == rocDecVideoChromaFormat_Monochrome) + video_surface_format_ = bitdepth_minus_8_ ? rocDecVideoSurfaceFormat_P016 : rocDecVideoSurfaceFormat_NV12; + else if (video_chroma_format_ == rocDecVideoChromaFormat_444) + video_surface_format_ = bitdepth_minus_8_ ? rocDecVideoSurfaceFormat_YUV444_16Bit : rocDecVideoSurfaceFormat_YUV444; + else if (video_chroma_format_ == rocDecVideoChromaFormat_422) + video_surface_format_ = bitdepth_minus_8_ ? rocDecVideoSurfaceFormat_YUV422_16Bit : rocDecVideoSurfaceFormat_YUV422; + } 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) { @@ -568,7 +583,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) { + if (!is_decode_res_changed && is_display_rect_changed && !is_bit_depth_changed) { return 1; } @@ -577,6 +592,7 @@ int RocVideoDecoder::ReconfigureDecoder(RocdecVideoFormat *p_video_format) { reconfig_params.height = coded_height_; reconfig_params.target_width = target_width_; reconfig_params.target_height = target_height_; + reconfig_params.bit_depth_minus_8 = bitdepth_minus_8_; reconfig_params.num_decode_surfaces = p_video_format->min_num_decode_surfaces; if (!(crop_rect_.right && crop_rect_.bottom)) { reconfig_params.display_rect.top = disp_rect_.top; @@ -600,10 +616,16 @@ int RocVideoDecoder::ReconfigureDecoder(RocdecVideoFormat *p_video_format) { input_video_info_str_.str(""); input_video_info_str_.clear(); - input_video_info_str_ << "Input Video Resolution Changed:" << std::endl - << "\tCoded size : [" << p_video_format->coded_width << ", " << p_video_format->coded_height << "]" << std::endl + if (is_decode_res_changed) { + input_video_info_str_ << "Input Video Resolution Changed:" << std::endl; + } + if (is_bit_depth_changed) { + input_video_info_str_ << "Input Video Bit Depth 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 << ", " << p_video_format->display_area.right << ", " << p_video_format->display_area.bottom << "]" << std::endl; + input_video_info_str_ << "\tBit depth : " << reconfig_params.bit_depth_minus_8 + 8 << std::endl; input_video_info_str_ << std::endl; input_video_info_str_ << "Video Decoding Params:" << std::endl << "\tNum Surfaces : " << reconfig_params.num_decode_surfaces << std::endl @@ -947,7 +969,7 @@ void RocVideoDecoder::SaveFrameToFile(std::string output_file_name, void *surf_m if (!current_output_filename.compare(output_file_name)) { std::string::size_type const pos(output_file_name.find_last_of('.')); extra_output_file_count_++; - std::string to_append = "_" + std::to_string(surf_info->output_width) + "_" + std::to_string(surf_info->output_height) + "_" + std::to_string(extra_output_file_count_); + std::string to_append = "_" + std::to_string(surf_info->output_width) + "_" + std::to_string(surf_info->output_height) + "_" + std::to_string(surf_info->bit_depth) + "bit" + "_" + std::to_string(extra_output_file_count_); if (pos != std::string::npos) { output_file_name.insert(pos, to_append); } else { diff --git a/projects/rocdecode/utils/rocvideodecode/roc_video_dec.h b/projects/rocdecode/utils/rocvideodecode/roc_video_dec.h index 022beb074e..7e4685e47f 100644 --- a/projects/rocdecode/utils/rocvideodecode/roc_video_dec.h +++ b/projects/rocdecode/utils/rocvideodecode/roc_video_dec.h @@ -83,10 +83,10 @@ inline int GetChromaPlaneCount(rocDecVideoSurfaceFormat surface_format) { break; case rocDecVideoSurfaceFormat_YUV444: case rocDecVideoSurfaceFormat_YUV444_16Bit: - num_planes = 2; - break; case rocDecVideoSurfaceFormat_YUV420: case rocDecVideoSurfaceFormat_YUV420_16Bit: + case rocDecVideoSurfaceFormat_YUV422: + case rocDecVideoSurfaceFormat_YUV422_16Bit: num_planes = 2; break; } @@ -103,6 +103,8 @@ inline float GetChromaHeightFactor(rocDecVideoSurfaceFormat surface_format) { case rocDecVideoSurfaceFormat_YUV420_16Bit: factor = 0.5; break; + case rocDecVideoSurfaceFormat_YUV422: + case rocDecVideoSurfaceFormat_YUV422_16Bit: case rocDecVideoSurfaceFormat_YUV444: case rocDecVideoSurfaceFormat_YUV444_16Bit: factor = 1.0;