diff --git a/projects/rocdecode/CHANGELOG.md b/projects/rocdecode/CHANGELOG.md index 12e4d756ade8..dcdad8518184 100644 --- a/projects/rocdecode/CHANGELOG.md +++ b/projects/rocdecode/CHANGELOG.md @@ -2,11 +2,12 @@ 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 * 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/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) diff --git a/projects/rocdecode/api/rocdecode/rocdecode.h b/projects/rocdecode/api/rocdecode/rocdecode.h index 56038355abbe..f3a1b02c2f88 100644 --- a/projects/rocdecode/api/rocdecode/rocdecode.h +++ b/projects/rocdecode/api/rocdecode/rocdecode.h @@ -112,6 +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 = 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 + 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 73c0f7b06050..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: 10 60 30 + :widths: 20 60 30 :header-rows: 1 * - Argument @@ -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 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 2431a9357606..c5037eea8128 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; }; @@ -147,6 +151,7 @@ typedef enum DecoderBackend_enum { } \ } while (false) + /** * @brief Struct containing all the information for decoding and displaying output * @@ -162,14 +167,16 @@ struct DecoderInfo { std::string output_file_path; OutputSurfaceMemoryType mem_type; rocDecVideoSurfaceFormat surf_format; - rocDecVideoSurfaceFormat video_chroma_format; + bool output_format_override; // true: user set output surface format; false: output surface format is determined by the coded stream + rocDecVideoChromaFormat video_chroma_format; uint32_t coded_width, coded_height; uint32_t bytes_per_pixel; bool is_decoder_reconfigured; 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{rocDecVideoChromaFormat_420}, is_decoder_reconfigured{false}, fp_out{nullptr} {} }; @@ -181,7 +188,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))); @@ -321,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(); @@ -357,12 +363,25 @@ 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; - 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)); } @@ -463,6 +482,63 @@ 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: { + 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 || 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; + 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; @@ -474,21 +550,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(); @@ -601,8 +663,10 @@ 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 << "-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 +705,27 @@ 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 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 +} +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; @@ -691,8 +769,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")) { @@ -734,6 +810,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 = std::stoul(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 +844,15 @@ 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); + 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); + 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/vaapi/vaapi_videodecoder.cpp b/projects/rocdecode/src/rocdecode/vaapi/vaapi_videodecoder.cpp index 447cb9560928..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)) { @@ -376,6 +439,13 @@ rocDecStatus VaapiVideoDecoder::ReconfigureDecoder(RocdecReconfigureDecoderInfo decoder_create_info_.target_width = reconfig_params->target_width; decoder_create_info_.bit_depth_minus_8 = reconfig_params->bit_depth_minus_8; + // Adjust output format if needed + if (output_surface_format_override_) { + ValidateOutputFormat(); + } else { + SetNativeOutputFormat(); + } + rocDecStatus rocdec_status; if (create_va_config) { rocdec_status = CreateDecoderConfig(); @@ -480,21 +550,30 @@ 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: { + // 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 (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 { + 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; 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: