From 7ac767ec0723ae6bfc304438fef3b47ac0ea7c72 Mon Sep 17 00:00:00 2001 From: Fiona-MCW <70996026+fiona-gladwin@users.noreply.github.com> Date: Wed, 5 Feb 2025 08:00:57 +0530 Subject: [PATCH] Video - rocDecode integration in rocAL (#253) * Add CMakeList changes Requires VideoDemuxer to have .cpp file * Add rocDecode utils files and cmake changes * rocDecode integration for rocAL * merge with tot * Add initial support for rocDecode integration * Add fix to decode sequences * VideoDemuxer - support to return dts * Support to seek exact frame Facing seg fault * Add intermediary buffers to copy * Change the name of rocdec files * Temporary rocDecode cmake changes Add utils folder to rocAL hip to compile with rocDecode * Fix CMake for rocDecode * Minor fix * Fix stride for rocdecode video decoder * Revert "Temporary rocDecode cmake changes" This reverts commit 21b0538d855442d88708e6ca3c4e1acb13b94f98. * Introduce CMake for rocDecode Revert additional changes * Fix issues with CMake * rocDecode Flush decoder after decoding each sequence * Add changes to flush decoder after seek * Add support in rocDecode to seek to exact frame using dts * Add changes in API to pass device ID to video decoder * Add stream synchronize * Minor changes * Minor change * Change rocDecode to all caps in CMake * Minor changes * Minor CMake change * Minor changes * Introduce enable rocdecode flag in CMake * Minor fix * Minor changes * Modify CMake to use only ROCM_PATH * Use Pascal case for fn names in Video Decoder and other derived classes * Fix CMakeLists * Minor change * Fix rocAL_hip CMakeLists for rocDecode * Add decoder type argument to Video readers * Fix video metadata reader * Minor changes * Move default constructor to class * Minor fix * Update CHANGELOG and docs * Add link to rocDecode * Update README with rocDecode installation instructions * Update rocAL version * Update README with rocDecode manual installation --------- Co-authored-by: rrawther Co-authored-by: Sundar Rajan Vaithiyanathan <99159823+SundarRajan28@users.noreply.github.com> Co-authored-by: Kiriti Gowda --- CHANGELOG.md | 20 +- CMakeLists.txt | 2 +- README.md | 4 + cmake/FindrocDecode.cmake | 80 ++++++++ docs/user_guide/ch1.md | 1 + rocAL/CMakeLists.txt | 18 +- rocAL/include/api/rocal_api_data_loaders.h | 16 +- rocAL/include/api/rocal_api_types.h | 6 +- rocAL/include/decoders/image/decoder.h | 8 +- .../decoders/video/ffmpeg_video_decoder.h | 6 +- .../decoders/video/hardware_video_decoder.h | 6 +- .../decoders/video/rocdec_video_decoder.h | 64 +++++++ rocAL/include/decoders/video/video_decoder.h | 6 +- rocAL/include/loaders/video/video_loader.h | 2 + .../loaders/video/video_read_and_decode.h | 5 +- rocAL/rocAL_hip/CMakeLists.txt | 6 +- rocAL/source/api/rocal_api_data_loaders.cpp | 41 ++-- .../decoders/video/ffmpeg_video_decoder.cpp | 10 +- .../decoders/video/hardware_video_decoder.cpp | 13 +- .../decoders/video/rocdec_video_decoder.cpp | 180 ++++++++++++++++++ .../decoders/video/video_decoder_factory.cpp | 9 +- rocAL/source/loaders/video/video_loader.cpp | 8 +- .../loaders/video/video_loader_sharded.cpp | 1 + .../loaders/video/video_read_and_decode.cpp | 7 +- rocAL/source/pipeline/master_graph.cpp | 1 + rocAL_pybind/amd/rocal/readers.py | 11 +- rocAL_pybind/amd/rocal/types.py | 1 + rocAL_pybind/getrocALwheelname.py | 2 +- rocAL_pybind/rocal_pybind.cpp | 1 + rocAL_pybind/setup.py | 2 +- tests/cpp_api/video_tests/README.md | 9 +- tests/cpp_api/video_tests/testScript.sh | 6 +- tests/cpp_api/video_tests/video_tests.cpp | 21 +- 33 files changed, 496 insertions(+), 77 deletions(-) create mode 100644 cmake/FindrocDecode.cmake create mode 100644 rocAL/include/decoders/video/rocdec_video_decoder.h create mode 100644 rocAL/source/decoders/video/rocdec_video_decoder.cpp diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e8f97c45..8d15a72fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,27 @@ Full documentation for rocLibrary is available at [https://rocm.docs.amd.com/projects/rocAL/](https://rocm.docs.amd.com/projects/rocAL/en/latest/). -## rocAL 2.2.0 (unreleased) +## rocAL 2.3.0 (unreleased) ### Added +* Extended support to rocAL's video decoder to use rocDecode hardware decoder. + +### Changed + +### Removed + +### Optimizations + +### Resolved issues + +### Known issues + +### Upcoming changes + +## rocAL 2.2.0 + +### Added +* Extended support to rocAL's video decoder to use rocDecode hardware decoder. ### Changed * AMD Clang is now the default CXX and C compiler. diff --git a/CMakeLists.txt b/CMakeLists.txt index a2a489292..700a9e162 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,7 +38,7 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED On) # rocAL Version -set(VERSION "2.2.0") +set(VERSION "2.3.0") # Set Project Version and Language project(rocal VERSION ${VERSION} LANGUAGES CXX) diff --git a/README.md b/README.md index 6e33953d9..57726ed79 100644 --- a/README.md +++ b/README.md @@ -148,6 +148,10 @@ rocAL can be currently used to perform the following operations either with rand * Source: `https://github.com/Tencent/rapidjson.git` * Tag: `master` +* [rocDecode](https://github.com/ROCm/rocDecode) - Manual install, Optional for source install, but required for package install + * Source : `https://github.com/ROCm/rocDecode.git` + * Tag : `develop` + > [!IMPORTANT] > * Required compiler support > * C++17 diff --git a/cmake/FindrocDecode.cmake b/cmake/FindrocDecode.cmake new file mode 100644 index 000000000..318eede8e --- /dev/null +++ b/cmake/FindrocDecode.cmake @@ -0,0 +1,80 @@ +################################################################################ +# +# MIT License +# +# Copyright (c) 2025 Advanced Micro Devices, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +################################################################################ + +# ROCM Path +if(ROCM_PATH) + message("-- ${White}FindrocDecode: ROCM_PATH Set -- ${ROCM_PATH}${ColourReset}") +else() + set(ROCM_PATH /opt/rocm CACHE PATH "Default ROCm installation path") +endif() + +# find rocDecode - library and headers +find_path(ROCDECODE_INCLUDE_DIR NAMES rocdecode.h PATHS ${ROCM_PATH}/include/rocdecode) +find_library(ROCDECODE_LIBRARY NAMES rocdecode HINTS ${ROCM_PATH}/lib) +mark_as_advanced(ROCDECODE_INCLUDE_DIR) +mark_as_advanced(ROCDECODE_LIBRARY) + +if(ROCDECODE_INCLUDE_DIR AND ROCDECODE_LIBRARY) + message("-- ${White}FindrocDecode -- Using rocDecode: \n\tIncludes:${ROCDECODE_INCLUDE_DIR}\n\tLib:${ROCDECODE_LIBRARY}${ColourReset}") + set(ROCDECODE_FOUND TRUE) +else() + if(rocDecode_FIND_REQUIRED) + message(FATAL_ERROR "FindrocDecode -- Failed to find rocDecode Library") + endif() + message( "-- ${Yellow}NOTE: FindrocDecode failed to find rocDecode -- INSTALL rocDecode${ColourReset}" ) +endif() + +if(ROCDECODE_FOUND) + # Find rocDecode Version + file(READ "${ROCDECODE_INCLUDE_DIR}/rocdecode_version.h" ROCDECODE_VERSION_FILE) + string(REGEX MATCH "ROCDECODE_MAJOR_VERSION ([0-9]*)" _ ${ROCDECODE_VERSION_FILE}) + set(ROCDECODE_VER_MAJOR ${CMAKE_MATCH_1}) + string(REGEX MATCH "ROCDECODE_MINOR_VERSION ([0-9]*)" _ ${ROCDECODE_VERSION_FILE}) + set(ROCDECODE_VER_MINOR ${CMAKE_MATCH_1}) + string(REGEX MATCH "ROCDECODE_MICRO_VERSION ([0-9]*)" _ ${ROCDECODE_VERSION_FILE}) + set(ROCDECODE_VER_MICRO ${CMAKE_MATCH_1}) + message("-- ${White}Found rocDecode Version: ${ROCDECODE_VER_MAJOR}.${ROCDECODE_VER_MINOR}.${ROCDECODE_VER_MICRO}${ColourReset}") + mark_as_advanced(ROCDECODE_VER_MAJOR) + mark_as_advanced(ROCDECODE_VER_MINOR) + mark_as_advanced(ROCDECODE_VER_MICRO) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + rocDecode + FOUND_VAR + ROCDECODE_FOUND + REQUIRED_VARS + ROCDECODE_INCLUDE_DIR + ROCDECODE_LIBRARY +) + +set(ROCDECODE_FOUND ${ROCDECODE_FOUND} CACHE INTERNAL "") +set(ROCDECODE_INCLUDE_DIR ${ROCDECODE_INCLUDE_DIR} CACHE INTERNAL "") +set(ROCDECODE_LIBRARY ${ROCDECODE_LIBRARY} CACHE INTERNAL "") +set(ROCDECODE_VER_MAJOR ${ROCDECODE_VER_MAJOR} CACHE INTERNAL "") +set(ROCDECODE_VER_MINOR ${ROCDECODE_VER_MINOR} CACHE INTERNAL "") +set(ROCDECODE_VER_MICRO ${ROCDECODE_VER_MICRO} CACHE INTERNAL "") diff --git a/docs/user_guide/ch1.md b/docs/user_guide/ch1.md index c552757b1..df68e8c10 100644 --- a/docs/user_guide/ch1.md +++ b/docs/user_guide/ch1.md @@ -79,5 +79,6 @@ rocAL operators offer the flexibility to run on CPU or GPU for building hybrid p | Image_raw | Decodes images in raw format | | Image_random_crop | Decodes and randomly crops JPEG images | | Image_slice | Decodes and slices JPEG images | +| Video | Decodes videos using FFmpeg/[rocDecode](https://github.com/ROCm/rocDecode) | To see examples demonstrating the usage of decoders and readers, [click here](https://github.com/ROCm/rocAL/tree/master/docs/examples) diff --git a/rocAL/CMakeLists.txt b/rocAL/CMakeLists.txt index 8ea2eb358..b686e6c71 100644 --- a/rocAL/CMakeLists.txt +++ b/rocAL/CMakeLists.txt @@ -64,6 +64,7 @@ find_package(FFmpeg QUIET) find_package(OpenCV QUIET) find_package(SndFile QUIET) find_package(LibTar QUIET) +find_package(rocDecode QUIET) # HIP Backend if(GPU_SUPPORT AND "${BACKEND}" STREQUAL "HIP") @@ -268,7 +269,11 @@ if(${BUILD_ROCAL}) ) link_directories(${ROCM_PATH}/${CMAKE_INSTALL_LIBDIR}) - + #rocDecode + if ("${BACKEND}" STREQUAL "HIP" AND HIP_FOUND AND ROCDECODE_FOUND) + include_directories(${ROCDECODE_INCLUDE_DIR} ${ROCM_PATH}/share/rocdecode/utils/rocvideodecode) + set(LINK_LIBRARY_LIST ${LINK_LIBRARY_LIST} ${ROCDECODE_LIBRARY}) + endif() if("${BACKEND}" STREQUAL "HIP" AND HIP_FOUND) link_directories(${HIP_PATH}/${CMAKE_INSTALL_LIBDIR}) include_directories(${ROCM_PATH}/${CMAKE_INSTALL_INCLUDEDIR} rocAL_hip) @@ -281,7 +286,9 @@ if(${BUILD_ROCAL}) link_directories(${AMDRPP_LIBRARIES_DIRS} ${TurboJpeg_LIBRARIES_DIRS} ${PROTOBUF_LIBRARY_DIRS} /usr/local/lib/) file(GLOB_RECURSE SOURCES "source/*.cpp") - add_library(${PROJECT_NAME} SHARED ${SOURCES} ${TF_PROTO_SRCS} ${TF_PROTO_HEADERS} ${CAFFE_PROTO_HEADERS} ${CAFFE_PROTO_SRCS} ${CAFFE2_PROTO_SRCS} ${CAFFE2_PROTO_HEADERS}) + set(ROCDECODE_SRCS ${ROCM_PATH}/share/rocdecode/utils/rocvideodecode/roc_video_dec.cpp) + add_library(${PROJECT_NAME} SHARED ${SOURCES} ${TF_PROTO_SRCS} ${TF_PROTO_HEADERS} ${CAFFE_PROTO_HEADERS} + ${CAFFE_PROTO_SRCS} ${CAFFE2_PROTO_SRCS} ${CAFFE2_PROTO_HEADERS} ${ROCDECODE_SRCS}) if("${BACKEND}" STREQUAL "HIP" AND HIP_FOUND) add_dependencies(${PROJECT_NAME} rocAL_hip) @@ -289,6 +296,12 @@ if(${BUILD_ROCAL}) target_compile_definitions(${PROJECT_NAME} PRIVATE __HIP_PLATFORM_AMD__) target_compile_definitions(${PROJECT_NAME} PUBLIC ENABLE_HIP=1) target_compile_definitions(${PROJECT_NAME} PUBLIC ENABLE_OPENCL=0) + if(ROCDECODE_FOUND) + include_directories(${ROCM_PATH}/share/rocdecode/utils) + target_compile_definitions(${PROJECT_NAME} PUBLIC ENABLE_ROCDECODE=1) + else() + target_compile_definitions(${PROJECT_NAME} PUBLIC ENABLE_ROCDECODE=0) + endif() message("-- ${White}rocAL built with HIP Backend${ColourReset}") elseif("${BACKEND}" STREQUAL "OPENCL" AND OPENCL_FOUND) include_directories(${OpenCL_INCLUDE_DIRS} ${OpenCL_INCLUDE_DIRS}/Headers) @@ -321,6 +334,7 @@ if(${BUILD_ROCAL}) target_compile_definitions(${PROJECT_NAME} PUBLIC ENABLE_OPENCV=0) message("-- ${Yellow}NOTE: rocAL built without OpenCV extension functionality${ColourReset}") endif() + # FFMPEG if(NOT FFMPEG_FOUND) message("-- ${Yellow}NOTE: rocAL built without FFmpeg video decode functionality${ColourReset}") diff --git a/rocAL/include/api/rocal_api_data_loaders.h b/rocAL/include/api/rocal_api_data_loaders.h index d443d4689..98c826f3a 100644 --- a/rocAL/include/api/rocal_api_data_loaders.h +++ b/rocAL/include/api/rocal_api_data_loaders.h @@ -623,12 +623,13 @@ extern "C" RocalTensor ROCAL_API_CALL rocalRawTFRecordSourceSingleShard(RocalCon * \param [in] context Rocal context * \param [in] source_path A NULL terminated char string pointing to the location on the disk. source_path can be a video file, folder containing videos or a text file * \param [in] color_format The color format the frames will be decoded to. - * \param [in] rocal_decode_device Enables software or hardware decoding. Currently only software decoding is supported. + * \param [in] rocal_decode_device Enables software decoding(using FFmpeg) or hardware decoding(using FFmepg/rocDecode hardware decoder). * \param [in] internal_shard_count Defines the parallelism level by internally sharding the input dataset and load/decode using multiple decoder/loader instances. * \param [in] sequence_length: The number of frames in a sequence. * \param [in] shuffle: to shuffle sequences. * \param [in] is_output Determines if the user wants the loaded sequence of frames to be part of the output or not. * \param [in] loop: repeat data loading. + * \param [in] rocal_decoder_type Determines the decoder_type, FFmepg or rocDecode * \param [in] step: Frame interval between each sequence. * \param [in] stride: Frame interval between frames in a sequence. * \param [in] file_list_frame_num: Determines if the user wants to read frame number or timestamps if a text file is passed in the source_path. @@ -644,6 +645,7 @@ extern "C" RocalTensor ROCAL_API_CALL rocalVideoFileSource(RocalContext context, bool is_output = false, bool shuffle = false, bool loop = false, + RocalDecoderType rocal_decoder_type = RocalDecoderType::ROCAL_DECODER_VIDEO_FFMPEG_SW, unsigned step = 0, unsigned stride = 0, bool file_list_frame_num = true, @@ -654,13 +656,14 @@ extern "C" RocalTensor ROCAL_API_CALL rocalVideoFileSource(RocalContext context, * \param [in] context Rocal context * \param [in] source_path A NULL terminated char string pointing to the location on the disk. source_path can be a video file, folder containing videos or a text file * \param [in] color_format The color format the frames will be decoded to. - * \param [in] rocal_decode_device Enables software or hardware decoding. Currently only software decoding is supported. + * \param [in] rocal_decode_device Enables software decoding(using FFmpeg) or hardware decoding(using FFmepg/rocDecode hardware decoder). * \param [in] shard_id Shard id for this loader. * \param [in] shard_count Total shard count. * \param [in] sequence_length: The number of frames in a sequence. * \param [in] shuffle: to shuffle sequences. * \param [in] is_output Determines if the user wants the loaded sequence of frames to be part of the output or not. * \param [in] loop: repeat data loading. + * \param [in] rocal_decoder_type Determines the decoder_type, FFmepg or rocDecode * \param [in] step: Frame interval between each sequence. * \param [in] stride: Frame interval between frames in a sequence. * \param [in] file_list_frame_num: Determines if the user wants to read frame number or timestamps if a text file is passed in the source_path. @@ -677,6 +680,7 @@ extern "C" RocalTensor ROCAL_API_CALL rocalVideoFileSourceSingleShard(RocalConte bool shuffle = false, bool is_output = false, bool loop = false, + RocalDecoderType rocal_decoder_type = RocalDecoderType::ROCAL_DECODER_VIDEO_FFMPEG_SW, unsigned step = 0, unsigned stride = 0, bool file_list_frame_num = true, @@ -687,7 +691,7 @@ extern "C" RocalTensor ROCAL_API_CALL rocalVideoFileSourceSingleShard(RocalConte * \param [in] context Rocal context * \param [in] source_path A NULL terminated char string pointing to the location on the disk. source_path can be a video file, folder containing videos or a text file * \param [in] color_format The color format the frames will be decoded to. - * \param [in] rocal_decode_device Enables software or hardware decoding. Currently only software decoding is supported. + * \param [in] rocal_decode_device Enables software decoding(using FFmpeg) or hardware decoding(using FFmepg/rocDecode hardware decoder). * \param [in] internal_shard_count Defines the parallelism level by internally sharding the input dataset and load/decode using multiple decoder/loader instances. * \param [in] sequence_length: The number of frames in a sequence. * \param [in] dest_width The output width of frames. @@ -695,6 +699,7 @@ extern "C" RocalTensor ROCAL_API_CALL rocalVideoFileSourceSingleShard(RocalConte * \param [in] shuffle: to shuffle sequences. * \param [in] is_output Determines if the user wants the loaded sequence of frames to be part of the output or not. * \param [in] loop: repeat data loading. + * \param [in] rocal_decoder_type Determines the decoder_type, FFmepg or rocDecode * \param [in] step: Frame interval between each sequence. * \param [in] stride: Frame interval between frames in a sequence. * \param [in] file_list_frame_num: Determines if the user wants to read frame number or timestamps if a text file is passed in the source_path. @@ -712,6 +717,7 @@ extern "C" RocalTensor ROCAL_API_CALL rocalVideoFileResize(RocalContext context, bool shuffle = false, bool is_output = false, bool loop = false, + RocalDecoderType rocal_decoder_type = RocalDecoderType::ROCAL_DECODER_VIDEO_FFMPEG_SW, unsigned step = 0, unsigned stride = 0, bool file_list_frame_num = true, @@ -727,7 +733,7 @@ extern "C" RocalTensor ROCAL_API_CALL rocalVideoFileResize(RocalContext context, * \param [in] context Rocal context * \param [in] source_path A NULL terminated char string pointing to the location on the disk. source_path can be a video file, folder containing videos or a text file * \param [in] color_format The color format the frames will be decoded to. - * \param [in] rocal_decode_device Enables software or hardware decoding. Currently only software decoding is supported. + * \param [in] rocal_decode_device Enables software decoding(using FFmpeg) or hardware decoding(using FFmepg/rocDecode hardware decoder). * \param [in] shard_id Shard id for this loader. * \param [in] shard_count Total shard count. * \param [in] sequence_length: The number of frames in a sequence. @@ -736,6 +742,7 @@ extern "C" RocalTensor ROCAL_API_CALL rocalVideoFileResize(RocalContext context, * \param [in] shuffle: to shuffle sequences. * \param [in] is_output Determines if the user wants the loaded sequence of frames to be part of the output or not. * \param [in] loop: repeat data loading. + * \param [in] rocal_decoder_type Determines the decoder_type, FFmepg or rocDecode * \param [in] step: Frame interval between each sequence. * \param [in] stride: Frame interval between frames in a sequence. * \param [in] file_list_frame_num: Determines if the user wants to read frame number or timestamps if a text file is passed in the source_path. @@ -754,6 +761,7 @@ extern "C" RocalTensor ROCAL_API_CALL rocalVideoFileResizeSingleShard(RocalConte bool shuffle = false, bool is_output = false, bool loop = false, + RocalDecoderType rocal_decoder_type = RocalDecoderType::ROCAL_DECODER_VIDEO_FFMPEG_SW, unsigned step = 0, unsigned stride = 0, bool file_list_frame_num = true, diff --git a/rocAL/include/api/rocal_api_types.h b/rocAL/include/api/rocal_api_types.h index 94761825d..51f098abe 100644 --- a/rocAL/include/api/rocal_api_types.h +++ b/rocAL/include/api/rocal_api_types.h @@ -280,7 +280,11 @@ enum RocalDecoderType { /*! \brief AMD ROCAL_DECODER_AUDIO_GENERIC * Uses SndFile library to read audio files */ - ROCAL_DECODER_AUDIO_GENERIC = 5 + ROCAL_DECODER_AUDIO_GENERIC = 5, + /*! \brief AMD ROCAL_DECODER_VIDEO_ROCDECODE + * Uses rocDecode library to decode videos on hardware + */ + ROCAL_DECODER_VIDEO_ROCDECODE = 6 }; enum RocalOutputMemType { diff --git a/rocAL/include/decoders/image/decoder.h b/rocAL/include/decoders/image/decoder.h index fbbe25d04..050fcfff8 100644 --- a/rocAL/include/decoders/image/decoder.h +++ b/rocAL/include/decoders/image/decoder.h @@ -32,11 +32,11 @@ enum class DecoderType { TURBO_JPEG = 0, //!< Can only decode FUSED_TURBO_JPEG = 1, //!< FOR PARTIAL DECODING OPENCV_DEC = 2, //!< for back_up decoding - HW_JPEG_DEC = 3, + HW_JPEG_DEC = 3, //!< for JPEG decoding using HW via FFMPEG SKIP_DECODE = 4, //!< For skipping decoding in case of uncompressed data from reader - OVX_FFMPEG = 5, //!< Uses FFMPEG to decode video streams, can decode up to 4 video streams simultaneously - FFMPEG_SOFTWARE_DECODE = 6, - FFMPEG_HARDWARE_DECODE = 7, + FFMPEG_SW_DECODE = 5, //!< for video decoding using CPU and FFMPEG + FFMPEG_HW_DECODE = 6, //!< for video decoding using HW via FFMPEG + ROCDEC_VIDEO_DECODE = 7, //!< for video decoding using HW via rocDecode AUDIO_SOFTWARE_DECODE = 8 //!< Uses sndfile to decode audio files }; diff --git a/rocAL/include/decoders/video/ffmpeg_video_decoder.h b/rocAL/include/decoders/video/ffmpeg_video_decoder.h index 5be738ff8..32b786dde 100644 --- a/rocAL/include/decoders/video/ffmpeg_video_decoder.h +++ b/rocAL/include/decoders/video/ffmpeg_video_decoder.h @@ -29,10 +29,10 @@ class FFmpegVideoDecoder : public VideoDecoder { public: //! Default constructor FFmpegVideoDecoder(); - VideoDecoder::Status Initialize(const char *src_filename) override; + VideoDecoder::Status Initialize(const char *src_filename, int device_id = 0) override; VideoDecoder::Status Decode(unsigned char *output_buffer, unsigned seek_frame_number, size_t sequence_length, size_t stride, int out_width, int out_height, int out_stride, AVPixelFormat out_format) override; - int seek_frame(AVRational avg_frame_rate, AVRational time_base, unsigned frame_number) override; - void release() override; + int SeekFrame(AVRational avg_frame_rate, AVRational time_base, unsigned frame_number) override; + void Release() override; ~FFmpegVideoDecoder() override; private: diff --git a/rocAL/include/decoders/video/hardware_video_decoder.h b/rocAL/include/decoders/video/hardware_video_decoder.h index e9a3904b6..a1c36bc33 100644 --- a/rocAL/include/decoders/video/hardware_video_decoder.h +++ b/rocAL/include/decoders/video/hardware_video_decoder.h @@ -29,10 +29,10 @@ class HardWareVideoDecoder : public VideoDecoder { public: //! Default constructor HardWareVideoDecoder(); - VideoDecoder::Status Initialize(const char *src_filename) override; + VideoDecoder::Status Initialize(const char *src_filename, int device_id = 0) override; VideoDecoder::Status Decode(unsigned char *output_buffer, unsigned seek_frame_number, size_t sequence_length, size_t stride, int out_width, int out_height, int out_stride, AVPixelFormat out_format) override; - int seek_frame(AVRational avg_frame_rate, AVRational time_base, unsigned frame_number) override; - void release() override; + int SeekFrame(AVRational avg_frame_rate, AVRational time_base, unsigned frame_number) override; + void Release() override; ~HardWareVideoDecoder() override; private: diff --git a/rocAL/include/decoders/video/rocdec_video_decoder.h b/rocAL/include/decoders/video/rocdec_video_decoder.h new file mode 100644 index 000000000..e6a3a0638 --- /dev/null +++ b/rocAL/include/decoders/video/rocdec_video_decoder.h @@ -0,0 +1,64 @@ +/* +Copyright (c) 2025 Advanced Micro Devices, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#pragma once + +#include "video_decoder.h" + +#ifdef ROCAL_VIDEO +#if ENABLE_HIP && ENABLE_ROCDECODE + +#include "video_demuxer.h" +#include "video_post_process.h" +#include "rocvideodecode/roc_video_dec.h" + +typedef enum ReconfigFlushModeEnum { + RECONFIG_FLUSH_MODE_NONE = 0, /**< Just flush to get the frame count */ + RECONFIG_FLUSH_MODE_DUMP_TO_FILE = 1, /**< The remaining frames will be dumped to file in this mode */ + RECONFIG_FLUSH_MODE_CALCULATE_MD5 = 2, /**< Calculate the MD5 of the flushed frames */ +} ReconfigFlushMode; + +typedef struct ReconfigDumpFileStruct_t { + bool b_dump_frames_to_file; + std::string output_file_name; +} ReconfigDumpFileStruct; + +class RocDecVideoDecoder : public VideoDecoder { + public: + //! Default constructor + RocDecVideoDecoder() {} + VideoDecoder::Status Initialize(const char *src_filename, int device_id = 0) override; + VideoDecoder::Status Decode(unsigned char *output_buffer, unsigned seek_frame_number, size_t sequence_length, size_t stride, int out_width, int out_height, int out_stride, AVPixelFormat out_format) override; + int SeekFrame(AVRational avg_frame_rate, AVRational time_base, unsigned frame_number) override { return 0; } + void Release() override {} + ~RocDecVideoDecoder() override; + + private: + const char *_src_filename = NULL; + std::shared_ptr _demuxer; + std::shared_ptr _rocvid_decoder; + OutputFormatEnum _output_format = rgb; + int _device_id; +}; + +#endif +#endif diff --git a/rocAL/include/decoders/video/video_decoder.h b/rocAL/include/decoders/video/video_decoder.h index 74c2b247f..42602a6ba 100644 --- a/rocAL/include/decoders/video/video_decoder.h +++ b/rocAL/include/decoders/video/video_decoder.h @@ -59,10 +59,10 @@ class VideoDecoder { RGB, BGR }; - virtual VideoDecoder::Status Initialize(const char *src_filename) = 0; + virtual VideoDecoder::Status Initialize(const char *src_filename, int device_id = 0) = 0; virtual VideoDecoder::Status Decode(unsigned char *output_buffer, unsigned seek_frame_number, size_t sequence_length, size_t stride, int out_width, int out_height, int out_stride, AVPixelFormat out_format) = 0; - virtual int seek_frame(AVRational avg_frame_rate, AVRational time_base, unsigned frame_number) = 0; - virtual void release() = 0; + virtual int SeekFrame(AVRational avg_frame_rate, AVRational time_base, unsigned frame_number) = 0; + virtual void Release() = 0; virtual ~VideoDecoder() = default; }; #endif diff --git a/rocAL/include/loaders/video/video_loader.h b/rocAL/include/loaders/video/video_loader.h index 893e91526..550357ba7 100644 --- a/rocAL/include/loaders/video/video_loader.h +++ b/rocAL/include/loaders/video/video_loader.h @@ -48,6 +48,7 @@ class VideoLoader : public LoaderModule { void start_loading() override; LoaderModuleStatus set_cpu_affinity(cpu_set_t cpu_mask); LoaderModuleStatus set_cpu_sched_policy(struct sched_param sched_policy); + void set_gpu_device_id(int device_id); std::vector get_id() override; DecodedDataInfo get_decode_data_info() override; void set_prefetch_queue_depth(size_t prefetch_queue_depth) override; @@ -83,6 +84,7 @@ class VideoLoader : public LoaderModule { size_t _image_counter = 0; //!< How many frames have been loaded already size_t _remaining_sequences_count; //!< How many frames are there yet to be loaded bool _decoder_keep_original = false; + int _device_id = 0; //!< device_id for this loader std::vector> _sequence_start_framenum_vec; std::vector>> _sequence_frame_timestamps_vec; CropImageInfo _crop_img_info; diff --git a/rocAL/include/loaders/video/video_read_and_decode.h b/rocAL/include/loaders/video/video_read_and_decode.h index 4695289d8..1dfd02142 100644 --- a/rocAL/include/loaders/video/video_read_and_decode.h +++ b/rocAL/include/loaders/video/video_read_and_decode.h @@ -29,7 +29,7 @@ THE SOFTWARE. #include #include #include "pipeline/commons.h" -#include "decoders/video/ffmpeg_video_decoder.h" +#include "decoders/video/video_decoder.h" #include "readers/video/video_reader_factory.h" #include "pipeline/timing_debug.h" #include "loaders/loader_module.h" @@ -48,7 +48,7 @@ class VideoReadAndDecode { ~VideoReadAndDecode(); size_t count(); void reset(); - void create(ReaderConfig reader_config, DecoderConfig decoder_config, int batch_size); + void create(ReaderConfig reader_config, DecoderConfig decoder_config, int batch_size, int device_id = 0); void set_video_process_count(size_t video_count) { _video_process_count = (video_count <= _max_video_count) ? video_count : _max_video_count; } @@ -110,5 +110,6 @@ class VideoReadAndDecode { size_t _max_decoded_stride; AVPixelFormat _out_pix_fmt; DecoderConfig _video_decoder_config; + int _device_id = 0; }; #endif \ No newline at end of file diff --git a/rocAL/rocAL_hip/CMakeLists.txt b/rocAL/rocAL_hip/CMakeLists.txt index 32c960c2f..e2e78d2b9 100644 --- a/rocAL/rocAL_hip/CMakeLists.txt +++ b/rocAL/rocAL_hip/CMakeLists.txt @@ -33,12 +33,16 @@ list(APPEND rocAL_HIP_SOURCES rocal_hip_kernels.cpp box_encoder_hip.cpp ) +set (rocDecode_UTIL_SOURCES + ${ROCM_PATH}/share/rocdecode/utils/resize_kernels.cpp + ${ROCM_PATH}/share/rocdecode/utils/colorspace_kernels.cpp +) set_source_files_properties(${rocAL_HIP_SOURCES} PROPERTIES HIP_SOURCE_PROPERTY_FORMAT 1) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17") -add_library(${PROJECT_NAME} OBJECT ${rocAL_HIP_SOURCES}) +add_library(${PROJECT_NAME} OBJECT ${rocAL_HIP_SOURCES} ${rocDecode_UTIL_SOURCES}) set_target_properties(${PROJECT_NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON) target_compile_definitions(${PROJECT_NAME} PRIVATE __HIP_PLATFORM_AMD__) target_link_libraries(${PROJECT_NAME} hip::device) diff --git a/rocAL/source/api/rocal_api_data_loaders.cpp b/rocAL/source/api/rocal_api_data_loaders.cpp index 4da1bb385..4cd87aba3 100644 --- a/rocAL/source/api/rocal_api_data_loaders.cpp +++ b/rocAL/source/api/rocal_api_data_loaders.cpp @@ -149,6 +149,19 @@ auto convert_decoder_mode = [](RocalDecodeDevice decode_mode) { } }; +auto convert_video_decoder_type = [](RocalDecoderType decoder_type) { + switch (decoder_type) { + case ROCAL_DECODER_VIDEO_FFMPEG_SW: + return DecoderType::FFMPEG_SW_DECODE; + case ROCAL_DECODER_VIDEO_FFMPEG_HW: + return DecoderType::FFMPEG_HW_DECODE; + case ROCAL_DECODER_VIDEO_ROCDECODE: + return DecoderType::ROCDEC_VIDEO_DECODE; + default: + THROW("Unsupported video decoder type" + TOSTR(decoder_type)) + } +}; + auto convert_last_batch_policy = [](RocalLastBatchPolicy last_batch_policy) { switch (last_batch_policy) { case ROCAL_LAST_BATCH_FILL: @@ -1621,6 +1634,7 @@ rocalVideoFileSource( bool shuffle, bool is_output, bool loop, + RocalDecoderType rocal_decoder_type, unsigned step, unsigned stride, bool file_list_frame_num, @@ -1641,12 +1655,8 @@ rocalVideoFileSource( stride = (stride == 0) ? 1 : stride; VideoProperties video_prop; - DecoderType decoder_type; + DecoderType decoder_type = convert_video_decoder_type(rocal_decoder_type); find_video_properties(video_prop, source_path, file_list_frame_num); - if (rocal_decode_device == RocalDecodeDevice::ROCAL_HW_DECODE) - decoder_type = DecoderType::FFMPEG_HARDWARE_DECODE; - else - decoder_type = DecoderType::FFMPEG_SOFTWARE_DECODE; auto [color_format, tensor_layout, dims, num_of_planes] = convert_color_format_sequence(rocal_color_format, context->user_batch_size(), video_prop.height, video_prop.width, sequence_length); auto decoder_mode = convert_decoder_mode(rocal_decode_device); @@ -1687,6 +1697,7 @@ rocalVideoFileSourceSingleShard( bool shuffle, bool is_output, bool loop, + RocalDecoderType rocal_decoder_type, unsigned step, unsigned stride, bool file_list_frame_num, @@ -1713,12 +1724,8 @@ rocalVideoFileSourceSingleShard( stride = (stride == 0) ? 1 : stride; VideoProperties video_prop; - DecoderType decoder_type; + DecoderType decoder_type = convert_video_decoder_type(rocal_decoder_type); find_video_properties(video_prop, source_path, file_list_frame_num); - if (rocal_decode_device == RocalDecodeDevice::ROCAL_HW_DECODE) - decoder_type = DecoderType::FFMPEG_HARDWARE_DECODE; - else - decoder_type = DecoderType::FFMPEG_SOFTWARE_DECODE; auto [color_format, tensor_layout, dims, num_of_planes] = convert_color_format_sequence(rocal_color_format, context->user_batch_size(), video_prop.height, video_prop.width, sequence_length); auto decoder_mode = convert_decoder_mode(rocal_decode_device); @@ -1760,6 +1767,7 @@ rocalVideoFileResize( bool shuffle, bool is_output, bool loop, + RocalDecoderType rocal_decoder_type, unsigned step, unsigned stride, bool file_list_frame_num, @@ -1786,12 +1794,8 @@ rocalVideoFileResize( stride = (stride == 0) ? 1 : stride; VideoProperties video_prop; - DecoderType decoder_type; + DecoderType decoder_type = convert_video_decoder_type(rocal_decoder_type); find_video_properties(video_prop, source_path, file_list_frame_num); - if (rocal_decode_device == RocalDecodeDevice::ROCAL_HW_DECODE) - decoder_type = DecoderType::FFMPEG_HARDWARE_DECODE; - else - decoder_type = DecoderType::FFMPEG_SOFTWARE_DECODE; auto [color_format, tensor_layout, dims, num_of_planes] = convert_color_format_sequence(rocal_color_format, context->user_batch_size(), video_prop.height, video_prop.width, sequence_length); auto decoder_mode = convert_decoder_mode(rocal_decode_device); @@ -1913,6 +1917,7 @@ rocalVideoFileResizeSingleShard( bool shuffle, bool is_output, bool loop, + RocalDecoderType rocal_decoder_type, unsigned step, unsigned stride, bool file_list_frame_num, @@ -1945,12 +1950,8 @@ rocalVideoFileResizeSingleShard( stride = (stride == 0) ? 1 : stride; VideoProperties video_prop; - DecoderType decoder_type; + DecoderType decoder_type = convert_video_decoder_type(rocal_decoder_type); find_video_properties(video_prop, source_path, file_list_frame_num); - if (rocal_decode_device == RocalDecodeDevice::ROCAL_HW_DECODE) - decoder_type = DecoderType::FFMPEG_HARDWARE_DECODE; - else - decoder_type = DecoderType::FFMPEG_SOFTWARE_DECODE; auto [color_format, tensor_layout, dims, num_of_planes] = convert_color_format_sequence(rocal_color_format, context->user_batch_size(), video_prop.height, video_prop.width, sequence_length); auto decoder_mode = convert_decoder_mode(rocal_decode_device); diff --git a/rocAL/source/decoders/video/ffmpeg_video_decoder.cpp b/rocAL/source/decoders/video/ffmpeg_video_decoder.cpp index 75f8a364b..fce261eab 100644 --- a/rocAL/source/decoders/video/ffmpeg_video_decoder.cpp +++ b/rocAL/source/decoders/video/ffmpeg_video_decoder.cpp @@ -28,7 +28,7 @@ THE SOFTWARE. #ifdef ROCAL_VIDEO FFmpegVideoDecoder::FFmpegVideoDecoder(){}; -int FFmpegVideoDecoder::seek_frame(AVRational avg_frame_rate, AVRational time_base, unsigned frame_number) { +int FFmpegVideoDecoder::SeekFrame(AVRational avg_frame_rate, AVRational time_base, unsigned frame_number) { auto seek_time = av_rescale_q((int64_t)frame_number, av_inv_q(avg_frame_rate), AV_TIME_BASE_Q); int64_t select_frame_pts = av_rescale_q((int64_t)frame_number, av_inv_q(avg_frame_rate), time_base); int ret = av_seek_frame(_fmt_ctx, -1, seek_time, AVSEEK_FLAG_BACKWARD); @@ -53,7 +53,7 @@ VideoDecoder::Status FFmpegVideoDecoder::Decode(unsigned char *out_buffer, unsig return Status::FAILED; } } - int select_frame_pts = seek_frame(_video_stream->avg_frame_rate, _video_stream->time_base, seek_frame_number); + int select_frame_pts = SeekFrame(_video_stream->avg_frame_rate, _video_stream->time_base, seek_frame_number); if (select_frame_pts < 0) { ERR("Error in seeking frame..Unable to seek the given frame in a video"); return Status::FAILED; @@ -128,7 +128,7 @@ VideoDecoder::Status FFmpegVideoDecoder::Decode(unsigned char *out_buffer, unsig } // Initialize will open a new decoder and initialize the context -VideoDecoder::Status FFmpegVideoDecoder::Initialize(const char *src_filename) { +VideoDecoder::Status FFmpegVideoDecoder::Initialize(const char *src_filename, int device_id) { VideoDecoder::Status status = Status::OK; int ret; AVDictionary *opts = NULL; @@ -192,7 +192,7 @@ VideoDecoder::Status FFmpegVideoDecoder::Initialize(const char *src_filename) { return status; } -void FFmpegVideoDecoder::release() { +void FFmpegVideoDecoder::Release() { if (_video_dec_ctx) avcodec_free_context(&_video_dec_ctx); if (_fmt_ctx) @@ -200,6 +200,6 @@ void FFmpegVideoDecoder::release() { } FFmpegVideoDecoder::~FFmpegVideoDecoder() { - release(); + Release(); } #endif diff --git a/rocAL/source/decoders/video/hardware_video_decoder.cpp b/rocAL/source/decoders/video/hardware_video_decoder.cpp index 1909de658..7555c2913 100644 --- a/rocAL/source/decoders/video/hardware_video_decoder.cpp +++ b/rocAL/source/decoders/video/hardware_video_decoder.cpp @@ -21,19 +21,18 @@ THE SOFTWARE. */ #include "decoders/video/hardware_video_decoder.h" - #include "pipeline/commons.h" #include #ifdef ROCAL_VIDEO HardWareVideoDecoder::HardWareVideoDecoder(){}; -int HardWareVideoDecoder::seek_frame(AVRational avg_frame_rate, AVRational time_base, unsigned frame_number) { +int HardWareVideoDecoder::SeekFrame(AVRational avg_frame_rate, AVRational time_base, unsigned frame_number) { auto seek_time = av_rescale_q((int64_t)frame_number, av_inv_q(avg_frame_rate), AV_TIME_BASE_Q); int64_t select_frame_pts = av_rescale_q((int64_t)frame_number, av_inv_q(avg_frame_rate), time_base); int ret = av_seek_frame(_fmt_ctx, -1, seek_time, AVSEEK_FLAG_BACKWARD); if (ret < 0) { - ERR("HardWareVideoDecoder::seek_frame Error in seeking frame. Unable to seek the given frame in a video"); + ERR("HardWareVideoDecoder::SeekFrame Error in seeking frame. Unable to seek the given frame in a video"); return ret; } return select_frame_pts; @@ -61,7 +60,7 @@ VideoDecoder::Status HardWareVideoDecoder::Decode(unsigned char *out_buffer, uns return Status::FAILED; } } - int select_frame_pts = seek_frame(_video_stream->avg_frame_rate, _video_stream->time_base, seek_frame_number); + int select_frame_pts = SeekFrame(_video_stream->avg_frame_rate, _video_stream->time_base, seek_frame_number); if (select_frame_pts < 0) { ERR("HardWareVideoDecoder::Decode Error in seeking frame. Unable to seek the given frame in a video"); return Status::FAILED; @@ -149,7 +148,7 @@ VideoDecoder::Status HardWareVideoDecoder::Decode(unsigned char *out_buffer, uns } // Initialize will open a new decoder and initialize the context -VideoDecoder::Status HardWareVideoDecoder::Initialize(const char *src_filename) { +VideoDecoder::Status HardWareVideoDecoder::Initialize(const char *src_filename, int device_id) { VideoDecoder::Status status = Status::OK; int ret; AVDictionary *opts = NULL; @@ -242,7 +241,7 @@ VideoDecoder::Status HardWareVideoDecoder::Initialize(const char *src_filename) return status; } -void HardWareVideoDecoder::release() { +void HardWareVideoDecoder::Release() { if (_video_dec_ctx) avcodec_free_context(&_video_dec_ctx); if (_fmt_ctx) @@ -250,6 +249,6 @@ void HardWareVideoDecoder::release() { } HardWareVideoDecoder::~HardWareVideoDecoder() { - release(); + Release(); } #endif diff --git a/rocAL/source/decoders/video/rocdec_video_decoder.cpp b/rocAL/source/decoders/video/rocdec_video_decoder.cpp new file mode 100644 index 000000000..581675ce3 --- /dev/null +++ b/rocAL/source/decoders/video/rocdec_video_decoder.cpp @@ -0,0 +1,180 @@ +/* +Copyright (c) 2025 Advanced Micro Devices, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include +#include "decoders/video/rocdec_video_decoder.h" + +#ifdef ROCAL_VIDEO +#if ENABLE_HIP && ENABLE_ROCDECODE + +// callback function to flush last frames and save it to file when reconfigure happens +int ReconfigureFlushCallback(void *p_viddec_obj, uint32_t flush_mode, void *p_user_struct) { + int n_frames_flushed = 0; + if ((p_viddec_obj == nullptr) || (p_user_struct == nullptr)) return n_frames_flushed; + + RocVideoDecoder *viddec = static_cast (p_viddec_obj); + OutputSurfaceInfo *surf_info; + if (!viddec->GetOutputSurfaceInfo(&surf_info)) { + std::cerr << "Error: Failed to get Output Surface Info!" << std::endl; + return n_frames_flushed; + } + + uint8_t *pframe = nullptr; + int64_t pts; + while ((pframe = viddec->GetFrame(&pts))) { + if (flush_mode != RECONFIG_FLUSH_MODE_NONE) { + if (flush_mode == ReconfigFlushMode::RECONFIG_FLUSH_MODE_DUMP_TO_FILE) { + ReconfigDumpFileStruct *p_dump_file_struct = static_cast(p_user_struct); + if (p_dump_file_struct->b_dump_frames_to_file) { + viddec->SaveFrameToFile(p_dump_file_struct->output_file_name, pframe, surf_info); + } + } + } + // release and flush frame + viddec->ReleaseFrame(pts, true); + n_frames_flushed ++; + } + + return n_frames_flushed; +} + +// Initialize will open a new decoder and initialize the context +VideoDecoder::Status RocDecVideoDecoder::Initialize(const char *src_filename, int device_id) { + + VideoDecoder::Status status = Status::OK; + _src_filename = src_filename; + _device_id = device_id; + + // create rocDecoder and Demuxer for rocDecode + OutputSurfaceMemoryType mem_type = OUT_SURFACE_MEM_DEV_INTERNAL; // set to internal + _demuxer = std::make_shared(src_filename); + rocDecVideoCodec rocdec_codec_id = AVCodec2RocDecVideoCodec(_demuxer->GetCodecID()); + _rocvid_decoder = std::make_shared(device_id, mem_type, rocdec_codec_id, 0, nullptr, 0); + + if(!_rocvid_decoder->CodecSupported(device_id, rocdec_codec_id, _demuxer->GetBitDepth())) { + ERR("GPU doesn't support codec!") + return VideoDecoder::Status::FAILED; + } + + std::string device_name, gcn_arch_name; + int pci_bus_id, pci_domain_id, pci_device_id; + _rocvid_decoder->GetDeviceinfo(device_name, gcn_arch_name, pci_bus_id, pci_domain_id, pci_device_id); + std::cout << "info: Using GPU device " << device_id << " - " << device_name << "[" << gcn_arch_name << "] on PCI bus " << + std::setfill('0') << std::setw(2) << std::right << std::hex << pci_bus_id << ":" << std::setfill('0') << std::setw(2) << + std::right << std::hex << pci_domain_id << "." << pci_device_id << std::dec << std::endl; + + return status; +} + +// Seeks to the frame_number in the video file and decodes each frame in the sequence. +VideoDecoder::Status RocDecVideoDecoder::Decode(unsigned char *output_buffer_ptr, unsigned seek_frame_number, size_t sequence_length, size_t stride, int out_width, int out_height, int out_stride, AVPixelFormat out_pix_format) { + + VideoDecoder::Status status = Status::OK; + VideoSeekContext video_seek_ctx; + + // Reconfig the decoder + ReconfigDumpFileStruct reconfig_user_struct = { 0 }; + ReconfigParams reconfig_params = { 0 }; + reconfig_params.p_fn_reconfigure_flush = ReconfigureFlushCallback; + reconfig_params.reconfig_flush_mode = RECONFIG_FLUSH_MODE_NONE; + reconfig_params.p_reconfig_user_struct = &reconfig_user_struct; + _rocvid_decoder->SetReconfigParams(&reconfig_params); + + if (!_demuxer || !_rocvid_decoder || !output_buffer_ptr) { + ERR("Decoder is not initialized"); + return Status::FAILED; + } + if (!output_buffer_ptr || !(sequence_length|stride)) { + ERR("Invalid parameter passed"); + return Status::FAILED; + } + + int64_t pts = 0, dts = 0, requested_frame_dts = 0; + int n_video_bytes = 0, n_frame_returned = 0, n_frame = 0, pkg_flags = 0; + OutputSurfaceInfo *surf_info; + uint8_t *pvideo = nullptr; + int num_decoded_frames = sequence_length * stride; + + bool b_seek = true; // seek only for first frame in sequence + uint32_t image_size = out_height * out_stride * sizeof(uint8_t); + video_seek_ctx.seek_crit_ = SEEK_CRITERIA_FRAME_NUM; + video_seek_ctx.seek_mode_ = SEEK_MODE_PREV_KEY_FRAME; + VideoPostProcess post_process; + bool sequence_decoded = false; + do { + if (b_seek) { + video_seek_ctx.seek_frame_ = static_cast(seek_frame_number); + video_seek_ctx.seek_crit_ = SEEK_CRITERIA_FRAME_NUM; + video_seek_ctx.seek_mode_ = SEEK_MODE_PREV_KEY_FRAME; + _demuxer->Seek(video_seek_ctx, &pvideo, &n_video_bytes); + pts = video_seek_ctx.out_frame_pts_; + dts = video_seek_ctx.out_frame_dts_; + requested_frame_dts = video_seek_ctx.requested_frame_dts_; + b_seek = false; + _rocvid_decoder->FlushAndReconfigure(); + } else { + _demuxer->Demux(&pvideo, &n_video_bytes, &pts, &dts); + } + // Treat 0 bitstream size as end of stream indicator + if (n_video_bytes == 0) { + pkg_flags |= ROCDEC_PKT_ENDOFSTREAM; + } + n_frame_returned = _rocvid_decoder->DecodeFrame(pvideo, n_video_bytes, pkg_flags, pts); + if (!n_frame && !_rocvid_decoder->GetOutputSurfaceInfo(&surf_info)) { + ERR("Failed to get Output Surface Info!"); + return Status::FAILED; + } + // Take the min of sequence length and num frames to avoid out of bounds memory error + int required_n_frames = std::min(static_cast(sequence_length), n_frame_returned); + for (int i = 0; i < required_n_frames; i++) { + uint8_t *pframe = _rocvid_decoder->GetFrame(&pts); + if (dts >= requested_frame_dts) { + if (n_frame % stride == 0) { + post_process.ColorConvertYUV2RGB(pframe, surf_info, output_buffer_ptr, _output_format, _rocvid_decoder->GetStream()); + output_buffer_ptr += image_size; + } + n_frame++; + } + // release frame + _rocvid_decoder->ReleaseFrame(pts); + if (n_frame == num_decoded_frames) { + sequence_decoded = true; + break; + } + } + + if (sequence_decoded) { + if (hipStreamSynchronize(_rocvid_decoder->GetStream()) != hipSuccess) + THROW("hipStreamSynchronize failed: ") + break; + } + } while (n_video_bytes); + + return status; +} + +RocDecVideoDecoder::~RocDecVideoDecoder() { + Release(); +} + +#endif +#endif diff --git a/rocAL/source/decoders/video/video_decoder_factory.cpp b/rocAL/source/decoders/video/video_decoder_factory.cpp index 6442d020d..6af76d109 100644 --- a/rocAL/source/decoders/video/video_decoder_factory.cpp +++ b/rocAL/source/decoders/video/video_decoder_factory.cpp @@ -23,6 +23,7 @@ THE SOFTWARE. #include "decoders/video/ffmpeg_video_decoder.h" #include "decoders/video/hardware_video_decoder.h" +#include "decoders/video/rocdec_video_decoder.h" #include "decoders/video/video_decoder.h" #include "pipeline/commons.h" @@ -30,10 +31,14 @@ THE SOFTWARE. #ifdef ROCAL_VIDEO std::shared_ptr create_video_decoder(DecoderConfig config) { switch (config.type()) { - case DecoderType::FFMPEG_SOFTWARE_DECODE: + case DecoderType::FFMPEG_SW_DECODE: return std::make_shared(); - case DecoderType::FFMPEG_HARDWARE_DECODE: + case DecoderType::FFMPEG_HW_DECODE: return std::make_shared(); +#if ENABLE_ROCDECODE + case DecoderType::ROCDEC_VIDEO_DECODE: + return std::make_shared(); +#endif default: THROW("Unsupported decoder type " + TOSTR(config.type())); } diff --git a/rocAL/source/loaders/video/video_loader.cpp b/rocAL/source/loaders/video/video_loader.cpp index e576abefb..fed6eaf47 100644 --- a/rocAL/source/loaders/video/video_loader.cpp +++ b/rocAL/source/loaders/video/video_loader.cpp @@ -102,6 +102,12 @@ void VideoLoader::set_output(Tensor *output_tensor) { _output_mem_size = ((_output_tensor->info().data_size() + 8) & ~7); // Making output size as a multiple of 8 to support vectorized load and store in RPP } +void VideoLoader::set_gpu_device_id(int device_id) { + if (device_id < 0) + THROW("invalid device_id passed to loader"); + _device_id = device_id; +} + void VideoLoader::stop_internal_thread() { _internal_thread_running = false; _stopped = true; @@ -124,7 +130,7 @@ void VideoLoader::initialize(ReaderConfig reader_cfg, DecoderConfig decoder_cfg, _decoder_keep_original = decoder_keep_original; _video_loader = std::make_shared(); try { - _video_loader->create(reader_cfg, decoder_cfg, _batch_size); + _video_loader->create(reader_cfg, decoder_cfg, _batch_size, _device_id); } catch (const std::exception &e) { de_init(); throw; diff --git a/rocAL/source/loaders/video/video_loader_sharded.cpp b/rocAL/source/loaders/video/video_loader_sharded.cpp index a0d81c60e..e8868b2ca 100644 --- a/rocAL/source/loaders/video/video_loader_sharded.cpp +++ b/rocAL/source/loaders/video/video_loader_sharded.cpp @@ -83,6 +83,7 @@ void VideoLoaderSharded::initialize(ReaderConfig reader_cfg, DecoderConfig decod // Initialize loader modules for (size_t idx = 0; idx < _shard_count; idx++) { _loaders[idx]->set_output(_output_tensor); + _loaders[idx]->set_gpu_device_id(idx); reader_cfg.set_shard_count(_shard_count); reader_cfg.set_shard_id(idx); _loaders[idx]->initialize(reader_cfg, decoder_cfg, mem_type, batch_size, keep_orig_size); diff --git a/rocAL/source/loaders/video/video_read_and_decode.cpp b/rocAL/source/loaders/video/video_read_and_decode.cpp index 882d2f10f..7d6dde6aa 100644 --- a/rocAL/source/loaders/video/video_read_and_decode.cpp +++ b/rocAL/source/loaders/video/video_read_and_decode.cpp @@ -58,7 +58,7 @@ VideoReadAndDecode::~VideoReadAndDecode() { _video_decoder.clear(); } -void VideoReadAndDecode::create(ReaderConfig reader_config, DecoderConfig decoder_config, int batch_size) { +void VideoReadAndDecode::create(ReaderConfig reader_config, DecoderConfig decoder_config, int batch_size, int device_id) { _sequence_length = reader_config.get_sequence_length(); _stride = reader_config.get_frame_stride(); _video_prop = reader_config.get_video_properties(); @@ -72,6 +72,7 @@ void VideoReadAndDecode::create(ReaderConfig reader_config, DecoderConfig decode _actual_decoded_width.resize(_batch_size); _actual_decoded_height.resize(_batch_size); _video_decoder_config = decoder_config; + _device_id = device_id; // Initialize the ffmpeg context once for the video files. size_t i = 0; @@ -83,7 +84,7 @@ void VideoReadAndDecode::create(ReaderConfig reader_config, DecoderConfig decode video_map video_instance; video_instance._video_map_idx = atoi(substrings[0].c_str()); video_instance._is_decoder_instance = true; - if (_video_decoder[i]->Initialize(substrings[1].c_str()) != VideoDecoder::Status::OK) + if (_video_decoder[i]->Initialize(substrings[1].c_str(), _device_id) != VideoDecoder::Status::OK) video_instance._is_decoder_instance = false; _video_file_name_map.insert(std::pair(_video_names[i], video_instance)); } @@ -184,7 +185,7 @@ VideoReadAndDecode::load(unsigned char *buff, std::vector substrings; char delim = '#'; substring_extraction(itr->first, delim, substrings); - if (_video_decoder[video_idx]->Initialize(substrings[1].c_str()) == VideoDecoder::Status::OK) { + if (_video_decoder[video_idx]->Initialize(substrings[1].c_str(), _device_id) == VideoDecoder::Status::OK) { itr->second._video_map_idx = video_idx; itr->second._is_decoder_instance = true; } diff --git a/rocAL/source/pipeline/master_graph.cpp b/rocAL/source/pipeline/master_graph.cpp index 7a5f40a6f..39b17f5d5 100644 --- a/rocAL/source/pipeline/master_graph.cpp +++ b/rocAL/source/pipeline/master_graph.cpp @@ -1198,6 +1198,7 @@ TensorListVector* MasterGraph::create_webdataset_reader( } TensorListVector* MasterGraph::create_video_label_reader(const char *source_path, MetaDataReaderType reader_type, unsigned sequence_length, unsigned frame_step, unsigned frame_stride, bool file_list_frame_num) { + if (_meta_data_reader) THROW("A metadata reader has already been created") if (_augmented_meta_data) THROW("Metadata can only have a single output") diff --git a/rocAL_pybind/amd/rocal/readers.py b/rocAL_pybind/amd/rocal/readers.py index 2182fb525..f91158487 100644 --- a/rocAL_pybind/amd/rocal/readers.py +++ b/rocAL_pybind/amd/rocal/readers.py @@ -189,7 +189,8 @@ def caffe2(path, bbox=False, stick_to_shard=False, pad_last_batch=False): def video(sequence_length, file_list_frame_num=False, file_root="", image_type=types.RGB, num_shards=1, random_shuffle=False, step=1, stride=1, decoder_mode=types.SOFTWARE_DECODE, enable_frame_num=False, enable_timestamps=False, file_list="", stick_to_shard=False, pad_last_batch=False, - file_list_include_preceding_frame=False, normalized=False, skip_vfr_check=False, last_batch_policy=types.LAST_BATCH_FILL, pad_last_batch_repeated=False, shard_size=-1): + file_list_include_preceding_frame=False, normalized=False, skip_vfr_check=False, + last_batch_policy=types.LAST_BATCH_FILL, pad_last_batch_repeated=False, shard_size=-1, decoder_type=types.DECODER_VIDEO_FFMPEG_SW): """!Creates a VideoDecoder node for loading video sequences. @param sequence_length Number of frames in video sequence. @@ -209,6 +210,7 @@ def video(sequence_length, file_list_frame_num=False, file_root="", image_type=t @param file_list_include_preceding_frame Changes the behavior how file_list start and end frame timestamps are translated to a frame number. @param normalized Gets the output as normalized data. @param skip_vfr_check Skips the check for the variable frame rate (VFR) videos. + @param decoder_type Type of decoder used for video decoding, Currently supports FFmpeg/rocDecode @return list of loaded video sequences. """ @@ -233,6 +235,7 @@ def video(sequence_length, file_list_frame_num=False, file_root="", image_type=t "shuffle": random_shuffle, "is_output": False, "loop": False, + "rocal_decoder_type": decoder_type, "frame_step": step, "frame_stride": stride, "file_list_frame_num": file_list_frame_num, @@ -250,7 +253,8 @@ def video_resize(sequence_length, resize_width, resize_height, file_list_frame_n resize_longer=0, resize_shorter=0, max_size=[], enable_frame_num=False, enable_timestamps=False, file_list="", stick_to_shard=True, pad_last_batch=False, file_list_include_preceding_frame=False, normalized=False, skip_vfr_check=False, - last_batch_policy=types.LAST_BATCH_FILL, pad_last_batch_repeated=False, shard_size=-1): + last_batch_policy=types.LAST_BATCH_FILL, pad_last_batch_repeated=False, shard_size=-1, + decoder_type=types.DECODER_VIDEO_FFMPEG_SW): """!Creates a VideoDecoderResize node in the pipeline for loading and resizing video sequences. @param sequence_length Number of frames in video sequence. @@ -277,6 +281,7 @@ def video_resize(sequence_length, resize_width, resize_height, file_list_frame_n @param file_list_include_preceding_frame Specifies if file list includes preceding frames. @param normalized Gets the output as normalized data. @param skip_vfr_check Skips the check for the variable frame rate (VFR) videos. + @param decoder_type Type of decoder used for video decoding, Currently supports FFmpeg/rocDecode @returns loaded and resized video sequences and meta data. """ @@ -294,7 +299,7 @@ def video_resize(sequence_length, resize_width, resize_height, file_list_frame_n sharding_info = b.RocalShardingInfo(last_batch_policy, pad_last_batch_repeated, stick_to_shard, shard_size) kwargs_pybind_decoder = {"source_path": file_root, "color_format": image_type, "decoder_mode": decoder_mode, "shard_count": num_shards, "sequence_length": sequence_length, "resize_width": resize_width, "resize_height": resize_height, - "shuffle": random_shuffle, "is_output": False, "loop": False, "frame_step": step, "frame_stride": stride, + "shuffle": random_shuffle, "is_output": False, "loop": False, "rocal_decoder_type": decoder_type, "frame_step": step, "frame_stride": stride, "file_list_frame_num": file_list_frame_num, "scaling_mode": scaling_mode, "max_size": max_size, "resize_shorter": resize_shorter, "resize_longer": resize_longer, "interpolation_type": interpolation_type, "sharding_info": sharding_info} videos = b.videoDecoderResize( diff --git a/rocAL_pybind/amd/rocal/types.py b/rocAL_pybind/amd/rocal/types.py index ab871c30b..060fc2fe0 100644 --- a/rocAL_pybind/amd/rocal/types.py +++ b/rocAL_pybind/amd/rocal/types.py @@ -77,6 +77,7 @@ from rocal_pybind.types import DECODER_HW_JEPG from rocal_pybind.types import DECODER_VIDEO_FFMPEG_SW from rocal_pybind.types import DECODER_VIDEO_FFMPEG_HW +from rocal_pybind.types import DECODER_VIDEO_ROCDECODE # RocalResizeScalingMode from rocal_pybind.types import SCALING_MODE_DEFAULT diff --git a/rocAL_pybind/getrocALwheelname.py b/rocAL_pybind/getrocALwheelname.py index ce1f1ddfc..d8d72d195 100644 --- a/rocAL_pybind/getrocALwheelname.py +++ b/rocAL_pybind/getrocALwheelname.py @@ -21,4 +21,4 @@ def wheel_name(**kwargs): # Version updates - IMP: Change in version requires to match top level CMakeLists.txt ## * getrocALWheelname.py ## * setup.py -print(wheel_name(name='amd-rocal', version='2.2.0'), end='') +print(wheel_name(name='amd-rocal', version='2.3.0'), end='') diff --git a/rocAL_pybind/rocal_pybind.cpp b/rocAL_pybind/rocal_pybind.cpp index 85370f730..f94562e88 100644 --- a/rocAL_pybind/rocal_pybind.cpp +++ b/rocAL_pybind/rocal_pybind.cpp @@ -713,6 +713,7 @@ py::class_(m, "rocalListOfTensorList") .value("DECODER_HW_JEPG", ROCAL_DECODER_HW_JPEG) .value("DECODER_VIDEO_FFMPEG_SW", ROCAL_DECODER_VIDEO_FFMPEG_SW) .value("DECODER_VIDEO_FFMPEG_HW", ROCAL_DECODER_VIDEO_FFMPEG_HW) + .value("DECODER_VIDEO_ROCDECODE", ROCAL_DECODER_VIDEO_ROCDECODE) .export_values(); py::enum_(types_m, "RocalExternalSourceMode", "Rocal Extrernal Source Mode") .value("EXTSOURCE_FNAME", ROCAL_EXTSOURCE_FNAME) diff --git a/rocAL_pybind/setup.py b/rocAL_pybind/setup.py index 72368162c..14804eb3b 100644 --- a/rocAL_pybind/setup.py +++ b/rocAL_pybind/setup.py @@ -44,7 +44,7 @@ def has_ext_modules(self): name='amd-rocal', description='AMD ROCm Augmentation Library Python Bindings', url='https://github.com/ROCm/rocAL', - version='2.2.0', + version='2.3.0', author='AMD', license='MIT', packages=find_packages(where='@TARGET_NAME@'), diff --git a/tests/cpp_api/video_tests/README.md b/tests/cpp_api/video_tests/README.md index 892064e6d..3a2a70fcd 100644 --- a/tests/cpp_api/video_tests/README.md +++ b/tests/cpp_api/video_tests/README.md @@ -54,7 +54,7 @@ SAVE_FRAMES : Saves the output frames or avi files in the build/output_frames fo DEVICE : CPU:0/GPU:1 device is supported. -HARDWARE_DECODE_MODE : Uses Hardware decoder if set to true. +DECODER_TYPE : Determines type of decoder used for video decoding. Currently supports ffmpeg_sw:0/ffmpeg_hw:1/rocDecode:2. SHUFFLE : Shuffles the sequences if set to true. @@ -105,6 +105,13 @@ To test with VideoReaderResize pass reader_case as 2: Also RESIZE_WIDTH and RESIZE_HEIGHT can be changed in testScript.sh +**NOTE**: + +To run the Video reader with rocDecode decoder, the following arguments are to be modified in testScript.sh + +* DEVICE=1 +* DECODER_TYPE=2 +
**Example 2: Sequence Reader** diff --git a/tests/cpp_api/video_tests/testScript.sh b/tests/cpp_api/video_tests/testScript.sh index de731d37d..2932aa382 100755 --- a/tests/cpp_api/video_tests/testScript.sh +++ b/tests/cpp_api/video_tests/testScript.sh @@ -37,7 +37,7 @@ make SAVE_FRAMES=1 # (save_frames:on/off) RGB=1 # (rgb:1/gray:0) DEVICE=0 # (cpu:0/gpu:1) -HARDWARE_DECODE_MODE=0 # (hardware_decode_mode:on/off) +DECODER_TYPE=0 # (ffmpeg_sw:0/ffmpeg_hw=1/rocDecode=2) SHUFFLE=0 # (shuffle:on/off) BATCH_SIZE=1 # Number of sequences per batch @@ -53,10 +53,10 @@ ENABLE_FRAME_NUMBER=0 # outputs the starting frame numbers of the sequenc ENABLE_TIMESTAMPS=0 # outputs timestamps of the frames in the batch ENABLE_SEQUENCE_REARRANGE=0 # rearranges the frames in the sequence NOTE: The order needs to be set in the video_tests.cpp -echo ./video_tests "$INPUT_PATH" $READER_CASE $DEVICE $HARDWARE_DECODE_MODE $BATCH_SIZE $SEQUENCE_LENGTH $STEP $STRIDE \ +echo ./video_tests "$INPUT_PATH" $READER_CASE $DEVICE $DECODER_TYPE $BATCH_SIZE $SEQUENCE_LENGTH $STEP $STRIDE \ $RGB $SAVE_FRAMES $SHUFFLE $RESIZE_WIDTH $RESIZE_HEIGHT $FILELIST_FRAMENUM \ $ENABLE_METADATA $ENABLE_FRAME_NUMBER $ENABLE_TIMESTAMPS $ENABLE_SEQUENCE_REARRANGE -./video_tests "$INPUT_PATH" $READER_CASE $DEVICE $HARDWARE_DECODE_MODE $BATCH_SIZE $SEQUENCE_LENGTH $STEP $STRIDE \ +./video_tests "$INPUT_PATH" $READER_CASE $DEVICE $DECODER_TYPE $BATCH_SIZE $SEQUENCE_LENGTH $STEP $STRIDE \ $RGB $SAVE_FRAMES $SHUFFLE $RESIZE_WIDTH $RESIZE_HEIGHT $FILELIST_FRAMENUM \ $ENABLE_METADATA $ENABLE_FRAME_NUMBER $ENABLE_TIMESTAMPS $ENABLE_SEQUENCE_REARRANGE diff --git a/tests/cpp_api/video_tests/video_tests.cpp b/tests/cpp_api/video_tests/video_tests.cpp index f9136ab10..1299b8f85 100644 --- a/tests/cpp_api/video_tests/video_tests.cpp +++ b/tests/cpp_api/video_tests/video_tests.cpp @@ -92,13 +92,13 @@ int main(int argc, const char **argv) { bool enable_timestamps = true; bool enable_sequence_rearrange = false; bool is_output = true; - unsigned hardware_decode_mode = 0; + unsigned decoder_type = 0; if (argc >= argIdx + MIN_ARG_COUNT) reader_case = atoi(argv[++argIdx]); if (argc >= argIdx + MIN_ARG_COUNT) processing_device = atoi(argv[++argIdx]); if (argc >= argIdx + MIN_ARG_COUNT) - hardware_decode_mode = atoi(argv[++argIdx]); + decoder_type = atoi(argv[++argIdx]); if (argc >= argIdx + MIN_ARG_COUNT) input_batch_size = atoi(argv[++argIdx]); if (argc >= argIdx + MIN_ARG_COUNT) @@ -128,7 +128,18 @@ int main(int argc, const char **argv) { if (argc >= argIdx + MIN_ARG_COUNT) enable_sequence_rearrange = atoi(argv[++argIdx]) ? true : false; - auto decoder_mode = ((hardware_decode_mode == 1) ? RocalDecodeDevice::ROCAL_HW_DECODE : RocalDecodeDevice::ROCAL_SW_DECODE); + auto decoder_mode = ((decoder_type > 0) ? RocalDecodeDevice::ROCAL_HW_DECODE : RocalDecodeDevice::ROCAL_SW_DECODE); + RocalDecoderType rocal_decoder_type = RocalDecoderType::ROCAL_DECODER_VIDEO_FFMPEG_SW; + if (decoder_type == 1) { + rocal_decoder_type = RocalDecoderType::ROCAL_DECODER_VIDEO_FFMPEG_HW; + } else if (decoder_type == 2) { + rocal_decoder_type = RocalDecoderType::ROCAL_DECODER_VIDEO_ROCDECODE; + if (processing_device != 1) { + std::cerr << "Setting the processing device to GPU for rocDecode decoder\n"; + processing_device = 1; + } + } + if (!IsPathExist(source_path)) { std::cout << "\nThe folder/file path does not exist\n"; return -1; @@ -174,7 +185,7 @@ int main(int argc, const char **argv) { switch (reader_case) { default: { std::cout << "\nVIDEO READER\n"; - input1 = rocalVideoFileSource(handle, source_path, color_format, decoder_mode, shard_count, sequence_length, shuffle, is_output, false, frame_step, frame_stride, file_list_frame_num); + input1 = rocalVideoFileSource(handle, source_path, color_format, decoder_mode, shard_count, sequence_length, shuffle, is_output, false, rocal_decoder_type, frame_step, frame_stride, file_list_frame_num); break; } case 2: { @@ -183,7 +194,7 @@ int main(int argc, const char **argv) { std::cerr << "\n[ERR]Resize width and height are passed as NULL values\n"; return -1; } - input1 = rocalVideoFileResize(handle, source_path, color_format, decoder_mode, shard_count, sequence_length, resize_width, resize_height, shuffle, is_output, false, frame_step, frame_stride, file_list_frame_num); + input1 = rocalVideoFileResize(handle, source_path, color_format, decoder_mode, shard_count, sequence_length, resize_width, resize_height, shuffle, is_output, false, rocal_decoder_type, frame_step, frame_stride, file_list_frame_num); break; } case 3: {