From d9c9d65e48d78a48b4328e7781949846c18fb2b0 Mon Sep 17 00:00:00 2001 From: Jeff Jiang Date: Tue, 17 Mar 2026 11:53:54 -0400 Subject: [PATCH 1/8] * rocDecode feature: Remove dependency of output surface format on the coded stream and allow user to surface format of lower bit depth. - On 10 bit and up streams, the user can set output surface to 8 bit. - Added output format parameter to decoder reconfigure API. - Added output surface format command option to rocdecdecode sample. --- projects/rocdecode/api/rocdecode/rocdecode.h | 3 +- .../samples/rocdecDecode/rocdecdecode.cpp | 105 ++++++++++++++---- .../rocdecode/src/rocdecode/rocdecode_api.cpp | 47 ++++++++ .../rocdecode/vaapi/vaapi_videodecoder.cpp | 27 +++-- 4 files changed, 152 insertions(+), 30 deletions(-) diff --git a/projects/rocdecode/api/rocdecode/rocdecode.h b/projects/rocdecode/api/rocdecode/rocdecode.h index 56038355abbe..945be29615a5 100644 --- a/projects/rocdecode/api/rocdecode/rocdecode.h +++ b/projects/rocdecode/api/rocdecode/rocdecode.h @@ -230,7 +230,8 @@ typedef struct _RocdecReconfigureDecoderInfo { uint32_t target_height; /**< IN: Post Processed output height */ uint32_t num_decode_surfaces; /**< IN: Maximum number of internal decode surfaces */ uint32_t bit_depth_minus_8; /**< IN: The Value "BitDepth minus 8" */ - uint32_t reserved_1[11]; /**< Reserved for future use. Set to Zero */ + rocDecVideoSurfaceFormat output_format; /**< IN: rocDecVideoSurfaceFormat_XXX */ + uint32_t reserved_1[10]; /**< Reserved for future use. Set to Zero */ struct { int16_t left; int16_t top; diff --git a/projects/rocdecode/samples/rocdecDecode/rocdecdecode.cpp b/projects/rocdecode/samples/rocdecDecode/rocdecdecode.cpp index 2431a9357606..f8751883dfc2 100644 --- a/projects/rocdecode/samples/rocdecDecode/rocdecdecode.cpp +++ b/projects/rocdecode/samples/rocdecDecode/rocdecdecode.cpp @@ -147,6 +147,7 @@ typedef enum DecoderBackend_enum { } \ } while (false) + /** * @brief Struct containing all the information for decoding and displaying output * @@ -162,6 +163,7 @@ struct DecoderInfo { std::string output_file_path; OutputSurfaceMemoryType mem_type; rocDecVideoSurfaceFormat surf_format; + bool output_format_override; // true: user set output surface format; false: output surface format is determined by the coded stream rocDecVideoSurfaceFormat video_chroma_format; uint32_t coded_width, coded_height; uint32_t bytes_per_pixel; @@ -169,7 +171,8 @@ struct DecoderInfo { Rect disp_rect; FILE *fp_out; DecoderInfo() : dec_device_id(0), backend(DECODER_BACKEND_DEVICE), decoder(nullptr), bit_depth(8), dump_decoded_frames(0), mem_type{OUT_SURFACE_MEM_DEV_INTERNAL}, - surf_format{rocDecVideoSurfaceFormat_NV12}, video_chroma_format{rocDecVideoSurfaceFormat_NV12}, + surf_format{rocDecVideoSurfaceFormat_NV12}, output_format_override{false}, + video_chroma_format{rocDecVideoSurfaceFormat_NV12}, is_decoder_reconfigured{false}, fp_out{nullptr} {} }; @@ -181,7 +184,6 @@ struct DecoderInfo { * @param pitch stride in bytes of luma and chroma planes */ void save_frame_to_file(DecoderInfo *p_dec_info, void *surf_mem[], uint32_t *pitch) { - uint8_t *hst_ptr = nullptr; uint64_t output_image_size_luma = pitch[0] * p_dec_info->coded_height; uint64_t output_image_size_chroma = pitch[1] * ((p_dec_info->coded_height * GetChromaHeightFactor(p_dec_info->surf_format))); @@ -357,7 +359,7 @@ void create_decoder(DecoderInfo& dec_info) { create_info.display_rect.right = static_cast(DEFAULT_WIDTH); create_info.display_rect.top = 0; create_info.display_rect.bottom = static_cast(DEFAULT_HEIGHT); - // for decode creation: assuming chroma_format is 4:2:0 and output_format is NV12. + // for decode creation: assuming chroma_format is 4:2:0 and output_format is NV12 unless overridden by user. // video dimensions ( width, height, max_width, max_height), num_decode_surfaces, and bit_depth_minus_8 are hardcoded here // this will get changed in reconfigure when the sequence header is parsed from the stream to detect the actual video parameters create_info.chroma_format = rocDecVideoChromaFormat_420; @@ -463,9 +465,49 @@ int ROCDECAPI handle_video_sequence(void* user_data, RocdecVideoFormat* format) int bitdepth_minus_8 = format->bit_depth_luma_minus8; uint32_t target_width = (format->display_area.right - format->display_area.left + 1) & ~1; uint32_t target_height = (format->display_area.bottom - format->display_area.top + 1) & ~1; + + p_dec_info->is_decoder_reconfigured = true; + p_dec_info->disp_rect.top = format->display_area.top; + p_dec_info->disp_rect.bottom = format->display_area.bottom; + p_dec_info->disp_rect.left = format->display_area.left; + p_dec_info->disp_rect.right = format->display_area.right; + if (p_dec_info->output_format_override) { + switch (p_dec_info->surf_format) { + case rocDecVideoSurfaceFormat_NV12: + case rocDecVideoSurfaceFormat_YUV420: + case rocDecVideoSurfaceFormat_YUV422: + case rocDecVideoSurfaceFormat_YUV444: + p_dec_info->bytes_per_pixel = 1; + p_dec_info->bit_depth = 8; + break; + + case rocDecVideoSurfaceFormat_P016: + case rocDecVideoSurfaceFormat_YUV420_16Bit: + case rocDecVideoSurfaceFormat_YUV444_16Bit: + case rocDecVideoSurfaceFormat_YUV422_16Bit: + p_dec_info->bytes_per_pixel = 2; + p_dec_info->bit_depth = bitdepth_minus_8 + 8; + break; + } + } else { + rocDecVideoChromaFormat video_chroma_format = format->chroma_format; + if (video_chroma_format == rocDecVideoChromaFormat_420 || rocDecVideoChromaFormat_Monochrome) + p_dec_info->surf_format = bitdepth_minus_8 ? rocDecVideoSurfaceFormat_P016 : rocDecVideoSurfaceFormat_NV12; + else if (video_chroma_format == rocDecVideoChromaFormat_444) + p_dec_info->surf_format = bitdepth_minus_8 ? rocDecVideoSurfaceFormat_YUV444_16Bit : rocDecVideoSurfaceFormat_YUV444; + else if (video_chroma_format == rocDecVideoChromaFormat_422) + p_dec_info->surf_format = bitdepth_minus_8 ? rocDecVideoSurfaceFormat_YUV422_16Bit : rocDecVideoSurfaceFormat_YUV422; + + p_dec_info->bytes_per_pixel = bitdepth_minus_8 > 0 ? 2 : 1; + p_dec_info->bit_depth = bitdepth_minus_8 + 8; + } + p_dec_info->coded_width = format->coded_width; + p_dec_info->coded_height = format->coded_height; + reconfig_params.width = format->coded_width; reconfig_params.height = format->coded_height; reconfig_params.bit_depth_minus_8 = bitdepth_minus_8; + reconfig_params.output_format = p_dec_info->surf_format; reconfig_params.num_decode_surfaces = format->min_num_decode_surfaces; reconfig_params.target_width = target_width; reconfig_params.target_height = target_height; @@ -474,21 +516,7 @@ int ROCDECAPI handle_video_sequence(void* user_data, RocdecVideoFormat* format) reconfig_params.display_rect.top = format->display_area.top; reconfig_params.display_rect.bottom = format->display_area.bottom; CHECK(rocDecReconfigureDecoder(p_dec_info->decoder, &reconfig_params)); - p_dec_info->is_decoder_reconfigured = true; - p_dec_info->disp_rect.top = format->display_area.top; - p_dec_info->disp_rect.bottom = format->display_area.bottom; - p_dec_info->disp_rect.left = format->display_area.left; - p_dec_info->disp_rect.right = format->display_area.right; - rocDecVideoChromaFormat video_chroma_format = format->chroma_format; - if (video_chroma_format == rocDecVideoChromaFormat_420 || rocDecVideoChromaFormat_Monochrome) - p_dec_info->surf_format = bitdepth_minus_8 ? rocDecVideoSurfaceFormat_P016 : rocDecVideoSurfaceFormat_NV12; - else if (video_chroma_format == rocDecVideoChromaFormat_444) - p_dec_info->surf_format = bitdepth_minus_8 ? rocDecVideoSurfaceFormat_YUV444_16Bit : rocDecVideoSurfaceFormat_YUV444; - else if (video_chroma_format == rocDecVideoChromaFormat_422) - p_dec_info->surf_format = bitdepth_minus_8 ? rocDecVideoSurfaceFormat_YUV422_16Bit : rocDecVideoSurfaceFormat_YUV422; - p_dec_info->coded_width = format->coded_width; - p_dec_info->coded_height = format->coded_height; - p_dec_info->bytes_per_pixel = bitdepth_minus_8 > 0 ? 2 : 1; + std::ostringstream input_video_info_str; input_video_info_str.str(""); input_video_info_str.clear(); @@ -603,6 +631,9 @@ void ShowHelpAndExit(const char *option = NULL) { #endif << "-c codec (0 : HEVC, 1 : H264, 2: AV1, 4: VP9, 5: VP8 ); optional; default: 0" << std::endl << "-n Number of iteration - specify the number of iterations for performance evaluation; optional; default: 1" << std::endl + << "-f Number of decoded frames - specify the number of pictures to be decoded; optional" << std::endl + << "-o_format Output surface format; optional; default: auto-detected from stream" + << " [NV12, P016, YUV444, YUV444_16Bit, YUV422, YUV422_16Bit, YUV420, YUV420_16Bit]" << std::endl << "-m output_surface_memory_type - decoded surface memory; optional; default - 0" << " [0 : OUT_SURFACE_MEM_DEV_INTERNAL/ 1 : OUT_SURFACE_MEM_DEV_COPIED/ 2 : OUT_SURFACE_MEM_HOST_COPIED/ 3 : OUT_SURFACE_MEM_NOT_MAPPED]" << std::endl; exit(0); @@ -641,13 +672,25 @@ bool compareFilenames(const std::string& a, const std::string& b) { return a < b; // Fallback to lexicographical comparison }; -int main(int argc, char** argv) { +static inline bool ParseOutputFormat(const char *str, rocDecVideoSurfaceFormat *surface_format) { + if (!strcmp(str, "NV12")) { *surface_format = rocDecVideoSurfaceFormat_NV12; return true; } + if (!strcmp(str, "P016")) { *surface_format = rocDecVideoSurfaceFormat_P016; return true; } + if (!strcmp(str, "YUV444")) { *surface_format = rocDecVideoSurfaceFormat_YUV444; return true; } + if (!strcmp(str, "YUV444_16Bit")) { *surface_format = rocDecVideoSurfaceFormat_YUV444_16Bit; return true; } + if (!strcmp(str, "YUV422")) { *surface_format = rocDecVideoSurfaceFormat_YUV422; return true; } + if (!strcmp(str, "YUV422_16Bit")) { *surface_format = rocDecVideoSurfaceFormat_YUV422_16Bit; return true; } + if (!strcmp(str, "YUV420")) { *surface_format = rocDecVideoSurfaceFormat_YUV420; return true; } + if (!strcmp(str, "YUV420_16Bit")) { *surface_format = rocDecVideoSurfaceFormat_YUV420_16Bit; return true; } + return false; // unrecognised +} +int main(int argc, char** argv) { std::string input_file_path, output_file_path; int dump_output_frames = 0; int device_id = 0; DecoderBackend backend = DECODER_BACKEND_DEVICE; - int num_iterations = 1; + int num_iterations = 1; + uint32_t num_decoded_frames = 0; // default value is 0, meaning decode all frames std::vector input_file_names; int codec_type = 0; // default for HEVC DecoderInfo dec_info; @@ -734,6 +777,24 @@ int main(int argc, char** argv) { num_iterations = atoi(argv[i]); continue; } + if (!strcmp(argv[i], "-f")) { + if (++i == argc) { + ShowHelpAndExit("-f"); + } + num_decoded_frames = atoi(argv[i]); + continue; + } + if (!strcmp(argv[i], "-o_format")) { + if (++i == argc) { + ShowHelpAndExit("-o_format"); + } + dec_info.output_format_override = ParseOutputFormat(argv[i], &dec_info.surf_format); + if (!dec_info.output_format_override) { + std::cerr << "Unknown output format: " << argv[i] << std::endl; + ShowHelpAndExit("-o_format"); + } + continue; + } ShowHelpAndExit(argv[i]); } dec_info.rocdec_codec_id = CodecTypeToRocDecVideoCodec(codec_type); @@ -750,10 +811,14 @@ int main(int argc, char** argv) { } #endif dec_info.dump_decoded_frames = dump_output_frames; + if (num_decoded_frames && num_decoded_frames < input_file_names.size()) { + input_file_names.resize(num_decoded_frames); + } auto input_frames = read_frames(input_file_names); auto start = std::chrono::high_resolution_clock::now(); for (int i = 0; i < num_iterations; i++) { decode_frames(dec_info, input_frames); + std::cout << "Total decoded frames in iteration " << i << ": " << input_frames.size() << std::endl; } auto end = std::chrono::high_resolution_clock::now(); auto elapsed = std::chrono::duration_cast(end - start).count(); diff --git a/projects/rocdecode/src/rocdecode/rocdecode_api.cpp b/projects/rocdecode/src/rocdecode/rocdecode_api.cpp index 463cc53ad3c8..46c34cb83541 100644 --- a/projects/rocdecode/src/rocdecode/rocdecode_api.cpp +++ b/projects/rocdecode/src/rocdecode/rocdecode_api.cpp @@ -27,6 +27,47 @@ THE SOFTWARE. namespace rocdecode { RocDecLogger logger; +/*****************************************************************************************************/ +//! \fn static void AdjustOutputFormatToBitDepth(rocDecVideoSurfaceFormat &output_format, uint32_t bit_depth_minus_8) +//! Validates that the bit depth of output_format does not exceed bit_depth_minus_8 + 8. A 16-bit +//! output format requires bit_depth_minus_8 > 0 since its bit depth (16) would exceed that of 8-bit +//! content. An 8-bit output format is always valid regardless of bit_depth_minus_8. If an incompatible +//! 16-bit format is detected for 8-bit content, a warning is logged and output_format is set to the +//! corresponding 8-bit format. +/*****************************************************************************************************/ +static void ValidateOutputFormat(rocDecVideoSurfaceFormat &output_format, uint32_t bit_depth_minus_8) { + if (bit_depth_minus_8 > 0) { + return; // 16-bit output formats are valid for content with bit depth > 8 + } + + // Content is 8-bit; a 16-bit output format would exceed the content bit depth. + rocDecVideoSurfaceFormat adjusted = output_format; + switch (output_format) { + case rocDecVideoSurfaceFormat_P016: + adjusted = rocDecVideoSurfaceFormat_NV12; + break; + case rocDecVideoSurfaceFormat_YUV444_16Bit: + adjusted = rocDecVideoSurfaceFormat_YUV444; + break; + case rocDecVideoSurfaceFormat_YUV420_16Bit: + adjusted = rocDecVideoSurfaceFormat_YUV420; + break; + case rocDecVideoSurfaceFormat_YUV422_16Bit: + adjusted = rocDecVideoSurfaceFormat_YUV422; + break; + default: + break; // already an 8-bit format, no adjustment needed + } + + if (adjusted != output_format) { + logger.WarningLog(MakeMsg("output_format (" + TOSTR(static_cast(output_format)) + + ") bit depth exceeds content bit depth (bit_depth_minus_8=" + + TOSTR(bit_depth_minus_8) + "). Adjusting output_format to " + + TOSTR(static_cast(adjusted)) + ".")); + output_format = adjusted; + } +} + /*****************************************************************************************************/ //! \fn rocDecStatus ROCDECAPI rocDecCreateDecoder(rocDecDecoderHandle *decoder_handle, RocDecoderCreateInfo *decoder_create_info) //! Create the decoder object based on decoder_create_info. A handle to the created decoder is returned @@ -39,6 +80,9 @@ rocDecCreateDecoder(rocDecDecoderHandle *decoder_handle, RocDecoderCreateInfo *d FunctionExitLog(logger); return ROCDEC_INVALID_PARAMETER; } + + ValidateOutputFormat(decoder_create_info->output_format, decoder_create_info->bit_depth_minus_8); + rocDecDecoderHandle handle = nullptr; try { handle = new DecHandle(*decoder_create_info); @@ -165,6 +209,9 @@ rocDecReconfigureDecoder(rocDecDecoderHandle decoder_handle, RocdecReconfigureDe return ROCDEC_INVALID_PARAMETER; } auto handle = static_cast(decoder_handle); + + ValidateOutputFormat(reconfig_params->output_format, reconfig_params->bit_depth_minus_8); + rocDecStatus ret; try { ret = handle->roc_decoder_->ReconfigureDecoder(reconfig_params); diff --git a/projects/rocdecode/src/rocdecode/vaapi/vaapi_videodecoder.cpp b/projects/rocdecode/src/rocdecode/vaapi/vaapi_videodecoder.cpp index 447cb9560928..38c000b5c11c 100644 --- a/projects/rocdecode/src/rocdecode/vaapi/vaapi_videodecoder.cpp +++ b/projects/rocdecode/src/rocdecode/vaapi/vaapi_videodecoder.cpp @@ -375,6 +375,7 @@ rocDecStatus VaapiVideoDecoder::ReconfigureDecoder(RocdecReconfigureDecoderInfo 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; + decoder_create_info_.output_format = reconfig_params->output_format; rocDecStatus rocdec_status; if (create_va_config) { @@ -480,21 +481,29 @@ rocDecStatus VaapiVideoDecoder::CreateSurfaces() { surf_attrib.value.type = VAGenericValueTypeInteger; uint32_t surface_format; switch (decoder_create_info_.chroma_format) { - case rocDecVideoChromaFormat_Monochrome: + case rocDecVideoChromaFormat_Monochrome: { surface_format = VA_RT_FORMAT_YUV400; surf_attrib.value.value.i = VA_FOURCC_Y800; + } break; - case rocDecVideoChromaFormat_420: - if (decoder_create_info_.bit_depth_minus_8 == 2) { - surface_format = VA_RT_FORMAT_YUV420_10; - surf_attrib.value.value.i = VA_FOURCC_P010; - } else if (decoder_create_info_.bit_depth_minus_8 == 4) { - surface_format = VA_RT_FORMAT_YUV420_12; - surf_attrib.value.value.i = VA_FOURCC_P012; - } else { + case rocDecVideoChromaFormat_420: { + // Special case for 8-bit output requirement even when the stream is 10-bit and above + if (decoder_create_info_.output_format == rocDecVideoSurfaceFormat_NV12) { surface_format = VA_RT_FORMAT_YUV420; surf_attrib.value.value.i = VA_FOURCC_NV12; + } else { + if (decoder_create_info_.bit_depth_minus_8 == 2) { + surface_format = VA_RT_FORMAT_YUV420_10; + surf_attrib.value.value.i = VA_FOURCC_P010; + } else if (decoder_create_info_.bit_depth_minus_8 == 4) { + surface_format = VA_RT_FORMAT_YUV420_12; + surf_attrib.value.value.i = VA_FOURCC_P012; + } else { + surface_format = VA_RT_FORMAT_YUV420; + surf_attrib.value.value.i = VA_FOURCC_NV12; + } } + } break; case rocDecVideoChromaFormat_422: surface_format = VA_RT_FORMAT_YUV422; From 7f40b73fef3647a9bb42e26dab96558b57cb6484 Mon Sep 17 00:00:00 2001 From: Jeff Jiang Date: Thu, 19 Mar 2026 13:20:13 -0400 Subject: [PATCH 2/8] * rocDecode/Output format: Removed the output format paramter from decoder reconfig API to avoid potentially breaking the current user workflow. Added a new output surface format to indicate that the output surface format is determined by the stream content. --- projects/rocdecode/api/rocdecode/rocdecode.h | 5 +- .../samples/rocdecDecode/rocdecdecode.cpp | 38 ++++++--- .../rocdecode/src/rocdecode/rocdecode_api.cpp | 47 ----------- .../rocdecode/vaapi/vaapi_videodecoder.cpp | 78 ++++++++++++++++++- .../src/rocdecode/vaapi/vaapi_videodecoder.h | 4 + .../ffmpegvideodecode/ffmpeg_video_dec.cpp | 1 + .../utils/rocvideodecode/roc_video_dec.cpp | 4 +- .../utils/rocvideodecode/roc_video_dec.h | 2 + 8 files changed, 115 insertions(+), 64 deletions(-) diff --git a/projects/rocdecode/api/rocdecode/rocdecode.h b/projects/rocdecode/api/rocdecode/rocdecode.h index 945be29615a5..1379fa9f0057 100644 --- a/projects/rocdecode/api/rocdecode/rocdecode.h +++ b/projects/rocdecode/api/rocdecode/rocdecode.h @@ -112,6 +112,8 @@ typedef enum rocDecVideoSurfaceFormat_enum { 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_Native = 0xFF, /**< Output format is determined by the coded stream parameters (chroma format + and bit depth). The decoder selects the appropriate surface format automatically. */ } rocDecVideoSurfaceFormat; /**************************************************************************************************************/ @@ -230,8 +232,7 @@ typedef struct _RocdecReconfigureDecoderInfo { uint32_t target_height; /**< IN: Post Processed output height */ uint32_t num_decode_surfaces; /**< IN: Maximum number of internal decode surfaces */ uint32_t bit_depth_minus_8; /**< IN: The Value "BitDepth minus 8" */ - rocDecVideoSurfaceFormat output_format; /**< IN: rocDecVideoSurfaceFormat_XXX */ - uint32_t reserved_1[10]; /**< Reserved for future use. Set to Zero */ + uint32_t reserved_1[11]; /**< Reserved for future use. Set to Zero */ struct { int16_t left; int16_t top; diff --git a/projects/rocdecode/samples/rocdecDecode/rocdecdecode.cpp b/projects/rocdecode/samples/rocdecDecode/rocdecdecode.cpp index f8751883dfc2..5013a40a0ca7 100644 --- a/projects/rocdecode/samples/rocdecDecode/rocdecdecode.cpp +++ b/projects/rocdecode/samples/rocdecDecode/rocdecdecode.cpp @@ -89,6 +89,8 @@ static inline float GetChromaHeightFactor(rocDecVideoSurfaceFormat surface_forma case rocDecVideoSurfaceFormat_YUV444_16Bit: factor = 1.0; break; + default: + break; } return factor; @@ -120,6 +122,8 @@ static inline float GetChromaWidthFactor(rocDecVideoSurfaceFormat surface_format case rocDecVideoSurfaceFormat_YUV422_16Bit: factor = 0.5; break; + default: + break; } return factor; }; @@ -164,7 +168,7 @@ struct DecoderInfo { OutputSurfaceMemoryType mem_type; rocDecVideoSurfaceFormat surf_format; bool output_format_override; // true: user set output surface format; false: output surface format is determined by the coded stream - rocDecVideoSurfaceFormat video_chroma_format; + rocDecVideoChromaFormat video_chroma_format; uint32_t coded_width, coded_height; uint32_t bytes_per_pixel; bool is_decoder_reconfigured; @@ -172,7 +176,7 @@ struct DecoderInfo { FILE *fp_out; DecoderInfo() : dec_device_id(0), backend(DECODER_BACKEND_DEVICE), decoder(nullptr), bit_depth(8), dump_decoded_frames(0), mem_type{OUT_SURFACE_MEM_DEV_INTERNAL}, surf_format{rocDecVideoSurfaceFormat_NV12}, output_format_override{false}, - video_chroma_format{rocDecVideoSurfaceFormat_NV12}, + video_chroma_format{rocDecVideoChromaFormat_420}, is_decoder_reconfigured{false}, fp_out{nullptr} {} }; @@ -323,7 +327,7 @@ std::vector> read_frames(std::vector& names) { std::cerr << "Error opening " << name << " for reading." << std::endl; std::abort(); } - std::cout << "Reading " << name << " for reading." << std::endl; + //std::cout << "Reading " << name << " for reading." << std::endl; // Determine the file size inputFile.seekg(0, std::ios::end); std::streamsize fileSize = inputFile.tellg(); @@ -363,8 +367,21 @@ void create_decoder(DecoderInfo& dec_info) { // video dimensions ( width, height, max_width, max_height), num_decode_surfaces, and bit_depth_minus_8 are hardcoded here // this will get changed in reconfigure when the sequence header is parsed from the stream to detect the actual video parameters create_info.chroma_format = rocDecVideoChromaFormat_420; - create_info.output_format = rocDecVideoSurfaceFormat_NV12; - create_info.bit_depth_minus_8 = 0; + if (dec_info.output_format_override) { + create_info.output_format = dec_info.surf_format; + if (create_info.output_format == rocDecVideoSurfaceFormat_P016) { + create_info.bit_depth_minus_8 = 2; + } else { + create_info.bit_depth_minus_8 = 0; + } + } else { + // Default setting + create_info.output_format = rocDecVideoSurfaceFormat_Native; + create_info.bit_depth_minus_8 = 0; + dec_info.surf_format = create_info.output_format; + dec_info.bit_depth = create_info.bit_depth_minus_8 + 8; + dec_info.bytes_per_pixel = (dec_info.bit_depth + 7) / 8; + } create_info.num_output_surfaces = 1; CHECK(rocDecCreateDecoder(&dec_info.decoder, &create_info)); } @@ -488,6 +505,8 @@ int ROCDECAPI handle_video_sequence(void* user_data, RocdecVideoFormat* format) p_dec_info->bytes_per_pixel = 2; p_dec_info->bit_depth = bitdepth_minus_8 + 8; break; + default: + break; } } else { rocDecVideoChromaFormat video_chroma_format = format->chroma_format; @@ -507,7 +526,6 @@ int ROCDECAPI handle_video_sequence(void* user_data, RocdecVideoFormat* format) reconfig_params.width = format->coded_width; reconfig_params.height = format->coded_height; reconfig_params.bit_depth_minus_8 = bitdepth_minus_8; - reconfig_params.output_format = p_dec_info->surf_format; reconfig_params.num_decode_surfaces = format->min_num_decode_surfaces; reconfig_params.target_width = target_width; reconfig_params.target_height = target_height; @@ -632,8 +650,7 @@ void ShowHelpAndExit(const char *option = NULL) { << "-c codec (0 : HEVC, 1 : H264, 2: AV1, 4: VP9, 5: VP8 ); optional; default: 0" << std::endl << "-n Number of iteration - specify the number of iterations for performance evaluation; optional; default: 1" << std::endl << "-f Number of decoded frames - specify the number of pictures to be decoded; optional" << std::endl - << "-o_format Output surface format; optional; default: auto-detected from stream" - << " [NV12, P016, YUV444, YUV444_16Bit, YUV422, YUV422_16Bit, YUV420, YUV420_16Bit]" << std::endl + << "-o_format Output surface format; optional; default: auto-detected from stream, [NV12, P016]" << std::endl << "-m output_surface_memory_type - decoded surface memory; optional; default - 0" << " [0 : OUT_SURFACE_MEM_DEV_INTERNAL/ 1 : OUT_SURFACE_MEM_DEV_COPIED/ 2 : OUT_SURFACE_MEM_HOST_COPIED/ 3 : OUT_SURFACE_MEM_NOT_MAPPED]" << std::endl; exit(0); @@ -675,12 +692,14 @@ bool compareFilenames(const std::string& a, const std::string& b) { static inline bool ParseOutputFormat(const char *str, rocDecVideoSurfaceFormat *surface_format) { if (!strcmp(str, "NV12")) { *surface_format = rocDecVideoSurfaceFormat_NV12; return true; } if (!strcmp(str, "P016")) { *surface_format = rocDecVideoSurfaceFormat_P016; return true; } + #if 0 if (!strcmp(str, "YUV444")) { *surface_format = rocDecVideoSurfaceFormat_YUV444; return true; } if (!strcmp(str, "YUV444_16Bit")) { *surface_format = rocDecVideoSurfaceFormat_YUV444_16Bit; return true; } if (!strcmp(str, "YUV422")) { *surface_format = rocDecVideoSurfaceFormat_YUV422; return true; } if (!strcmp(str, "YUV422_16Bit")) { *surface_format = rocDecVideoSurfaceFormat_YUV422_16Bit; return true; } if (!strcmp(str, "YUV420")) { *surface_format = rocDecVideoSurfaceFormat_YUV420; return true; } if (!strcmp(str, "YUV420_16Bit")) { *surface_format = rocDecVideoSurfaceFormat_YUV420_16Bit; return true; } + #endif return false; // unrecognised } @@ -734,8 +753,6 @@ int main(int argc, char** argv) { } else { input_file_names.push_back(input_file_path); } - - std::cout << "Read " << input_file_names.size() << " frames from disk." << std::endl; continue; } if (!strcmp(argv[i], "-o")) { @@ -815,6 +832,7 @@ int main(int argc, char** argv) { input_file_names.resize(num_decoded_frames); } auto input_frames = read_frames(input_file_names); + std::cout << "Read " << input_file_names.size() << " frames from disk." << std::endl; auto start = std::chrono::high_resolution_clock::now(); for (int i = 0; i < num_iterations; i++) { decode_frames(dec_info, input_frames); diff --git a/projects/rocdecode/src/rocdecode/rocdecode_api.cpp b/projects/rocdecode/src/rocdecode/rocdecode_api.cpp index 46c34cb83541..463cc53ad3c8 100644 --- a/projects/rocdecode/src/rocdecode/rocdecode_api.cpp +++ b/projects/rocdecode/src/rocdecode/rocdecode_api.cpp @@ -27,47 +27,6 @@ THE SOFTWARE. namespace rocdecode { RocDecLogger logger; -/*****************************************************************************************************/ -//! \fn static void AdjustOutputFormatToBitDepth(rocDecVideoSurfaceFormat &output_format, uint32_t bit_depth_minus_8) -//! Validates that the bit depth of output_format does not exceed bit_depth_minus_8 + 8. A 16-bit -//! output format requires bit_depth_minus_8 > 0 since its bit depth (16) would exceed that of 8-bit -//! content. An 8-bit output format is always valid regardless of bit_depth_minus_8. If an incompatible -//! 16-bit format is detected for 8-bit content, a warning is logged and output_format is set to the -//! corresponding 8-bit format. -/*****************************************************************************************************/ -static void ValidateOutputFormat(rocDecVideoSurfaceFormat &output_format, uint32_t bit_depth_minus_8) { - if (bit_depth_minus_8 > 0) { - return; // 16-bit output formats are valid for content with bit depth > 8 - } - - // Content is 8-bit; a 16-bit output format would exceed the content bit depth. - rocDecVideoSurfaceFormat adjusted = output_format; - switch (output_format) { - case rocDecVideoSurfaceFormat_P016: - adjusted = rocDecVideoSurfaceFormat_NV12; - break; - case rocDecVideoSurfaceFormat_YUV444_16Bit: - adjusted = rocDecVideoSurfaceFormat_YUV444; - break; - case rocDecVideoSurfaceFormat_YUV420_16Bit: - adjusted = rocDecVideoSurfaceFormat_YUV420; - break; - case rocDecVideoSurfaceFormat_YUV422_16Bit: - adjusted = rocDecVideoSurfaceFormat_YUV422; - break; - default: - break; // already an 8-bit format, no adjustment needed - } - - if (adjusted != output_format) { - logger.WarningLog(MakeMsg("output_format (" + TOSTR(static_cast(output_format)) + - ") bit depth exceeds content bit depth (bit_depth_minus_8=" + - TOSTR(bit_depth_minus_8) + "). Adjusting output_format to " + - TOSTR(static_cast(adjusted)) + ".")); - output_format = adjusted; - } -} - /*****************************************************************************************************/ //! \fn rocDecStatus ROCDECAPI rocDecCreateDecoder(rocDecDecoderHandle *decoder_handle, RocDecoderCreateInfo *decoder_create_info) //! Create the decoder object based on decoder_create_info. A handle to the created decoder is returned @@ -80,9 +39,6 @@ rocDecCreateDecoder(rocDecDecoderHandle *decoder_handle, RocDecoderCreateInfo *d FunctionExitLog(logger); return ROCDEC_INVALID_PARAMETER; } - - ValidateOutputFormat(decoder_create_info->output_format, decoder_create_info->bit_depth_minus_8); - rocDecDecoderHandle handle = nullptr; try { handle = new DecHandle(*decoder_create_info); @@ -209,9 +165,6 @@ rocDecReconfigureDecoder(rocDecDecoderHandle decoder_handle, RocdecReconfigureDe return ROCDEC_INVALID_PARAMETER; } auto handle = static_cast(decoder_handle); - - ValidateOutputFormat(reconfig_params->output_format, reconfig_params->bit_depth_minus_8); - rocDecStatus ret; try { ret = handle->roc_decoder_->ReconfigureDecoder(reconfig_params); diff --git a/projects/rocdecode/src/rocdecode/vaapi/vaapi_videodecoder.cpp b/projects/rocdecode/src/rocdecode/vaapi/vaapi_videodecoder.cpp index 38c000b5c11c..f92a85418f53 100644 --- a/projects/rocdecode/src/rocdecode/vaapi/vaapi_videodecoder.cpp +++ b/projects/rocdecode/src/rocdecode/vaapi/vaapi_videodecoder.cpp @@ -23,8 +23,9 @@ THE SOFTWARE. #include "vaapi_videodecoder.h" VaapiVideoDecoder::VaapiVideoDecoder(RocDecoderCreateInfo &decoder_create_info) : decoder_create_info_{decoder_create_info}, - va_display_{0}, va_config_attrib_{{}}, va_config_id_{0}, va_profile_ {VAProfileNone}, va_context_id_{0}, va_surface_ids_{{}}, - supports_modifiers_{false}, pic_params_buf_id_{0}, iq_matrix_buf_id_{0}, num_slices_{0}, slice_data_buf_id_{0} { + output_surface_format_override_{false}, va_display_{0}, va_config_attrib_{{}}, va_config_id_{0}, va_profile_ {VAProfileNone}, + va_context_id_{0}, va_surface_ids_{{}}, supports_modifiers_{false}, pic_params_buf_id_{0}, iq_matrix_buf_id_{0}, num_slices_{0}, + slice_data_buf_id_{0} { }; VaapiVideoDecoder::~VaapiVideoDecoder() { @@ -57,10 +58,72 @@ VaapiVideoDecoder::~VaapiVideoDecoder() { } } +void VaapiVideoDecoder::ValidateOutputFormat() { + // When content is 8-bit; a 16-bit output format would exceed the content bit depth. + if (decoder_create_info_.bit_depth_minus_8 == 0) { + rocDecVideoSurfaceFormat adjusted = decoder_create_info_.output_format; + switch (decoder_create_info_.output_format) { + case rocDecVideoSurfaceFormat_P016: + adjusted = rocDecVideoSurfaceFormat_NV12; + break; + case rocDecVideoSurfaceFormat_YUV444_16Bit: + adjusted = rocDecVideoSurfaceFormat_YUV444; + break; + case rocDecVideoSurfaceFormat_YUV420_16Bit: + adjusted = rocDecVideoSurfaceFormat_YUV420; + break; + case rocDecVideoSurfaceFormat_YUV422_16Bit: + adjusted = rocDecVideoSurfaceFormat_YUV422; + break; + default: + break; // already an 8-bit format, no adjustment needed + } + if (adjusted != decoder_create_info_.output_format) { + logger_.WarningLog(MakeMsg("output_format (" + TOSTR(static_cast(decoder_create_info_.output_format)) + + ") bit depth exceeds content bit depth (bit_depth_minus_8 = " + + TOSTR(decoder_create_info_.bit_depth_minus_8) + "). Adjusting output_format to " + + TOSTR(static_cast(adjusted)) + ".")); + decoder_create_info_.output_format = adjusted; + } + } +} + +void VaapiVideoDecoder::SetNativeOutputFormat() { + switch (decoder_create_info_.chroma_format) { + case rocDecVideoChromaFormat_Monochrome: + case rocDecVideoChromaFormat_420: + decoder_create_info_.output_format = (decoder_create_info_.bit_depth_minus_8 > 0) ? rocDecVideoSurfaceFormat_P016 : rocDecVideoSurfaceFormat_NV12; + break; + case rocDecVideoChromaFormat_422: + decoder_create_info_.output_format = (decoder_create_info_.bit_depth_minus_8 > 0) ? rocDecVideoSurfaceFormat_YUV422_16Bit : rocDecVideoSurfaceFormat_YUV422; + break; + case rocDecVideoChromaFormat_444: + decoder_create_info_.output_format = (decoder_create_info_.bit_depth_minus_8 > 0) ? rocDecVideoSurfaceFormat_YUV444_16Bit : rocDecVideoSurfaceFormat_YUV444; + break; + default: + decoder_create_info_.output_format = rocDecVideoSurfaceFormat_NV12; + break; + } +} + +void VaapiVideoDecoder::CheckOutputFormat() { + if (decoder_create_info_.output_format == rocDecVideoSurfaceFormat_Native) { + output_surface_format_override_ = false; + // Resolve Native to the concrete format that matches the stream's chroma format and bit depth. + SetNativeOutputFormat(); + } else { + output_surface_format_override_ = true; + ValidateOutputFormat(); + } +} + rocDecStatus VaapiVideoDecoder::InitializeDecoder() { FunctionEntryLog(logger_); rocDecStatus rocdec_status = ROCDEC_SUCCESS; + // Check if the output surface format is set by the user or native. + CheckOutputFormat(); + // Before initializing the VAAPI, first check to see if the requested codec config is supported if (!IsCodecConfigSupported(decoder_create_info_.device_id, decoder_create_info_.codec_type, decoder_create_info_.chroma_format, decoder_create_info_.bit_depth_minus_8, decoder_create_info_.output_format)) { @@ -375,7 +438,13 @@ rocDecStatus VaapiVideoDecoder::ReconfigureDecoder(RocdecReconfigureDecoderInfo 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; - decoder_create_info_.output_format = reconfig_params->output_format; + + // Adjust output format if needed + if (output_surface_format_override_) { + ValidateOutputFormat(); + } else { + SetNativeOutputFormat(); + } rocDecStatus rocdec_status; if (create_va_config) { @@ -487,8 +556,9 @@ rocDecStatus VaapiVideoDecoder::CreateSurfaces() { } break; case rocDecVideoChromaFormat_420: { + // If the user sets the output surface format // Special case for 8-bit output requirement even when the stream is 10-bit and above - if (decoder_create_info_.output_format == rocDecVideoSurfaceFormat_NV12) { + if (output_surface_format_override_ && decoder_create_info_.output_format == rocDecVideoSurfaceFormat_NV12) { surface_format = VA_RT_FORMAT_YUV420; surf_attrib.value.value.i = VA_FOURCC_NV12; } else { diff --git a/projects/rocdecode/src/rocdecode/vaapi/vaapi_videodecoder.h b/projects/rocdecode/src/rocdecode/vaapi/vaapi_videodecoder.h index 42b156a1b0d8..6d4faf51adc0 100644 --- a/projects/rocdecode/src/rocdecode/vaapi/vaapi_videodecoder.h +++ b/projects/rocdecode/src/rocdecode/vaapi/vaapi_videodecoder.h @@ -101,6 +101,7 @@ class VaapiVideoDecoder { private: RocDecoderCreateInfo decoder_create_info_; + bool output_surface_format_override_; VADisplay va_display_; VAConfigAttrib va_config_attrib_; VAConfigID va_config_id_; @@ -117,6 +118,9 @@ class VaapiVideoDecoder { RocDecLogger logger_; + void SetNativeOutputFormat(); + void ValidateOutputFormat(); + void CheckOutputFormat(); bool IsCodecConfigSupported(int device_id, rocDecVideoCodec codec_type, rocDecVideoChromaFormat chroma_format, uint32_t bit_depth_minus8, rocDecVideoSurfaceFormat output_format); rocDecStatus CreateDecoderConfig(); rocDecStatus CreateSurfaces(); diff --git a/projects/rocdecode/utils/ffmpegvideodecode/ffmpeg_video_dec.cpp b/projects/rocdecode/utils/ffmpegvideodecode/ffmpeg_video_dec.cpp index 9c4f289dbb17..0236bc8a169f 100644 --- a/projects/rocdecode/utils/ffmpegvideodecode/ffmpeg_video_dec.cpp +++ b/projects/rocdecode/utils/ffmpegvideodecode/ffmpeg_video_dec.cpp @@ -31,6 +31,7 @@ static inline float GetChromaWidthFactor(rocDecVideoSurfaceFormat surface_format case rocDecVideoSurfaceFormat_P016: case rocDecVideoSurfaceFormat_YUV444: case rocDecVideoSurfaceFormat_YUV444_16Bit: + default: factor = 1.0; break; case rocDecVideoSurfaceFormat_YUV420: diff --git a/projects/rocdecode/utils/rocvideodecode/roc_video_dec.cpp b/projects/rocdecode/utils/rocvideodecode/roc_video_dec.cpp index fa1296424b49..f678cd354f01 100644 --- a/projects/rocdecode/utils/rocvideodecode/roc_video_dec.cpp +++ b/projects/rocdecode/utils/rocvideodecode/roc_video_dec.cpp @@ -206,6 +206,7 @@ static void GetSurfaceStrideInternal(rocDecVideoSurfaceFormat surface_format, ui switch (surface_format) { case rocDecVideoSurfaceFormat_NV12: + default: *pitch = align(width, 256); *vstride = align(height, 16); break; @@ -353,7 +354,7 @@ int RocVideoDecoder::HandleVideoSequence(RocdecVideoFormat *p_video_format) { videoDecodeCreateInfo.device_id = device_id_; videoDecodeCreateInfo.codec_type = codec_id_; videoDecodeCreateInfo.chroma_format = video_chroma_format_; - videoDecodeCreateInfo.output_format = video_surface_format_; + videoDecodeCreateInfo.output_format = rocDecVideoSurfaceFormat_Native; // Signal to decode that surface format will be set based on chroma format and bit depth videoDecodeCreateInfo.bit_depth_minus_8 = bitdepth_minus_8_; videoDecodeCreateInfo.num_decode_surfaces = num_decode_surfaces_; videoDecodeCreateInfo.width = coded_width_; @@ -556,6 +557,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) { diff --git a/projects/rocdecode/utils/rocvideodecode/roc_video_dec.h b/projects/rocdecode/utils/rocvideodecode/roc_video_dec.h index df162bedf355..bb999be79522 100644 --- a/projects/rocdecode/utils/rocvideodecode/roc_video_dec.h +++ b/projects/rocdecode/utils/rocvideodecode/roc_video_dec.h @@ -79,6 +79,7 @@ inline int GetChromaPlaneCount(rocDecVideoSurfaceFormat surface_format) { switch (surface_format) { case rocDecVideoSurfaceFormat_NV12: case rocDecVideoSurfaceFormat_P016: + default: num_planes = 1; break; case rocDecVideoSurfaceFormat_YUV444: @@ -101,6 +102,7 @@ inline float GetChromaHeightFactor(rocDecVideoSurfaceFormat surface_format) { case rocDecVideoSurfaceFormat_P016: case rocDecVideoSurfaceFormat_YUV420: case rocDecVideoSurfaceFormat_YUV420_16Bit: + default: factor = 0.5; break; case rocDecVideoSurfaceFormat_YUV422: From 1825b6382793171588d5b9cc4b64a69991411af1 Mon Sep 17 00:00:00 2001 From: Jeff Jiang Date: Thu, 19 Mar 2026 17:15:22 -0400 Subject: [PATCH 3/8] * rocDecode/Output format: Updated change log and rocdecdecode sample document. Addressed several review comments. --- projects/rocdecode/CHANGELOG.md | 1 + .../how-to/using-rocDecode-rocdecdecoder.rst | 10 ++++++- .../samples/rocdecDecode/rocdecdecode.cpp | 28 +++++++++++++++---- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/projects/rocdecode/CHANGELOG.md b/projects/rocdecode/CHANGELOG.md index 12e4d756ade8..61bcc32b27f1 100644 --- a/projects/rocdecode/CHANGELOG.md +++ b/projects/rocdecode/CHANGELOG.md @@ -7,6 +7,7 @@ Full documentation for rocDecode is available at [https://rocm.docs.amd.com/proj ### Added * Logging improvement: Added function entry and exit logs (at Info log level). +* Feature: support for user set output surface format. ## rocDecode 1.7.0 for ROCm 7.2.1 diff --git a/projects/rocdecode/docs/how-to/using-rocDecode-rocdecdecoder.rst b/projects/rocdecode/docs/how-to/using-rocDecode-rocdecdecoder.rst index 73c0f7b06050..f51b6b2c8c40 100644 --- a/projects/rocdecode/docs/how-to/using-rocDecode-rocdecdecoder.rst +++ b/projects/rocdecode/docs/how-to/using-rocDecode-rocdecdecoder.rst @@ -54,7 +54,15 @@ The sample decodes raw elementary video frame files as input and produces indivi * - ``-m`` - The output surface memory type. The memory type where the surface data, such as the decoded frames, resides. Set this to 0 for intermediate GPU memory, to 1 for GPU memory, and to 2 for CPU memory. See :doc:`Surface data memory locations <../conceptual/rocDecode-memory-types>` for more information. - - Optional. Set to 0 by default. + - Optional. Set to 0 by default. + + * - ``-f`` + - Number of decoded frames to be decoded. + - Optional. + + * - ``-o_format`` + - Output surface format; [NV12, P016]. + - Optional. If net set: auto-detected from stream. The ``DecoderInfo`` struct defined in the sample is used to store user-supplied parameters as well as the decoder and parser handles. diff --git a/projects/rocdecode/samples/rocdecDecode/rocdecdecode.cpp b/projects/rocdecode/samples/rocdecDecode/rocdecdecode.cpp index 5013a40a0ca7..665baa2e3374 100644 --- a/projects/rocdecode/samples/rocdecDecode/rocdecdecode.cpp +++ b/projects/rocdecode/samples/rocdecDecode/rocdecdecode.cpp @@ -493,24 +493,40 @@ int ROCDECAPI handle_video_sequence(void* user_data, RocdecVideoFormat* format) case rocDecVideoSurfaceFormat_NV12: case rocDecVideoSurfaceFormat_YUV420: case rocDecVideoSurfaceFormat_YUV422: - case rocDecVideoSurfaceFormat_YUV444: + case rocDecVideoSurfaceFormat_YUV444: { p_dec_info->bytes_per_pixel = 1; p_dec_info->bit_depth = 8; + } break; case rocDecVideoSurfaceFormat_P016: case rocDecVideoSurfaceFormat_YUV420_16Bit: case rocDecVideoSurfaceFormat_YUV444_16Bit: - case rocDecVideoSurfaceFormat_YUV422_16Bit: - p_dec_info->bytes_per_pixel = 2; - p_dec_info->bit_depth = bitdepth_minus_8 + 8; + case rocDecVideoSurfaceFormat_YUV422_16Bit: { + if (bitdepth_minus_8) { + p_dec_info->bytes_per_pixel = 2; + p_dec_info->bit_depth = bitdepth_minus_8 + 8; + } else { + p_dec_info->bytes_per_pixel = 1; + p_dec_info->bit_depth = 8; + if (p_dec_info->surf_format == rocDecVideoSurfaceFormat_P016) { + p_dec_info->surf_format = rocDecVideoSurfaceFormat_NV12; + } else if (p_dec_info->surf_format == rocDecVideoSurfaceFormat_YUV420_16Bit) { + p_dec_info->surf_format = rocDecVideoSurfaceFormat_YUV420; + } else if (p_dec_info->surf_format == rocDecVideoSurfaceFormat_YUV422_16Bit) { + p_dec_info->surf_format = rocDecVideoSurfaceFormat_YUV422; + } else if (p_dec_info->surf_format == rocDecVideoSurfaceFormat_YUV444_16Bit) { + p_dec_info->surf_format = rocDecVideoSurfaceFormat_YUV444; + } + } + } break; default: break; } } else { rocDecVideoChromaFormat video_chroma_format = format->chroma_format; - if (video_chroma_format == rocDecVideoChromaFormat_420 || rocDecVideoChromaFormat_Monochrome) + if (video_chroma_format == rocDecVideoChromaFormat_420 || video_chroma_format == rocDecVideoChromaFormat_Monochrome) p_dec_info->surf_format = bitdepth_minus_8 ? rocDecVideoSurfaceFormat_P016 : rocDecVideoSurfaceFormat_NV12; else if (video_chroma_format == rocDecVideoChromaFormat_444) p_dec_info->surf_format = bitdepth_minus_8 ? rocDecVideoSurfaceFormat_YUV444_16Bit : rocDecVideoSurfaceFormat_YUV444; @@ -650,7 +666,7 @@ void ShowHelpAndExit(const char *option = NULL) { << "-c codec (0 : HEVC, 1 : H264, 2: AV1, 4: VP9, 5: VP8 ); optional; default: 0" << std::endl << "-n Number of iteration - specify the number of iterations for performance evaluation; optional; default: 1" << std::endl << "-f Number of decoded frames - specify the number of pictures to be decoded; optional" << std::endl - << "-o_format Output surface format; optional; default: auto-detected from stream, [NV12, P016]" << std::endl + << "-o_format Output surface format; optional; [NV12, P016]; if net set: auto-detected from stream" << std::endl << "-m output_surface_memory_type - decoded surface memory; optional; default - 0" << " [0 : OUT_SURFACE_MEM_DEV_INTERNAL/ 1 : OUT_SURFACE_MEM_DEV_COPIED/ 2 : OUT_SURFACE_MEM_HOST_COPIED/ 3 : OUT_SURFACE_MEM_NOT_MAPPED]" << std::endl; exit(0); From 86d4281d457134e83d9f5d1f699605e94cdcdae8 Mon Sep 17 00:00:00 2001 From: Jeff Jiang Date: Thu, 19 Mar 2026 17:21:36 -0400 Subject: [PATCH 4/8] * rocDecode/Output format: Adjusted table. --- .../rocdecode/docs/how-to/using-rocDecode-rocdecdecoder.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/rocdecode/docs/how-to/using-rocDecode-rocdecdecoder.rst b/projects/rocdecode/docs/how-to/using-rocDecode-rocdecdecoder.rst index f51b6b2c8c40..7e47803efc7b 100644 --- a/projects/rocdecode/docs/how-to/using-rocDecode-rocdecdecoder.rst +++ b/projects/rocdecode/docs/how-to/using-rocDecode-rocdecdecoder.rst @@ -20,7 +20,7 @@ The sample decodes raw elementary video frame files as input and produces indivi ``rocdecdecode.cpp`` takes the following arguments: .. list-table:: - :widths: 10 60 30 + :widths: 15 60 30 :header-rows: 1 * - Argument From cc327d09480a1fe70c0597828d3a114884b41184 Mon Sep 17 00:00:00 2001 From: Jeff Jiang Date: Thu, 19 Mar 2026 20:34:47 -0400 Subject: [PATCH 5/8] * rocDecode/Output format: Minor changes based on review comments. --- projects/rocdecode/api/rocdecode/rocdecode.h | 7 +++++-- .../docs/how-to/using-rocDecode-rocdecdecoder.rst | 4 ++-- projects/rocdecode/samples/rocdecDecode/rocdecdecode.cpp | 4 ++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/projects/rocdecode/api/rocdecode/rocdecode.h b/projects/rocdecode/api/rocdecode/rocdecode.h index 1379fa9f0057..c7fa52f02fb9 100644 --- a/projects/rocdecode/api/rocdecode/rocdecode.h +++ b/projects/rocdecode/api/rocdecode/rocdecode.h @@ -112,8 +112,11 @@ typedef enum rocDecVideoSurfaceFormat_enum { 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_Native = 0xFF, /**< Output format is determined by the coded stream parameters (chroma format - and bit depth). The decoder selects the appropriate surface format automatically. */ + rocDecVideoSurfaceFormat_Native = 0xFF, /**< Sentinel value: output format is determined by the coded stream parameters + (chroma format and bit depth), and the decoder selects the appropriate surface + format automatically. This value will not appear in any output_format_mask (or + similar bitmask fields) and MUST NOT be used as a bit position when constructing + or interpreting format bitmasks. */ } rocDecVideoSurfaceFormat; /**************************************************************************************************************/ diff --git a/projects/rocdecode/docs/how-to/using-rocDecode-rocdecdecoder.rst b/projects/rocdecode/docs/how-to/using-rocDecode-rocdecdecoder.rst index 7e47803efc7b..6ddebf3bfad5 100644 --- a/projects/rocdecode/docs/how-to/using-rocDecode-rocdecdecoder.rst +++ b/projects/rocdecode/docs/how-to/using-rocDecode-rocdecdecoder.rst @@ -20,7 +20,7 @@ The sample decodes raw elementary video frame files as input and produces indivi ``rocdecdecode.cpp`` takes the following arguments: .. list-table:: - :widths: 15 60 30 + :widths: 20 60 30 :header-rows: 1 * - Argument @@ -62,7 +62,7 @@ The sample decodes raw elementary video frame files as input and produces indivi * - ``-o_format`` - Output surface format; [NV12, P016]. - - Optional. If net set: auto-detected from stream. + - Optional. If not set: auto-detected from stream. The ``DecoderInfo`` struct defined in the sample is used to store user-supplied parameters as well as the decoder and parser handles. diff --git a/projects/rocdecode/samples/rocdecDecode/rocdecdecode.cpp b/projects/rocdecode/samples/rocdecDecode/rocdecdecode.cpp index 665baa2e3374..2ae461aafbcd 100644 --- a/projects/rocdecode/samples/rocdecDecode/rocdecdecode.cpp +++ b/projects/rocdecode/samples/rocdecDecode/rocdecdecode.cpp @@ -666,7 +666,7 @@ void ShowHelpAndExit(const char *option = NULL) { << "-c codec (0 : HEVC, 1 : H264, 2: AV1, 4: VP9, 5: VP8 ); optional; default: 0" << std::endl << "-n Number of iteration - specify the number of iterations for performance evaluation; optional; default: 1" << std::endl << "-f Number of decoded frames - specify the number of pictures to be decoded; optional" << std::endl - << "-o_format Output surface format; optional; [NV12, P016]; if net set: auto-detected from stream" << std::endl + << "-o_format Output surface format; optional; [NV12, P016]; if not set: auto-detected from stream" << std::endl << "-m output_surface_memory_type - decoded surface memory; optional; default - 0" << " [0 : OUT_SURFACE_MEM_DEV_INTERNAL/ 1 : OUT_SURFACE_MEM_DEV_COPIED/ 2 : OUT_SURFACE_MEM_HOST_COPIED/ 3 : OUT_SURFACE_MEM_NOT_MAPPED]" << std::endl; exit(0); @@ -814,7 +814,7 @@ int main(int argc, char** argv) { if (++i == argc) { ShowHelpAndExit("-f"); } - num_decoded_frames = atoi(argv[i]); + num_decoded_frames = std::stoul(argv[i]); continue; } if (!strcmp(argv[i], "-o_format")) { From 84cf1a5b2d8e68d38c816c78c1004217ebb8fbe0 Mon Sep 17 00:00:00 2001 From: Jeff Jiang Date: Mon, 23 Mar 2026 17:09:15 -0400 Subject: [PATCH 6/8] * rocDecode/Ouput format: Change enum value based on review comments. --- projects/rocdecode/api/rocdecode/rocdecode.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/rocdecode/api/rocdecode/rocdecode.h b/projects/rocdecode/api/rocdecode/rocdecode.h index c7fa52f02fb9..f3a1b02c2f88 100644 --- a/projects/rocdecode/api/rocdecode/rocdecode.h +++ b/projects/rocdecode/api/rocdecode/rocdecode.h @@ -112,7 +112,7 @@ typedef enum rocDecVideoSurfaceFormat_enum { 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_Native = 0xFF, /**< Sentinel value: output format is determined by the coded stream parameters + rocDecVideoSurfaceFormat_Native = 8 /**< Sentinel value: output format is determined by the coded stream parameters (chroma format and bit depth), and the decoder selects the appropriate surface format automatically. This value will not appear in any output_format_mask (or similar bitmask fields) and MUST NOT be used as a bit position when constructing From 58b0b11eb0afc48b51542f9858acbf59af885eac Mon Sep 17 00:00:00 2001 From: Jeff Jiang Date: Tue, 24 Mar 2026 10:16:44 -0400 Subject: [PATCH 7/8] * rocDecode: Bumped version to 1.8.0. --- projects/rocdecode/CHANGELOG.md | 2 +- projects/rocdecode/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/rocdecode/CHANGELOG.md b/projects/rocdecode/CHANGELOG.md index 61bcc32b27f1..dcdad8518184 100644 --- a/projects/rocdecode/CHANGELOG.md +++ b/projects/rocdecode/CHANGELOG.md @@ -2,7 +2,7 @@ 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 1.7.1 +## (Unreleased) rocDecode 1.8.0 ### Added diff --git a/projects/rocdecode/CMakeLists.txt b/projects/rocdecode/CMakeLists.txt index 71f2978fc321..768ff5cffafb 100644 --- a/projects/rocdecode/CMakeLists.txt +++ b/projects/rocdecode/CMakeLists.txt @@ -47,7 +47,7 @@ if (NOT DEFINED CMAKE_CXX_COMPILER) endif() # rocdecode Version -set(VERSION "1.7.1") +set(VERSION "1.8.0") # Set Project Version and Language project(rocdecode VERSION ${VERSION} LANGUAGES CXX) From d7c9a0ee0be50160d63042d9969d239608c0f3e7 Mon Sep 17 00:00:00 2001 From: Jeff Jiang Date: Fri, 27 Mar 2026 12:30:45 -0400 Subject: [PATCH 8/8] * rocDecode/Output format: Fixed typos. --- projects/rocdecode/samples/rocdecDecode/rocdecdecode.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/rocdecode/samples/rocdecDecode/rocdecdecode.cpp b/projects/rocdecode/samples/rocdecDecode/rocdecdecode.cpp index 2ae461aafbcd..c5037eea8128 100644 --- a/projects/rocdecode/samples/rocdecDecode/rocdecdecode.cpp +++ b/projects/rocdecode/samples/rocdecDecode/rocdecdecode.cpp @@ -663,7 +663,7 @@ void ShowHelpAndExit(const char *option = NULL) { #else << "-b backend (0 for GPU); optional; default: 0" << std::endl #endif - << "-c codec (0 : HEVC, 1 : H264, 2: AV1, 4: VP9, 5: VP8 ); optional; default: 0" << std::endl + << "-c codec (0 : HEVC, 1 : H264, 2: AV1, 3: VP9, 4: VP8 ); optional; default: 0" << std::endl << "-n Number of iteration - specify the number of iterations for performance evaluation; optional; default: 1" << std::endl << "-f Number of decoded frames - specify the number of pictures to be decoded; optional" << std::endl << "-o_format Output surface format; optional; [NV12, P016]; if not set: auto-detected from stream" << std::endl