diff --git a/CHANGELOG.md b/CHANGELOG.md index bfc9e3478..ad6d6cee5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,20 @@ 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.5.0 +## rocDecode 1.6.0 for ROCm 7.2.1 ### Changed * Updated libdrm path configuration and libva version requirements for ROCm and TheRock platforms +### Added +* Logging control. Message output from the core components is now controlled by the logging level threshold, which can be set by an environment variable or other methods. +* rocdecode-host package - rocdecode-host library and samples + +### Resolved issues + +* Fixed the build error with videodecodepicfiles sample. +* Added error handling of sample app command option combination of memory type OUT_SURFACE_MEM_NOT_MAPPED and MD5 generation. + ## rocDecode 1.4.0 for ROCm 7.1.0 ### Added diff --git a/CMakeLists.txt b/CMakeLists.txt index d533a365a..a0af40e03 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,13 @@ elseif(ROCM_PATH) else() set(ROCM_PATH /opt/rocm CACHE PATH "Default ROCm installation path") endif() + +# Check if lib/rocm_sysdeps/lib exists in the ROCm path which indicates ROCm installation via TheRock +set(USING_THE_ROCK OFF) +if(EXISTS "${ROCM_PATH}/lib/rocm_sysdeps/lib") + set(USING_THE_ROCK ON) +endif() + # Set AMD Clang as default compiler set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED On) @@ -40,7 +47,7 @@ if (NOT DEFINED CMAKE_CXX_COMPILER) endif() # rocdecode Version -set(VERSION "1.5.0") +set(VERSION "1.7.0") # Set Project Version and Language project(rocdecode VERSION ${VERSION} LANGUAGES CXX) @@ -106,19 +113,11 @@ option(ROCDECODE_ENABLE_ROCPROFILER_REGISTER "Enable rocprofiler-register suppor # Add an option for enabling FFMPEG avcodec host-based decoder option(ROCDECODE_ENABLE_HOST_DECODER "Enable rocdecode-host-based decoder support" ON) +set (HIP_PLATFORM amd CACHE STRING "HIP platform") find_package(HIP QUIET) find_package(Libva QUIET) find_package(Libdrm_amdgpu QUIET) -# Check if lib/rocm_sysdeps/lib exists in the libdrm_amdgpu library path which indicates ROCm installation via TheRock -set(USING_THE_ROCK OFF) -if(LIBDRM_AMDGPU_LIBRARY) - string(FIND "${LIBDRM_AMDGPU_LIBRARY}" "lib/rocm_sysdeps/lib" ROCM_SYSDEPS_FOUND) - if(NOT ROCM_SYSDEPS_FOUND EQUAL -1) - set(USING_THE_ROCK ON) - endif() -endif() - # Find Ubuntu 22.04 file(READ "/etc/os-release" OS_RELEASE) string(REGEX MATCH "22.04" UBUNTU_22_FOUND ${OS_RELEASE}) @@ -127,23 +126,24 @@ string(REGEX MATCH "22.04" UBUNTU_22_FOUND ${OS_RELEASE}) # - Ubuntu 22.04 with standard ROCm installation: requires libva >= 1.16 # - TheRock installation (any OS): libva >= 1.8 is sufficient # - Other OS versions with standard ROCm: libva >= 1.8 is sufficient -if(UBUNTU_22_FOUND AND NOT USING_THE_ROCK) - if((${Libva_VERSION_MAJOR} GREATER_EQUAL 1) AND (${Libva_VERSION_MINOR} GREATER_EQUAL 16)) - message("-- ${White}\tLibva Version Supported${ColourReset}") - else() - set(Libva_FOUND FALSE) - message("-- ${Yellow}\tLibva Version Not Supported${ColourReset}") - endif() -else() - if((${Libva_VERSION_MAJOR} GREATER_EQUAL 1) AND (${Libva_VERSION_MINOR} GREATER_EQUAL 8)) - message("-- ${White}\tLibva Version Supported${ColourReset}") +if(Libva_FOUND) + if(UBUNTU_22_FOUND AND NOT USING_THE_ROCK) + if((${Libva_VERSION_MAJOR} GREATER_EQUAL 1) AND (${Libva_VERSION_MINOR} GREATER_EQUAL 16)) + message("-- ${White}\tLibva Version Supported${ColourReset}") + else() + set(Libva_FOUND FALSE) + message("-- ${Yellow}\tLibva Version Not Supported${ColourReset}") + endif() else() - set(Libva_FOUND FALSE) - message("-- ${Yellow}\tLibva Version Not Supported${ColourReset}") + if((${Libva_VERSION_MAJOR} GREATER_EQUAL 1) AND (${Libva_VERSION_MINOR} GREATER_EQUAL 8)) + message("-- ${White}\tLibva Version Supported${ColourReset}") + else() + set(Libva_FOUND FALSE) + message("-- ${Yellow}\tLibva Version Not Supported${ColourReset}") + endif() endif() endif() - if(ROCDECODE_ENABLE_ROCPROFILER_REGISTER) find_package(rocprofiler-register QUIET HINTS $ENV{rocprofiler_register_ROOT} $ENV{ROCPROFILER_REGISTER_ROOT} ${CMAKE_INSTALL_PREFIX} @@ -172,10 +172,10 @@ if(HIP_FOUND AND Libva_FOUND AND Libdrm_amdgpu_FOUND) endif() # local include files - include_directories(api src/rocdecode src/parser src/rocdecode/vaapi) + include_directories(${CMAKE_CURRENT_SOURCE_DIR}/api ${CMAKE_CURRENT_SOURCE_DIR}/src/rocdecode ${CMAKE_CURRENT_SOURCE_DIR}/src/parser ${CMAKE_CURRENT_SOURCE_DIR}/src/rocdecode/vaapi) # source files - file(GLOB_RECURSE SOURCES "./src/*.cpp") - list(FILTER SOURCES EXCLUDE REGEX "./src/rocdecode-host/*.*") + file(GLOB_RECURSE SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp") + list(FILTER SOURCES EXCLUDE REGEX "${CMAKE_CURRENT_SOURCE_DIR}/src/rocdecode-host/*.*") # rocdecode.so add_library(${PROJECT_NAME} SHARED ${SOURCES}) @@ -187,6 +187,10 @@ if(HIP_FOUND AND Libva_FOUND AND Libdrm_amdgpu_FOUND) set_target_properties(${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE CXX) set_target_properties(${PROJECT_NAME} PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR}) + if(USING_THE_ROCK) + set_target_properties(${PROJECT_NAME} PROPERTIES INSTALL_RPATH "$ORIGIN;$ORIGIN/rocm_sysdeps/lib" BUILD_WITH_INSTALL_RPATH TRUE) + endif() + # rocprofiler if (rocprofiler-register_FOUND) string(REPLACE "." ";" VERSION_LIST ${VERSION}) @@ -227,13 +231,13 @@ if(HIP_FOUND AND Libva_FOUND AND Libdrm_amdgpu_FOUND) # install rocdecode samples -- {ROCM_PATH}/share/rocdecode install(DIRECTORY cmake DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME} COMPONENT dev) install(DIRECTORY utils/rocvideodecode DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/utils COMPONENT dev) - install(DIRECTORY utils/ffmpegvideodecode DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/utils COMPONENT dev) install(FILES samples/videoDecode/CMakeLists.txt samples/videoDecode/README.md samples/videoDecode/videodecode.cpp DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/samples/videoDecode COMPONENT dev) install(FILES samples/videoDecodeRaw/CMakeLists.txt samples/videoDecodeRaw/README.md samples/videoDecodeRaw/videodecoderaw.cpp DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/samples/videoDecodeRaw COMPONENT dev) install(FILES samples/videoDecodeMem/CMakeLists.txt samples/videoDecodeMem/README.md samples/videoDecodeMem/videodecodemem.cpp DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/samples/videoDecodeMem COMPONENT dev) install(FILES samples/videoDecodePerf/CMakeLists.txt samples/videoDecodePerf/README.md samples/videoDecodePerf/videodecodeperf.cpp DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/samples/videoDecodePerf COMPONENT dev) install(FILES samples/videoDecodeRGB/CMakeLists.txt samples/videoDecodeRGB/README.md samples/videoDecodeRGB/videodecrgb.cpp DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/samples/videoDecodeRGB COMPONENT dev) install(FILES samples/videoDecodeBatch/CMakeLists.txt samples/videoDecodeBatch/README.md samples/videoDecodeBatch/videodecodebatch.cpp DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/samples/videoDecodeBatch COMPONENT dev) + install(FILES samples/rocdecDecode/CMakeLists.txt samples/rocdecDecode/README.md samples/rocdecDecode/rocdecdecode.cpp DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/samples/rocdecDecode COMPONENT dev) install(FILES samples/common.h DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/samples COMPONENT dev) install(FILES utils/md5.h DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/utils COMPONENT dev) install(FILES utils/video_demuxer.h DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/utils COMPONENT dev) @@ -243,6 +247,7 @@ if(HIP_FOUND AND Libva_FOUND AND Libdrm_amdgpu_FOUND) install(FILES utils/resize_kernels.h DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/utils COMPONENT dev) install(FILES utils/video_post_process.h DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/utils COMPONENT dev) install(FILES data/videos/AMD_driving_virtual_20-H265.mp4 data/videos/AMD_driving_virtual_20-H265.265 data/videos/AMD_driving_virtual_20-H264.mp4 data/videos/AMD_driving_virtual_20-H264.264 data/videos/AMD_driving_virtual_20-AV1.mp4 data/videos/AMD_driving_virtual_20-AV1.ivf data/videos/AMD_driving_virtual_20-VP9.ivf DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/video COMPONENT dev) + install(DIRECTORY data/frames/ DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/frames COMPONENT dev) # install license information - {ROCM_PATH}/share/doc/rocdecode set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") install(FILES ${CPACK_RESOURCE_FILE_LICENSE} DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT runtime) @@ -380,6 +385,9 @@ if(HIP_FOUND AND Libva_FOUND AND Libdrm_amdgpu_FOUND) # Debian package - Test set(CPACK_DEBIAN_TEST_PACKAGE_NAME "${PROJECT_NAME}-test" ) set(CPACK_DEBIAN_TEST_PACKAGE_DEPENDS "rocm-core, ${CPACK_DEBIAN_DEV_PACKAGE_NAME}" ) + # Debian package - Host + set(CPACK_DEBIAN_HOST_PACKAGE_NAME "${PROJECT_NAME}-host" ) + set(CPACK_DEBIAN_HOST_PACKAGE_DEPENDS "rocm-core, ${CPACK_DEBIAN_DEV_PACKAGE_NAME}" ) # RPM package set(CPACK_RPM_COMPONENT_INSTALL ON) set(CPACK_RPM_RUNTIME_PACKAGE_NAME "${PROJECT_NAME}") @@ -393,23 +401,28 @@ if(HIP_FOUND AND Libva_FOUND AND Libdrm_amdgpu_FOUND) # RPM package specific variable for Test set(CPACK_RPM_TEST_PACKAGE_NAME "${PROJECT_NAME}-test" ) set(CPACK_RPM_TEST_PACKAGE_REQUIRES "rocm-core, ${CPACK_RPM_DEV_PACKAGE_NAME}" ) + # RPM package specific variable for Host + set(CPACK_RPM_HOST_PACKAGE_NAME "${PROJECT_NAME}-host" ) + set(CPACK_RPM_HOST_PACKAGE_REQUIRES "rocm-core, ${CPACK_RPM_DEV_PACKAGE_NAME}" ) if(NOT ROCM_DEP_ROCMCORE) string(REGEX REPLACE ",? ?rocm-core," "" CPACK_RPM_RUNTIME_PACKAGE_REQUIRES ${CPACK_RPM_RUNTIME_PACKAGE_REQUIRES}) string(REGEX REPLACE ",? ?rocm-core-asan," "" CPACK_RPM_ASAN_PACKAGE_REQUIRES ${CPACK_RPM_ASAN_PACKAGE_REQUIRES}) string(REGEX REPLACE ",? ?rocm-core," "" CPACK_RPM_DEV_PACKAGE_REQUIRES ${CPACK_RPM_DEV_PACKAGE_REQUIRES}) string(REGEX REPLACE ",? ?rocm-core," "" CPACK_RPM_TEST_PACKAGE_REQUIRES ${CPACK_RPM_TEST_PACKAGE_REQUIRES}) + string(REGEX REPLACE ",? ?rocm-core," "" CPACK_RPM_HOST_PACKAGE_REQUIRES ${CPACK_RPM_TEST_PACKAGE_REQUIRES}) string(REGEX REPLACE ",? ?rocm-core," "" CPACK_DEBIAN_RUNTIME_PACKAGE_DEPENDS ${CPACK_DEBIAN_RUNTIME_PACKAGE_DEPENDS}) string(REGEX REPLACE ",? ?rocm-core-asan," "" CPACK_DEBIAN_ASAN_PACKAGE_DEPENDS ${CPACK_DEBIAN_ASAN_PACKAGE_DEPENDS}) string(REGEX REPLACE ",? ?rocm-core," "" CPACK_DEBIAN_DEV_PACKAGE_DEPENDS ${CPACK_DEBIAN_DEV_PACKAGE_DEPENDS}) string(REGEX REPLACE ",? ?rocm-core," "" CPACK_DEBIAN_TEST_PACKAGE_DEPENDS ${CPACK_DEBIAN_TEST_PACKAGE_DEPENDS}) + string(REGEX REPLACE ",? ?rocm-core," "" CPACK_DEBIAN_HOST_PACKAGE_DEPENDS ${CPACK_DEBIAN_TEST_PACKAGE_DEPENDS}) endif() if(ENABLE_ASAN_PACKAGING) # ASAN Package requires asan component with only libraries and license file set(CPACK_COMPONENTS_ALL asan) else() - set(CPACK_COMPONENTS_ALL runtime dev test) + set(CPACK_COMPONENTS_ALL runtime dev test host) endif() set(CPACK_DEBIAN_FILE_NAME "DEB-DEFAULT") @@ -456,6 +469,13 @@ if(HIP_FOUND AND Libva_FOUND AND Libdrm_amdgpu_FOUND) cpack_add_component(test DISPLAY_NAME "rocdecode Test Package" DESCRIPTION "High perf video decode SDK for AMD GPUs. rocdecode test") + + # make rocdecode-host for decoding on HOST only if FFMPEG is available + if(ROCDECODE_ENABLE_HOST_DECODER AND FFMPEG_FOUND) + cpack_add_component(host + DISPLAY_NAME "rocdecode host package" + DESCRIPTION "High perf video decode host SDK for AMD GPUs") + endif() else() message("-- ${Red}AMD ROCm ${PROJECT_NAME} -- unmet dependencies${ColourReset}") diff --git a/README.md b/README.md index e09899f01..0763b52c1 100644 --- a/README.md +++ b/README.md @@ -122,28 +122,30 @@ system. * Runtime package - `rocdecode` only provides the rocdecode library `librocdecode.so` * Development package - `rocdecode-dev`/`rocdecode-devel` provides the library, header files, and samples +* Host package - `rocdecode-host` provides rocdecode host decode * Test package - `rocdecode-test` provides CTest to verify installation #### Ubuntu ```shell - sudo apt install rocdecode rocdecode-dev rocdecode-test + sudo apt install rocdecode rocdecode-dev rocdecode-test rocdecode-host ``` #### RHEL ```shell - sudo yum install rocdecode rocdecode-devel rocdecode-test + sudo yum install rocdecode rocdecode-devel rocdecode-test rocdecode-host ``` #### SLES ```shell - sudo zypper install rocdecode rocdecode-devel rocdecode-test + sudo zypper install rocdecode rocdecode-devel rocdecode-test rocdecode-host ``` >[!NOTE] -> Package install auto installs all dependencies. +> * Package install auto installs all dependencies. +> * `rocdecode-host` package is optional package use in host video decode > [!IMPORTANT] > `RHEL`/`SLES` package install requires manual `FFMPEG` dev install diff --git a/cmake/FindLibva.cmake b/cmake/FindLibva.cmake index 2663a85f1..66581b196 100644 --- a/cmake/FindLibva.cmake +++ b/cmake/FindLibva.cmake @@ -21,9 +21,9 @@ # ################################################################################ -find_library(LIBVA_LIBRARY NAMES va HINTS /opt/amdgpu/lib/x86_64-linux-gnu /opt/amdgpu/lib64 /usr/lib/x86_64-linux-gnu /usr/lib64) -find_library(LIBVA_DRM_LIBRARY NAMES va-drm HINTS /opt/amdgpu/lib/x86_64-linux-gnu /opt/amdgpu/lib64 /usr/lib/x86_64-linux-gnu /usr/lib64) -find_path(LIBVA_INCLUDE_DIR NAMES va/va.h PATHS /opt/amdgpu/include /usr/include NO_DEFAULT_PATH) +find_library(LIBVA_LIBRARY NAMES va HINTS ${ROCM_PATH}/lib/rocm_sysdeps/lib /opt/amdgpu/lib/x86_64-linux-gnu /opt/amdgpu/lib64 /usr/lib/x86_64-linux-gnu /usr/lib64) +find_library(LIBVA_DRM_LIBRARY NAMES va-drm HINTS ${ROCM_PATH}/lib/rocm_sysdeps/lib /opt/amdgpu/lib/x86_64-linux-gnu /opt/amdgpu/lib64 /usr/lib/x86_64-linux-gnu /usr/lib64) +find_path(LIBVA_INCLUDE_DIR NAMES va/va.h PATHS ${ROCM_PATH}/lib/rocm_sysdeps/include /opt/amdgpu/include /usr/include NO_DEFAULT_PATH) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Libva DEFAULT_MSG LIBVA_INCLUDE_DIR LIBVA_LIBRARY) diff --git a/docker/rocDecode-on-ubuntu20.dockerfile b/docker/rocDecode-on-ubuntu20.dockerfile index 16256f7ba..8bdcdca0b 100644 --- a/docker/rocDecode-on-ubuntu20.dockerfile +++ b/docker/rocDecode-on-ubuntu20.dockerfile @@ -14,4 +14,4 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get -y install initramfs-tools libnuma-de WORKDIR /workspace # install rocDecode package -RUN DEBIAN_FRONTEND=noninteractive sudo apt install -y rocdecode rocdecode-dev rocdecode-test \ No newline at end of file +RUN DEBIAN_FRONTEND=noninteractive sudo apt install -y rocdecode rocdecode-dev rocdecode-test rocdecode-host \ No newline at end of file diff --git a/docker/rocDecode-on-ubuntu22.dockerfile b/docker/rocDecode-on-ubuntu22.dockerfile index 0634f913d..7100c1d6e 100644 --- a/docker/rocDecode-on-ubuntu22.dockerfile +++ b/docker/rocDecode-on-ubuntu22.dockerfile @@ -14,4 +14,4 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get -y install initramfs-tools libnuma-de WORKDIR /workspace # install rocDecode package -RUN DEBIAN_FRONTEND=noninteractive sudo apt install -y rocdecode rocdecode-dev rocdecode-test \ No newline at end of file +RUN DEBIAN_FRONTEND=noninteractive sudo apt install -y rocdecode rocdecode-dev rocdecode-test rocdecode-host \ No newline at end of file diff --git a/docs/doxygen/Doxyfile b/docs/doxygen/Doxyfile index b0aac5179..31047432a 100644 --- a/docs/doxygen/Doxyfile +++ b/docs/doxygen/Doxyfile @@ -1158,7 +1158,7 @@ FILTER_SOURCE_PATTERNS = # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. -USE_MDFILE_AS_MAINPAGE = README.md +USE_MDFILE_AS_MAINPAGE = # The Fortran standard specifies that for fixed formatted Fortran code all # characters from position 72 are to be considered as comment. A common diff --git a/docs/how-to/using-rocDecode-rocdecdecoder.rst b/docs/how-to/using-rocDecode-rocdecdecoder.rst new file mode 100644 index 000000000..981b08efb --- /dev/null +++ b/docs/how-to/using-rocDecode-rocdecdecoder.rst @@ -0,0 +1,245 @@ +.. meta:: + :description: Using the rocDecode core API + :keywords: rocDecode, AMD, ROCm, core API + +******************************************************************** +Using the rocdecdecode example +******************************************************************** + +rocDecode provides four core APIs exposed in the header files in the |apifolder|_ directory: + +| The rocDecode parser API, exposed in ``rocparser.h``. +| The hardware decoder API, exposed in ``rocdecode.h``. +| The software decoder API, exposed in ``rocdecode_host.h``. +| The bitstream reader API, exposed in ``roc_bitstream_reader.h``. + +The |rocdecdecode|_ sample demonstrates how to use the rocDecode core APIs in an application. It shows how to use the parser and both the hardware and software decoders. For information on how to use the bitstream reader API, see :doc:`Using the rocDecode bitstream reader API <./using-rocDecode-bitstream>`. + +The sample decodes raw elementary video frame files as input and produces individually decoded frames in YUV format as output. The input can be one individual frame file or multiple frames from one or more video files. The individual frame files must be numbered in ascending order of frames. + +``rocdecdecode.cpp`` takes the following arguments: + +.. list-table:: + :widths: 10 60 30 + :header-rows: 1 + + * - Argument + - Description + - Note + + * - ``-i`` + - Path to the input video frame file or to frame folder. + - Required. + + * - ``-o`` + - Output path. Saves the decoded YUV frames to this folder. + - Optional. Decoded frames aren't saved by default. + + * - ``-d`` + - GPU device ID. Set it to 0 for the first device, 1 for the second device, 2 for the third device, and so on for each subsequent device. + - Optional. Set to 0 by default. + + * - ``-b`` + - Backend. Set it to 0 to use the hardware decoder on the GPU or to 1 to use the software decoder on the CPU. + - Optional. Set to 0 by default. + + + * - ``-c`` + - Codec. Set to 0 for HEVC, 1 for H264, 2 for AV1, 4 for VP9, 5 for VP8, or 6 for MJPEG. + - Optional. Set to 0 by default. + + * - ``-n`` + - Number of iterations for performance evaluation. + - Optional. Set to 1 by default. + + * - ``-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. + +The ``DecoderInfo`` struct defined in the sample is used to store user-supplied parameters as well as the decoder and parser handles. + +The memory type and the type of decoder is set by the specified backend. If the GPU (device) backend is selected, both a parser and a hardware decoder are created. If the CPU (host) backend is selected, only a software decoder is created: + +.. code:: cpp + + DecoderInfo dec_info; + [...] + int main(int argc, char** argv) { + [...] + dec_info.rocdec_codec_id = CodecTypeToRocDecVideoCodec(codec_type); + dec_info.dec_device_id = device_id; + dec_info.mem_type = (!backend) ? OUT_SURFACE_MEM_DEV_INTERNAL : OUT_SURFACE_MEM_HOST; + init(); + if (backend == DECODER_BACKEND_DEVICE) { + create_parser(dec_info); + create_decoder(dec_info); + } else { + create_decoder_host(dec_info); + } + [...] + } + +All applications need to register the ``pfn_sequence_callback`` and ``pfn_display_picture`` callbacks. Applications that use the parser must also register the ``pfn_decode_picture`` callback. + +When the GPU backend is selected, these callbacks are registered in the ``create_parser()`` function. ``create_parser`` also creates the parser using ``rocDecCreateVideoParser()``: + +.. code:: cpp + + void create_parser(DecoderInfo& dec_info) { + RocdecParserParams params = {}; + params.codec_type = dec_info.rocdec_codec_id; + params.max_num_decode_surfaces = 6; + params.max_display_delay = 1; + params.user_data = &dec_info; + params.pfn_sequence_callback = handle_video_sequence; + params.pfn_decode_picture = handle_picture_decode; + params.pfn_display_picture = handle_picture_display; + CHECK(rocDecCreateVideoParser(&dec_info.parser, ¶ms)); + } + +The ``create_decoder()`` function sets the decoder parameters and passes them to ``rocDecCreateDecoder()`` to create the hardware decoder: + +.. code:: cpp + + void create_decoder(DecoderInfo& dec_info) { + RocDecoderCreateInfo create_info = {}; + create_info.codec_type = dec_info.rocdec_codec_id; // user specified codec_type for raw files + [...] + CHECK(rocDecCreateDecoder(&dec_info.decoder, &create_info)); + } + +The ``create_decoder_host()`` function performs the same actions as ``create_decoder()``, but uses ``rocDecCreateDecoderHost()`` to create a software decoder. Because the parser isn't used with the software decoder, and because the software decoder uses different function calls, the callbacks for the software decoder are registered in ``create_decoder_host()``: + +.. code:: cpp + + void create_decoder_host(DecoderInfo& dec_info) { + RocDecoderHostCreateInfo create_info = {}; + create_info.codec_type = dec_info.rocdec_codec_id; + [...] + create_info.pfn_sequence_callback = handle_video_sequence_host; + create_info.pfn_display_picture = handle_picture_display_host; + CHECK(rocDecCreateDecoderHost(&dec_info.decoder, &create_info)); + dec_info.backend = DECODER_BACKEND_HOST; + } + +After the decoder and parser have been created, ``decode_frames`` is called. + +.. code:: cpp + + int main(int argc, char** argv) { + [...] + dec_info.dump_decoded_frames = dump_output_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); + } + [...] + } + +``decode_frames`` calls ``rocDecParseVideoData()`` or ``rocDecDecodeFrameHost()``, depending on the backend, to parse and decode the frames: + +.. code:: cpp + + void decode_frames(DecoderInfo& dec_info, const std::vector>& frames) { + // gpu backend using VCN + if (dec_info.backend == DECODER_BACKEND_DEVICE) { + for (int i=0; i < static_cast(frames.size()); ++i) { + RocdecSourceDataPacket packet = {}; + packet.payload_size = frames[i].size(); + packet.payload = frames[i].data(); + if (i == static_cast(frames.size() - 1)) { + packet.flags = ROCDEC_PKT_ENDOFPICTURE; // mark end_of_picture flag for last frame + } + CHECK(rocDecParseVideoData(dec_info.parser, &packet)); + } + } else if (dec_info.backend == DECODER_BACKEND_HOST) { + for (int i=0; i < static_cast(frames.size()); ++i) { + RocdecPicParamsHost pic_params = {}; + pic_params.bitstream_data_len = frames[i].size(); + pic_params.bitstream_data = frames[i].data(); + if (i == static_cast(frames.size() - 1)) { + pic_params.flags = ROCDEC_PKT_ENDOFPICTURE; // mark end_of_picture flag for last frame + } + CHECK(rocDecDecodeFrameHost(dec_info.decoder, &pic_params)); + } + } + } + +The registered callbacks are triggered during the calls to ``rocDecParseVideoData()`` and ``rocDecDecodeFrameHost()``. + +``pfn_decode_picture`` is triggered when a new frame is ready to be decoded, ``pfn_sequence_callback`` is triggered when a new sequence header is encountered, and ``pfn_display_picture`` is triggered when a frame has finished being decoded. + +``pfn_decode_picture`` needs to call ``rocDecDecodeFrame()`` or ``rocDecodeFrameHost()``, depending on the specified backend, to decode a frame. + +In ``rocdecdecode.cpp``, ``pfn_decode_picture`` calls ``handle_picture_decode()`` or ``handle_picture_decode_host()``, depending on the specified backend: + +.. code:: cpp + + int ROCDECAPI handle_picture_decode(void* user_data, RocdecPicParams* params) { + DecoderInfo *p_dec_info = static_cast(user_data); + CHECK(rocDecDecodeFrame(p_dec_info->decoder, params)); + return 1; + } + +``pfn_sequence_callback`` is triggered when a format change occurs or when a new sequence header is encountered. When this happens, the decoder is reconfigured to handle the new sequence or format. + +``pfn_sequence_callback`` needs to call ``rocDecReconfigureDecoder()`` or ``rocDecReconfigureDecoderHost()`` depending on the backend, to reconfigure the decoder. + +In the ``rocdecdecode.cpp`` sample, ``pfn_sequence_callback`` calls ``handle_video_sequence()`` or ``handle_video_sequence_host()``, depending on the specified backend: + +.. code:: cpp + + int ROCDECAPI handle_video_sequence(void* user_data, RocdecVideoFormat* format) { + DecoderInfo *p_dec_info = static_cast(user_data); + [...] + RocdecReconfigureDecoderInfo reconfig_params = {}; + reconfig_params.width = format->coded_width; + reconfig_params.height = format->coded_height; + reconfig_params.bit_depth_minus_8 = bitdepth_minus_8; + reconfig_params.num_decode_surfaces = format->min_num_decode_surfaces; + reconfig_params.target_width = target_width; + reconfig_params.target_height = target_height; + reconfig_params.display_rect.left = format->display_area.left; + reconfig_params.display_rect.right = format->display_area.right; + 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)); + [...] + return 1; + } + +``pfn_display_picture`` is triggered when a frame has been decoded. It needs to call ``rocDecGetVideoFrame()`` or ``rocDecGetVideoFrameHost()``, depending on the specified backend. + +``rocDecGetVideoFrame()`` and ``rocDecGetVideoFrameHost()`` map the video ID of the decoded frame to HIP. Calls to both these functions block until the frame is decoded and the memory mapping is complete. They return the HIP device pointer or the host memory pointer, depending on the backend specified, as well as information about the :doc:`output surface <../conceptual/rocDecode-memory-types>`. + +``pfn_display_picture`` calls ``handle_picture_display()`` or ``handle_handle_picture_display_host()``, depending on the specified backend, and saves the frames to file if the ``rocdecdecode`` was run with the ``-o`` option: + +From the ``rocdecdecode.cpp`` sample: + +.. code:: cpp + + int ROCDECAPI handle_picture_display(void* user_data, RocdecParserDispInfo* disp_info) { + DecoderInfo *p_dec_info = static_cast(user_data); + RocdecProcParams params = {}; + params.progressive_frame = disp_info->progressive_frame; + params.top_field_first = disp_info->top_field_first; + void* dev_mem_ptr[3] = { 0 }; + uint32_t pitch[3] = { 0 }; + CHECK(rocDecGetVideoFrame(p_dec_info->decoder, disp_info->picture_index, dev_mem_ptr, pitch, ¶ms)); + if (p_dec_info->dump_decoded_frames) { + save_frame_to_file(p_dec_info, dev_mem_ptr, pitch); + } + return 1; + } + +Once decoding is complete, ``rocDecDestroyVideoParser()`` needs to be called to destroy the parser, and either ``rocDecDestroyDecoderHost()`` or ``rocDecDestroyDecoder()`` needs to be called to destroy the decoder. + +.. |rocdecdecode| replace:: ``rocdecdecode`` +.. _rocdecdecode: https://github.com/ROCm/rocDecode/tree/develop/samples/rocdecDecode/README.md + +.. |apifolder| replace:: ``api/rocdecode/`` +.. _apifolder: https://github.com/ROCm/rocDecode/tree/develop/api/rocdecode + +.. |utilsfolder| replace:: ``utils`` folder +.. _utilsfolder: https://github.com/ROCm/rocDecode/tree/develop/utils diff --git a/docs/how-to/using-rocDecode-video-decoder.rst b/docs/how-to/using-rocDecode-video-decoder.rst index 83d6f500b..0b00f2db7 100644 --- a/docs/how-to/using-rocDecode-video-decoder.rst +++ b/docs/how-to/using-rocDecode-video-decoder.rst @@ -6,9 +6,10 @@ Using the rocDecode RocVideoDecoder ******************************************************************** -rocDecode provides two ways of decoding a video stream: using the rocDecode RocVideoDecoder on GPU or using the FFmpeg decoder on CPU. +rocDecode provides two methods fpr decoding a video stream: using the rocDecode RocVideoDecoder on the GPU or using the FFmpeg decoder on the CPU. -This topic covers how to decode a video stream using the RocVideoDecoder class in |roc_video_dec|_. The RocVideoDecode class provides high-level calls to the core APIs in the |apifolder|_ of the rocDecode GitHub repository. For information about the core APIs, see :doc:`Using the rocDecode core APIs <./using-rocdecode>`. + +This topic covers how to decode a video stream using the RocVideoDecoder class in |roc_video_dec|_. The RocVideoDecode class provides high-level calls to the core APIs in the |apifolder|_ of the rocDecode GitHub repository. For information about the core APIs, see :doc:`Using the rocDecode core APIs <../reference/rocDecode-core-APIs>`. The RocVideoDecoder takes a demultiplexed coded picture as input. The picture can be demultiplexed from a video stream using the :doc:`FFmpeg demultiplexer <./using-rocDecode-ffmpeg>`. @@ -86,12 +87,10 @@ To prevent the remaining frames in the buffers from being deleted along with the The |reconfig_struct|_ struct stores information on how to handle the reconfiguration. A callback, a user-defined flush mode, and a user-defined struct are passed to ``ReconfigParams_t``. The reconfiguration parameters are then passed to the decoder using ``SetReconfigParams``. -The reconfiguration parameters need to be defined prior to entering the decoding loop. - -For example, the reconfiguration structs are defined in |common|_ in the rocDecode samples and then used in ``videodecode.cpp``: - -.. code:: C++ +The reconfiguration parameters need to be defined prior to entering the decoding loop. For example, the reconfiguration structs are defined in |common|_ in the rocDecode samples and then used in ``videodecode.cpp`` +.. code:: cpp + typedef enum ReconfigFlushMode_enum { RECONFIG_FLUSH_MODE_NONE = 0x0, /**< Just flush to get the frame count */ RECONFIG_FLUSH_MODE_DUMP_TO_FILE = 0x1, /**< The remaining frames will be dumped to file in this mode */ @@ -104,7 +103,6 @@ For example, the reconfiguration structs are defined in |common|_ in the rocDeco void *md5_generator_handle; } ReconfigDumpFileStruct; - reconfig_params.p_fn_reconfigure_flush = ReconfigureFlushCallback; reconfig_user_struct.b_dump_frames_to_file = dump_output_frames; reconfig_user_struct.output_file_name = output_file_path; @@ -118,13 +116,8 @@ For example, the reconfiguration structs are defined in |common|_ in the rocDeco reconfig_params.p_reconfig_user_struct = &reconfig_user_struct; viddec.SetReconfigParams(&reconfig_params); - In the decode loop, the demultiplexed coded picture is passed to ``DecodeFrame``. Once the frame is decoded and processed, it is released with ``ReleaseFrame``. - - - - .. |videodecode| replace:: ``videodecode.cpp`` .. _videodecode: https://github.com/ROCm/rocDecode/tree/develop/samples/videoDecode/videodecode.cpp diff --git a/docs/how-to/using-rocDecode-videodecode-sample.rst b/docs/how-to/using-rocDecode-videodecode-sample.rst index bc7884b51..2a91a8d12 100644 --- a/docs/how-to/using-rocDecode-videodecode-sample.rst +++ b/docs/how-to/using-rocDecode-videodecode-sample.rst @@ -76,7 +76,6 @@ The ``videodecode.cpp`` sample lets the user choose which method to use through - Seek criteria and seek starting point - Optional. Set to 1 and the frame number to start demultiplexing from that specific frame. Set to 2 and the timestamp to start demultiplexing from that specific timestamp. The seek criteria and starting point must be comma-separated (``,``). Demultiplexing begins at the first frame by default. - * - ``-seek_mode`` - Seek mode - Optional. Set to 0 to seek to the previous keyframe. Set to 1 to seek to the exact frame. Seeks to previous keyframe by default. @@ -95,9 +94,6 @@ The FFMpeg demuxer is used to demultiplex the input stream unless the ``-no_ffmp VideoDemuxer *demuxer; demuxer = new VideoDemuxer(input_file_path.c_str()); - -.. code:: C++ - The ``GetCodecId`` and ``GetBitDepth`` functions are used to obtain the video stream's codec and bit depth. The ``AVCodec2RocDecVideoCodec`` utility function converts the codec returned from the demuxer to its corresponding ``rocDecVideoCodec_enum`` value. .. code:: C++ diff --git a/docs/how-to/using-rocdecode.rst b/docs/how-to/using-rocdecode.rst deleted file mode 100644 index 19f5225a8..000000000 --- a/docs/how-to/using-rocdecode.rst +++ /dev/null @@ -1,226 +0,0 @@ -.. meta:: - :description: Using rocDecode - :keywords: parse video, parse, decode, video decoder, video decoding, rocDecode, core APIs, AMD, ROCm - -******************************************************************** -Using the rocDecode core APIs -******************************************************************** - -rocDecode core APIs are available in the |apifolder|_ of the `rocDecode GitHub repository `_. - -.. note:: - - The rocDecode samples use the utility classes in the |utilsfolder|_ instead of the core APIs. For information about using the utility classes, see :doc:`Using rocDecode with the FFmpeg decoder <./using-rocDecode-ffmpeg>` and :doc:`Using rocDecode with the bitstream decoder <./using-rocDecode-bitstream>`. - - -API overview -==================================================== - -All rocDecode APIs are exposed in the header files ``rocdecode.h`` and ``rocparser.h``. You can find -these files in the ``api`` folder in the rocDecode repository. - -The samples use the ``RocVideoDecoder`` user class provided in ``roc_video_dec.h`` in the ``utils`` folder -of the rocDecode repository. - -A video parser (defined in ``rocparser.h``) is needed to extract and decode headers from the bitstream -in order to organize the data into a structured format for the hardware decoder. The parser is critical in -video decoding, as it controls the decoding and display of a bitstream's individual frames and fields. - -The parser object in ``rocparser.h`` has three main APIs: - -* ``rocDecCreateVideoParser()`` -* ``rocDecParseVideoData()`` -* ``rocDecDestroyVideoParser()`` - -Create a parser object -==================================================== - -The ``rocDecCreateVideoParser()`` API creates a video parser object for the codec that you specify. The -API takes ``max_num_decode_surfaces``, which determines the Decoded Picture Buffer (DPB) size for -decoding. When creating a parser object, the application must register certain callback functions with -the driver, which is called from the parser during decode. - - -* ``pfn_sequence_callback`` is called when the parser encounters a new sequence header. The parser - informs you of the minimum number of surfaces needed by the parser's DPB to successfully decode - the bitstream. In addition, the caller can set additional parameters, like ``max_display_delay``, to - control frame decoding and display. - -* The ``pfn_decode_picture`` callback function is triggered when a picture is set for decoding. - -* The ``pfn_display_picture`` callback function is triggered when a frame in display order is ready to be - consumed by the caller. - -* The ``pfn_get_sei_msg`` callback function is triggered when your Supplementation Enhancement - Information (SEI) message is parsed and returned to the caller. - - -Parse video data -==================================================== - -Elementary stream video packets extracted from the de-multiplexer are fed into the parser using the -``rocDecParseVideoData()`` API. - -During this call, the parser triggers the callbacks as it encounters a new sequence header, receives -compressed frame/field data ready to be decoded, or when it's ready to display a frame. If any of the -callbacks return a failure, it is propagated back to the application so the decoding can be ended -gracefully. - -Query decode capabilities -==================================================== - -The ``rocDecGetDecoderCaps()`` API allows you to query the capabilities of the underlying hardware -video decoder. Decoder capabilities usually include supported codecs, maximum resolution, and -bit depth. - - -The following pseudo-code illustrates the use of this API. The application handles the error -appropriately for non-supported decoder capabilities. - -.. code:: cpp - - RocdecDecodeCaps decode_caps; - memset(&decode_caps, 0, sizeof(decode_caps)); - decode_caps.codec_type = p_video_format->codec; - decode_caps.chroma_format = p_video_format->chroma_format; - decode_caps.bit_depth_minus_8 = p_video_format->bit_depth_luma_minus8; - - ROCDEC_API_CALL(rocDecGetDecoderCaps(&decode_caps)); - - if(!decode_caps.is_supported) { - ROCDEC_THROW("Rocdec:: Codec not supported on this GPU: ", ROCDEC_NOT_SUPPORTED); - return 0; - } - - if ((p_video_format->coded_width > decode_caps.max_width) || - (p_video_format->coded_height > decode_caps.max_height)) { - - std::ostringstream errorString; - errorString << std::endl - << "Resolution : " << p_video_format->coded_width << "x" << p_video_format->coded_height << std::endl - << "Max Supported (wxh) : " << decode_caps.max_width << "x" << decode_caps.max_height << std::endl - << "Resolution not supported on this GPU "; - - const std::string cErr = errorString.str(); - ROCDEC_THROW(cErr, ROCDEC_NOT_SUPPORTED); - return 0; - } - -Create a decoder -==================================================== - -``rocDecCreateDecoder()`` creates an instance of the hardware video decoder object and provides you -with a handle upon successful creation. Refer to the ``RocDecoderCreateInfo`` structure for information -about the parameters passed for creating the decoder. For example, -``RocDecoderCreateInfo::codec_type`` represents the codec type of the video. The decoder handle -returned by ``rocDecCreateDecoder()`` needs to be retained for the entire decode session because the -handle is passed along with the other decoding APIs. In addition, you can inform display or crop -dimensions along with this API. - -Decode the frame -==================================================== - -After de-multiplexing and parsing, you can decode bitstream data containing a frame/field using -hardware. - -Use the ``rocDecDecodeFrame()`` API to submit a new frame for hardware decoding. Underneath the -driver, the Video Acceleration API (VA-API) is used to submit compressed picture data to the driver. -The parser extracts all the necessary information from the bitstream and fills the ``RocdecPicParams`` -structure that's appropriate for the codec. The high-level ``RocVideoDecoder`` class connects the parser -and decoder used for all sample applications. - -The ``rocDecDecodeFrame()`` call takes the decoder handle and the pointer to the ``RocdecPicParams`` -structure and initiates the video decoding using VA-API. - -Query the decoding status -==================================================== - -After submitting a frame for decoding, you can call ``rocDecGetDecodeStatus()`` to query the decoding -status for a given frame. A structure pointer, ``RocdecDecodeStatus*``, is filled and returned. - -The API inputs are: - -* ``decoder_handle``: A ``RocDecoder`` handler, ``rocDecDecoderHandle``. -* ``pic_idx``: An `int` value for the ``picIdx`` for which you want a status in order to index of the picture. -* ``decode_status``: A pointer to ``RocdecDecodeStatus`` as a return value. - -Please note that this API makes a non-blocking call and returns the status of the frame associated with nPicIdx at the time of the call, -without waiting for the decoding to complete. The ``decode_status->decode_status`` can be either ``rocDecodeStatus_Success``, indicating that -the decoding has been completed, or ``rocDecodeStatus_InProgress``, which means that the decoding is still in progress. - -Prepare the decoded frame for further processing -==================================================== - -The decoded frames can be used for further postprocessing using ``rocDecGetVideoFrame()``. The -successful completion of ``rocDecGetVideoFrame()`` indicates that the decoding process is complete and -the device memory pointer is inter-opped into the ROCm HIP address space in order to further process -the decoded frame in device memory. Please note that the ``rocDecGetVideoFrame()`` API is a blocking call. -If the video frame associated with the pic_idx is not ready, the call will wait for the decoding to complete before mapping the video frame for use in HIP. -The caller gets the necessary information on the output surface, -such as YUV format, dimensions, and pitch from this call. In the high-level ``RocVideoDecoder`` class, we -provide four different surface type modes for the mapped surface, as specified in -``OutputSurfaceMemoryType``. - -.. code:: cpp - - typedef enum OutputSurfaceMemoryType_enum { - OUT_SURFACE_MEM_DEV_INTERNAL = 0, /**< Internal interopped decoded surface memory **/ - OUT_SURFACE_MEM_DEV_COPIED = 1, /**< decoded output will be copied to a separate device memory **/ - OUT_SURFACE_MEM_HOST_COPIED = 2 /**< decoded output will be copied to a separate host memory **/ - OUT_SURFACE_MEM_NOT_MAPPED = 3 /**< decoded output is not available (interop won't be used): useful for decode only performance app*/ - } OutputSurfaceMemoryType; - - -If the mapped surface type is ``OUT_SURFACE_MEM_DEV_INTERNAL``, the direct pointer to the decoded -surface is provided. You need to call ``ReleaseFrame()`` (``RocVideoDecoder`` class). If the requested surface -type is ``OUT_SURFACE_MEM_DEV_COPIED`` or ``OUT_SURFACE_MEM_HOST_COPIED``, the internal -decoded frame is copied to another buffer, either in device memory or host memory. After that, it's -immediately unmapped for reuse by the ``RocVideoDecoder`` class. - -Refer to the ``RocVideoDecoder`` class and -`samples `_ for details on how to use -these APIs. - -Reconfigure the decoder -==================================================== - -You can call ``rocDecReconfigureDecoder()`` to reuse a single decoder for multiple clips or when the -video resolution changes during the decode. The API currently supports resolution changes, resize -parameter changes, and target area parameter changes for the same codec without destroying an -ongoing decoder instance. This can improve performance and reduce overall latency. - -The API inputs are: - -* ``decoder_handle``: A ``RocDecoder`` handler, ``rocDecDecoderHandle``. -* ``reconfig_params``: You need to specify the parameters for the changes in - ``RocdecReconfigureDecoderInfo``. The width and height used for reconfiguration cannot exceed the - values set for ``max_width`` and ``max_height``, defined in ``RocDecoderCreateInfo``. If you need to - change these values, you have to destroy and recreate the session. - -.. note:: - - You need to call ``rocDecReconfigureDecoder()`` during ``RocdecParserParams::pfn_sequence_callback``. - -Destroy the decoder -==================================================== - -You need to call the ``rocDecDestroyDecoder()`` to destroy the session and free up resources. - -The API input is: - -* ``decoder_handle``: A ``RocDecoder`` handler, ``rocDecDecoderHandle``. - -The API returns a ``RocdecDecodeStatus`` value. - -Destroy the parser -==================================================== - -You need to call ``rocDecDestroyVideoParser()`` to destroy the parser object and free up all allocated -resources at the end of video decoding. - - -.. |apifolder| replace:: ``api`` folder -.. _apifolder: https://github.com/ROCm/rocDecode/tree/develop/api - -.. |utilsfolder| replace:: ``utils`` folder -.. _utilsfolder: https://github.com/ROCm/rocDecode/tree/develop/utils diff --git a/docs/index.rst b/docs/index.rst index c5be0879d..148295465 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -33,11 +33,11 @@ The rocDecode public repository is located at `https://github.com/ROCm/rocDecode .. grid-item-card:: How to * :doc:`Understand the rocDecode videodecode.cpp sample <./how-to/using-rocDecode-videodecode-sample>` + * :doc:`Understand the rocDecode rocdecdecode.cpp sample <./how-to/using-rocDecode-rocdecdecoder>` * :doc:`Use the rocDecode RocVideoDecoder <./how-to/using-rocDecode-video-decoder>` * :doc:`Use the rocDecode FFmpeg demultiplexer <./how-to/using-rocDecode-ffmpeg>` - * :doc:`Use the rocDecode bitstream reader APIs <./how-to/using-rocDecode-bitstream>` - * :doc:`Use the rocDecode core APIs <./how-to/using-rocdecode>` - + * :doc:`Use the rocDecode bitstream reader APIs <./how-to/using-rocDecode-bitstream>` + .. grid-item-card:: Samples @@ -45,8 +45,14 @@ The rocDecode public repository is located at `https://github.com/ROCm/rocDecode .. grid-item-card:: Reference + * :doc:`The rocDecode core APIs <./reference/rocDecode-core-APIs>` + + * :doc:`The rocDecode parser API <./reference/rocDecode-parser>` + * :doc:`The rocDecode hardware decoder API <./reference/rocDecode-hw-decoder>` + * :doc:`The rocDecode software decoder API <./reference/rocDecode-sw-decoder>` + + * :doc:`rocDecode logging levels <./reference/rocDecode-logging-control>` * :doc:`rocDecode codec support and hardware capabilities <./reference/rocDecode-formats-and-architectures>` - * :doc:`rocDecode tested configurations <./reference/rocDecode-tested-configurations>` * :doc:`API library <../doxygen/html/files>` * :doc:`Functions <../doxygen/html/globals>` * :doc:`Data structures <../doxygen/html/annotated>` diff --git a/docs/install/rocDecode-package-install.rst b/docs/install/rocDecode-package-install.rst index 66ce6d814..a9e6f93bb 100644 --- a/docs/install/rocDecode-package-install.rst +++ b/docs/install/rocDecode-package-install.rst @@ -9,14 +9,15 @@ Installing rocDecode with the package installer Three rocDecode packages are available: * ``rocdecode``: The rocDecode runtime package. This is the basic rocDecode package. It must always be installed. -* ``rocdecode-dev``: The rocDecode development package. This package installs a full suite of libraries, header files, and samples. This package needs to be installed to use the rocDecode samples. -* ``rocdecode-test``: A test package that provides a CTest to verify the installation. This package needs to be installed to use the rocDecode samples. +* ``rocdecode-host``: The rocDecode software decoding package. This package must be installed to use the FFmpeg software decoder. +* ``rocdecode-dev``: The rocDecode development package. This package installs a full suite of libraries, header files, and samples. This package must be installed to use the rocDecode samples. +* ``rocdecode-test``: A test package that provides a CTest to verify the installation. This package must be installed to use the rocDecode samples. All the required prerequisites are installed when the package installation method is used. -Basic installation -======================================== +Basic installation without software decoding +============================================== Use the following commands to install only the rocDecode runtime package: @@ -41,10 +42,36 @@ Use the following commands to install only the rocDecode runtime package: sudo zypper install rocdecode +Basic installation with software decoding +============================================== + +Use the following commands to install the rocDecode runtime package and the host decoding package: + +.. tab-set:: + + .. tab-item:: Ubuntu + + .. code:: shell + + sudo apt install rocdecode rocdecode-host + + .. tab-item:: RHEL + + .. code:: shell + + sudo yum install rocdecode rocdecode-host + + .. tab-item:: SLES + + .. code:: shell + + sudo zypper install rocdecode rocdecode-host + + Complete installation ======================================== -Use the following commands to install ``rocdecode``, ``rocdecode-dev``, and ``rocdecode-test``: +Use the following commands to install ``rocdecode``, ``rocdecode-host``, ``rocdecode-dev``, and ``rocdecode-test``: .. tab-set:: @@ -52,16 +79,15 @@ Use the following commands to install ``rocdecode``, ``rocdecode-dev``, and ``ro .. code:: shell - sudo apt install rocdecode rocdecode-dev rocdecode-test + sudo apt install rocdecode rocdecode-host rocdecode-dev rocdecode-test .. tab-item:: RHEL .. code:: shell - sudo yum install rocdecode rocdecode-devel rocdecode-test - + sudo yum install rocdecode rocdecode-host rocdecode-devel rocdecode-test .. tab-item:: SLES .. code:: shell - sudo zypper install rocdecode rocdecode-devel rocdecode-test + sudo zypper install rocdecode rocdecode-host rocdecode-devel rocdecode-test diff --git a/docs/install/rocDecode-prerequisites.rst b/docs/install/rocDecode-prerequisites.rst index ac99253a5..6e9447a9f 100644 --- a/docs/install/rocDecode-prerequisites.rst +++ b/docs/install/rocDecode-prerequisites.rst @@ -6,7 +6,7 @@ rocDecode prerequisites ******************************************************************** -rocDecode requires ROCm 6.1 or later running on `accelerators based on the CDNA architecture `_. +rocDecode requires ROCm running on `GPUs based on the CDNA architecture `_. ROCm must be installed using the AMDGPU installer with the ``rocm`` usecase: @@ -26,7 +26,7 @@ The following prerequisites are installed by the package installer. If you are b .. note:: - To use the rocDecode samples, the ``rocdecode``, ``rocdecode-dev``, and ``rocdecode-test`` packages need to be installed. + To use the rocDecode samples, the ``rocdecode``, ``rocdecode-dev``, ``rocdecode-host``, and ``rocdecode-test`` packages need to be installed. If you're installing using the rocDecode source code, the ``rocDecode-setup.py`` script must be run with ``--developer`` set to ``ON``. @@ -37,4 +37,5 @@ The following prerequisites are installed by the package installer. If you are b * pkg-config * FFmpeg runtime and headers * libstdc++-12-dev for installations on Ubuntu 22.04 +* HIP, specifically the ``hip-dev`` package diff --git a/docs/reference/index.md b/docs/reference/index.md deleted file mode 100644 index 7327f221a..000000000 --- a/docs/reference/index.md +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - -# API reference - -This section provides technical descriptions and important information about the different rocDecode -APIs and library components. - -* {doc}`Library <../doxygen/html/files>` -* {doc}`Functions <../doxygen/html/globals>` -* {doc}`Data structures <../doxygen/html/annotated>` diff --git a/docs/reference/rocDecode-core-APIs.rst b/docs/reference/rocDecode-core-APIs.rst new file mode 100644 index 000000000..bc1da5778 --- /dev/null +++ b/docs/reference/rocDecode-core-APIs.rst @@ -0,0 +1,37 @@ +.. meta:: + :description: Using rocDecode + :keywords: parse video, parse, decode, video decoder, video decoding, rocDecode, core APIs, AMD, ROCm + +******************************************************************** +The rocDecode core APIs +******************************************************************** + +The rocDecode core APIs are intended for users who want to have full control of the decoding pipeline and interact with the core components instead of the utility classes. The :doc:`Using the rocDecode videodecode sample <../how-to/using-rocDecode-videodecode-sample>` provides an introduction to using the utility classes. + +The rocDecode core APIs are exposed in header files in the |apifolder|_ folder of the `rocDecode GitHub repository `_. + +:doc:`The rocDecode parser API <./rocDecode-parser>` is exposed in |rocparser|_. It contains functions that create and destroy the parser, as well as functions that parse the bitstream. + +:doc:`The hardware decoder API <./rocDecode-hw-decoder>` is exposed in |rocdecode|_. It contains functions that create, control, and destroy the decoder, as well as functions that decode the parsed frames on the GPU. + +:doc:`The software decoder API <./rocDecode-sw-decoder>` is exposed in |rocdecodehost|_. It contains the same functionality as ``rocdecode.h``, but all the operations are run on the host rather than the GPU. + +:doc:`The bitstream reader API <../how-to/using-rocDecode-bitstream>` is exposed in |bitstreamreader|_. It provides an alternative to the FFMpeg demuxer and contains a simple stream file parser that can read elementary files and IVF container files. + +.. |apifolder| replace:: ``api/rocdecode`` +.. _apifolder: https://github.com/ROCm/rocDecode/tree/develop/api/rocdecode + +.. |rocparser| replace:: ``api/rocdecode/rocparser.h`` +.. _rocparser: https://github.com/ROCm/rocDecode/tree/develop/api/rocdecode/rocparser.h + +.. |rocdecode| replace:: ``api/rocDecode/rocdecode.h`` +.. _rocdecode: https://github.com/ROCm/rocDecode/tree/develop/api/rocdecode/rocdecode.h + +.. |rocdecodehost| replace:: ``api/rocDecode/rocdecode_host.h`` +.. _rocdecodehost: https://github.com/ROCm/rocDecode/tree/develop/api/rocdecode/rocdecode_host.h + +.. |bitstreamreader| replace:: ``api/rocDecode/roc_bitstream_reader.h`` +.. _bitstreamreader: https://github.com/ROCm/rocDecode/tree/develop/api/rocdecode/roc_bitstream_reader.h + +.. |utilsfolder| replace:: ``utils`` folder +.. _utilsfolder: https://github.com/ROCm/rocDecode/tree/develop/utils diff --git a/docs/reference/rocDecode-hw-decoder.rst b/docs/reference/rocDecode-hw-decoder.rst new file mode 100644 index 000000000..32ed29ad8 --- /dev/null +++ b/docs/reference/rocDecode-hw-decoder.rst @@ -0,0 +1,62 @@ +.. meta:: + :description: The rocDecode hardware decoder + :keywords: decode, video decoder, video decoding, rocDecode, core APIs, AMD, ROCm + +******************************************************************** +The rocDecode hardware decoder API +******************************************************************** + +The rocDecode hardware decoder API exposed in |rocdecode|_ is used to decode frames that were parsed by :doc:`the rocDecode parser <./rocDecode-parser>`. + +Parsing parameters are stored in the ``RocDecoderCreateInfo`` struct and passed to ``rocDecCreateDecoder()`` to create a new decoder. ``rocDecCreateDecoder()`` returns a handle to the decoder. For example: + +.. code:: cpp + + RocDecoderCreateInfo create_info = {}; + create_info.codec_type = dec_info.rocdec_codec_id; // user specified codec_type for raw files + create_info.max_width = DEFAULT_WIDTH; + create_info.max_height = DEFAULT_HEIGHT; + create_info.width = DEFAULT_WIDTH; + create_info.height = DEFAULT_HEIGHT; + create_info.num_decode_surfaces = 6; + create_info.num_output_surfaces = 1; + rocDecCreateDecoder(&decoder_handle, &create_info); + + +``rocDecGetDecoderCaps()`` queries the capabilities of the underlying hardware video decoder. Decoder capabilities usually include supported codecs, maximum resolution, and +bit depth. + +``rocDecDecodeFrame()`` is used to submit frames for hardware decoding. This function must be called when the ``pfn_decode_picture`` callback is triggered in the ``rocDecParseVideoData()`` call. See :doc:`The rocDecode parser API <./rocDecode-parser>` for details about this call. + +``rocDecDecodeFrame()`` takes the decoder handle and the pointer to the ``RocdecPicParams()`` struct and initiates the video decoding using VA-API. ``RocdecPicParams`` is populated with the decoded frame information. + +The ``pfn_sequence_callback`` callback is triggered when a format change occurs or when a new sequence header is encountered. The implementation of ``pfn_sequence_callback`` must call ``rocDecReconfigureDecoder()`` to reconfigure the decoder to handle the new sequence or format. See :doc:`The rocDecode parser API <./rocDecode-parser>` for details about this callback. + +``rocDecGetDecodeStatus()`` can be called to query the decoding status of a frame. The result of the query is either ``rocDecodeStatus_Success``, if decoding is complete, or ``rocDecodeStatus_InProgress``, if decoding is still in progress. + +The ``pfn_display_picture`` callback is triggered when a frame has been decoded. The decoded frame can then be further processed in device memory. The implementation for this callback must call ``rocDecGetVideoFrame()`` to obtain the decoded frame's HIP device pointer. + +``rocDecGetVideoFrame()`` provides a way to access the decoded frame in HIP. This is a blocking call that only returns once frame decoding and memory mapping is complete. It returns the HIP device pointer as well as information about the :doc:`output surface type <../conceptual/rocDecode-memory-types>`. + +If the output surface type is ``OUT_SURFACE_MEM_DEV_INTERNAL``, meaning intermediate GPU memory, the direct pointer to the decoded surface is provided. If the requested surface +type is ``OUT_SURFACE_MEM_DEV_COPIED`` or ``OUT_SURFACE_MEM_HOST_COPIED``, the internal decoded frame is copied to another buffer, either in device memory or host memory. + +Once decoding is complete, ``rocDecDestroyVideoParser()`` and ``rocDecDestroyDecoder()`` must be called to destroy the parser and the decoding session, and free resources. + +.. |apifolder| replace:: ``api/rocdecode`` +.. _apifolder: https://github.com/ROCm/rocDecode/tree/develop/api/rocdecode + +.. |rocparser| replace:: ``api/rocdecode/rocparser.h`` +.. _rocparser: https://github.com/ROCm/rocDecode/tree/develop/api/rocdecode/rocparser.h + +.. |rocdecode| replace:: ``api/rocDecode/rocdecode.h`` +.. _rocdecode: https://github.com/ROCm/rocDecode/tree/develop/api/rocdecode/rocdecode.h + +.. |rocdecodehost| replace:: ``api/rocDecode/rocdecode_host.h`` +.. _rocdecodehost: https://github.com/ROCm/rocDecode/tree/develop/api/rocdecode/rocdecode_host.h + +.. |bitstreamreader| replace:: ``api/rocDecode/roc_bitstream_reader.h`` +.. _bitstreamreader: https://github.com/ROCm/rocDecode/tree/develop/api/rocdecode/roc_bitstream_reader.h + +.. |utilsfolder| replace:: ``utils`` folder +.. _utilsfolder: https://github.com/ROCm/rocDecode/tree/develop/utils diff --git a/docs/reference/rocDecode-logging-control.rst b/docs/reference/rocDecode-logging-control.rst new file mode 100644 index 000000000..4047e7c52 --- /dev/null +++ b/docs/reference/rocDecode-logging-control.rst @@ -0,0 +1,53 @@ +.. meta:: + :description: rocDecode logging controls + :keywords: rocDecode, core APIs, logging, AMD, ROCm + +******************************************************************** +rocDecode logging control +******************************************************************** + +rocDecode core components can be configured to output different levels of log messages during decoding. + +The log level can be changed by either setting the log level through the ``ROCDEC_LOG_LEVEL`` environment variable, or by calling the ``RocDecLogger::SetLogLevel()`` function in |commons|_. + +The logging levels are: + +| 0: Critical (Default level) +| 1: Error +| 2: Warning +| 3: Info +| 4: Debug + +The log level defines the maximum severity of log messages to output. For example, to output warning and error messages as well as critical messages, ``ROCDEC_LOG_LEVEL`` would need to be set to 2: + +.. code:: shell + + ROCDEC_LOG_LEVEL = 2 + +or + +.. code:: cpp + + SetLogLevel(2); + + +.. |apifolder| replace:: ``api/rocdecode`` +.. _apifolder: https://github.com/ROCm/rocDecode/tree/develop/api/rocdecode + +.. |rocparser| replace:: ``api/rocdecode/rocparser.h`` +.. _rocparser: https://github.com/ROCm/rocDecode/tree/develop/api/rocdecode/rocparser.h + +.. |rocdecode| replace:: ``api/rocDecode/rocdecode.h`` +.. _rocdecode: https://github.com/ROCm/rocDecode/tree/develop/api/rocdecode/rocdecode.h + +.. |rocdecodehost| replace:: ``api/rocDecode/rocdecode_host.h`` +.. _rocdecodehost: https://github.com/ROCm/rocDecode/tree/develop/api/rocdecode/rocdecode_host.h + +.. |bitstreamreader| replace:: ``api/rocDecode/roc_bitstream_reader.h`` +.. _bitstreamreader: https://github.com/ROCm/rocDecode/tree/develop/api/rocdecode/roc_bitstream_reader.h + +.. |utilsfolder| replace:: ``utils`` folder +.. _utilsfolder: https://github.com/ROCm/rocDecode/tree/develop/utils + +.. |commons| replace:: ``commons.h`` +.. _commons: https://github.com/ROCm/rocDecode/tree/develop/src/commons.h diff --git a/docs/reference/rocDecode-parser.rst b/docs/reference/rocDecode-parser.rst new file mode 100644 index 000000000..04b76d17b --- /dev/null +++ b/docs/reference/rocDecode-parser.rst @@ -0,0 +1,54 @@ +.. meta:: + :description: The rocDecode parser API + :keywords: parse video, parser, decode, video decoder, video decoding, rocDecode, core APIs, AMD, ROCm + +******************************************************************** +The rocDecode parser API +******************************************************************** + +The rocDecode parser API, exposed in |rocparser|_, is used to decode bitstreams and organize them in a structured format that can be consumed by the hardware decoder. + +The parser parameters are stored in the ``RocdecParserParams`` struct and passed to ``rocDecCreateVideoParser()`` to create a new parser. ``rocDecCreateVideoParser()`` returns a handle to the parser. For example: + +.. code:: cpp + + RocdecParserParams params = {}; + params.codec_type = rocdec_codec_id; + params.max_num_decode_surfaces = 6; + params.max_display_delay = 1; + params.user_data = &dec_info; + rocDecCreateVideoParser(&parser_handle, ¶ms); + +Elementary stream video packets extracted from the demultiplexer (demuxer) are passed to the parser using the ``RocdecSourceDataPacket`` struct. Packet information in ``RocdecSourceDataPacket`` is passed to ``rocDecParseVideoData()``. For example: + +.. code:: cpp + + RocdecSourceDataPacket packet = {}; + packet.payload_size = frames[i].size(); + packet.payload = frames[i].data(); + rocDecParseVideoData(parser_handle, &packet); + +Three callbacks must be registered when the parser is used: ``pfn_decode_picture``, ``pfn_sequence_callback``, and ``pfn_display_picture``. These callbacks are triggered in the ``rocDecParseVideoData()`` call. + +``pfn_decode_picture`` is triggered when a picture is ready for decoding. Its implementation must call ``rocDecDecodeFrame()`` from the hardware decoder API. + +``pfn_sequence_callback`` is triggered when a new sequence header is encountered or when there's a format change. Its implementation handles reconfiguring the decoder to handle the new frame format. Its implementation must call ``rocDecReconfigureDecoder()`` from the hardware decoder API. + +``pfn_display_picture`` is triggered when a frame has been decoded. Its implementation must call ``rocDecGetVideoFrame()`` from the hardware decoder API. + +A fourth callback, ``pfn_get_sei_msg``, is optional. ``pfn_get_sei_msg`` is triggered when a Supplementation Enhancement Information (SEI) message is parsed and returned to the caller. + +If any of the callbacks return an error, the error is propagated back to the application. + +Once the stream is fully decoded, ``rocDecDestroyVideoParser()`` must be called to destroy the parser object and free all allocated resources. + + + +.. |rocparser| replace:: ``rocparser.h`` +.. _rocparser: https://github.com/ROCm/rocDecode/tree/develop/api/rocdecode/rocparser.h + +.. |utilsfolder| replace:: ``utils`` folder +.. _utilsfolder: https://github.com/ROCm/rocDecode/tree/develop/utils + +.. |rocdecdecode| replace:: ``rocdecdecode.cpp`` +.. _rocdecdecode: https://github.com/ROCm/rocDecode/tree/develop/samples/rocdecDecode/rocdecdecode.cpp diff --git a/docs/reference/rocDecode-sw-decoder.rst b/docs/reference/rocDecode-sw-decoder.rst new file mode 100644 index 000000000..1377da095 --- /dev/null +++ b/docs/reference/rocDecode-sw-decoder.rst @@ -0,0 +1,61 @@ +.. meta:: + :description: The rocDecode software decoder + :keywords: decode, video decoder, video decoding, rocDecode, core APIs, AMD, ROCm + +******************************************************************** +The rocDecode software decoder API +******************************************************************** + +The rocDecode software decoder API exposed in |rocdecodehost|_ is used to decode frames that have been demultiplexed (demuxed) by :doc:`the FFmpeg demuxer <../how-to/using-rocDecode-ffmpeg>`. + +Decoding parameters are stored in the ``RocDecoderHostCreateInfo`` struct and passed to ``rocDecCreateDecoderHost()`` to create a new software decoder. ``rocDecCreateDecoderHost()`` returns a handle to the decoder. For example: + +.. code:: cpp + + RocDecoderHostCreateInfo create_info = {}; + create_info.codec_type = rocdec_codec_id; + create_info.num_decode_threads = 0; // default + create_info.max_width = DEFAULT_WIDTH; + create_info.max_height = DEFAULT_HEIGHT; + create_info.chroma_format = rocDecVideoChromaFormat_420; + create_info.output_format = rocDecVideoSurfaceFormat_P016; + create_info.bit_depth_minus_8 = 2; + create_info.num_output_surfaces = 1; + create_info.user_data = &dec_info; + rocDecCreateDecoderHost(&dec_info.decoder, &create_info); + +``rocDecGetDecoderCapsHost()`` queries the capabilities of the underlying software video decoder. Decoder capabilities usually include supported codecs, maximum resolution, and +bit depth. + +``rocDecDecodeFrameHost()`` is used to submit frames for software decoding. ``rocDecDecodeFrameHost()`` takes the decoder handle and the pointer to the ``RocdecPicParamsHost`` struct and initiates the video decoding. ``RocdecPicParamsHost`` is populated with the decoded frame information. + +The ``pfn_sequence_callback`` callback is triggered when a format change occurs or when a new sequence header is encountered. This callback must be registered in any application that uses the software decoder and its implementation must call ``rocDecReconfigureDecoderHost()`` to reconfigure the decoder to handle the new sequence or format. + +``rocDecGetDecodeStatusHost()`` can be called to query the decoding status of a frame. The result of the query is either ``rocDecodeStatus_Success``, if decoding is complete, or ``rocDecodeStatus_InProgress``, if decoding is still in progress. + +The ``pfn_display_picture`` callback is triggered when a frame has been decoded. This callback must be registered by any application that uses the software decoder and its implementation must call ``rocDecGetVideoFrameHost()``. ``rocDecGetVideoFrameHost()`` returns the decoded frame's host memory pointer. The decoded frame can then be further processed using this pointer. + +``rocDecGetVideoFrameHost()`` provides a way to access the decoded frame in host memory. This is a blocking call that only returns once both frame decoding and memory mapping are done. It returns the host memory pointer as well as information about the :doc:`output surface type <../conceptual/rocDecode-memory-types>`. + +If the output surface type is ``OUT_SURFACE_MEM_DEV_INTERNAL``, meaning intermediate GPU memory, the direct pointer to the decoded surface is provided. If the requested surface +type is ``OUT_SURFACE_MEM_DEV_COPIED`` or ``OUT_SURFACE_MEM_HOST_COPIED``, the internal decoded frame is copied to another buffer, either in device memory or host memory. + +Once decoding is complete, ``rocDecDestroyDecoderHost()`` must be called to destroy the decoder and free resources. + +.. |apifolder| replace:: ``api/rocdecode`` +.. _apifolder: https://github.com/ROCm/rocDecode/tree/develop/api/rocdecode + +.. |rocparser| replace:: ``api/rocdecode/rocparser.h`` +.. _rocparser: https://github.com/ROCm/rocDecode/tree/develop/api/rocdecode/rocparser.h + +.. |rocdecode| replace:: ``api/rocDecode/rocdecode.h`` +.. _rocdecode: https://github.com/ROCm/rocDecode/tree/develop/api/rocdecode/rocdecode.h + +.. |rocdecodehost| replace:: ``api/rocDecode/rocdecode_host.h`` +.. _rocdecodehost: https://github.com/ROCm/rocDecode/tree/develop/api/rocdecode/rocdecode_host.h + +.. |bitstreamreader| replace:: ``api/rocDecode/roc_bitstream_reader.h`` +.. _bitstreamreader: https://github.com/ROCm/rocDecode/tree/develop/api/rocdecode/roc_bitstream_reader.h + +.. |utilsfolder| replace:: ``utils`` folder +.. _utilsfolder: https://github.com/ROCm/rocDecode/tree/develop/utils diff --git a/docs/reference/rocDecode-tested-configurations.rst b/docs/reference/rocDecode-tested-configurations.rst deleted file mode 100644 index eeb6f1604..000000000 --- a/docs/reference/rocDecode-tested-configurations.rst +++ /dev/null @@ -1,24 +0,0 @@ -.. meta:: - :description: rocDecode tested configurations - :keywords: install, rocDecode, AMD, ROCm, tested configurations, prerequisites, dependencies, requirements - -******************************************************************** -rocDecode tested configurations -******************************************************************** - -rocDecode has been tested on the following operating system, software, and library versions: - -* Linux: - - * Ubuntu 20.04, 22.04 - * RHEL 8, 9 - * SLES 15-SP5 - -* ROCm: - - * rocm-core 6.2.0.60200-66 - * amdgpu-core 1:6.2.60200-2009582 - -* libva-dev 2.7.0-2, 2.14.0-1 -* mesa-amdgpu-va-drivers 1:24.2.0.60200-2009582 -* FFmpeg 4.2.7, 4.4.2-0 \ No newline at end of file diff --git a/docs/sphinx/_toc.yml.in b/docs/sphinx/_toc.yml.in index e5b1ff742..ec3374475 100644 --- a/docs/sphinx/_toc.yml.in +++ b/docs/sphinx/_toc.yml.in @@ -32,22 +32,32 @@ subtrees: - caption: How to entries: - file: how-to/using-rocDecode-videodecode-sample.rst - title: Understand the rocDecode videodecode sample + title: Understand the videodecode sample + - file: how-to/using-rocDecode-rocdecdecoder.rst + title: Understand the rocdecdecode.cpp sample - file: how-to/using-rocDecode-video-decoder.rst - title: Use the rocDecode RocVideoDecoder + title: Use RocVideoDecoder - file: how-to/using-rocDecode-ffmpeg.rst - title: Use the rocDecode FFmpeg demultiplexer + title: Use the FFmpeg demultiplexer - file: how-to/using-rocDecode-bitstream.rst - title: Use the rocDecode bitstream reader APIs - - file: how-to/using-rocdecode.rst - title: Use the rocDecode core APIs + title: Use the bitstream reader APIs - caption: Reference entries: + - file: reference/rocDecode-core-APIs.rst + title: Core APIs + subtrees: + - entries: + - file: reference/rocDecode-parser.rst + title: Parser API + - file: reference/rocDecode-hw-decoder.rst + title: Hardware decoder API + - file: reference/rocDecode-sw-decoder.rst + title: Software decoder API + - file: reference/rocDecode-logging-control.rst + title: Logging levels - file: reference/rocDecode-formats-and-architectures.rst title: rocDecode supported codecs and architectures - - file: reference/rocDecode-tested-configurations.rst - title: rocDecode tested configurations - file: doxygen/html/files title: rocDecode API library - file: doxygen/html/globals diff --git a/docs/tutorials/README.md b/docs/tutorials/README.md deleted file mode 100644 index 8da51d9f9..000000000 --- a/docs/tutorials/README.md +++ /dev/null @@ -1 +0,0 @@ -Placeholder to ensure docs/tutorials folder is created. Can remove once tutorial content is provided. diff --git a/docs/tutorials/rocDecode-samples.rst b/docs/tutorials/rocDecode-samples.rst index b377a46b8..c2176d3e3 100644 --- a/docs/tutorials/rocDecode-samples.rst +++ b/docs/tutorials/rocDecode-samples.rst @@ -10,9 +10,9 @@ rocDecode samples are available in the `rocDecode GitHub repository `. -All three rocDecode packages, ``rocDecode``, ``rocdecode-dev``, and ``rocdecode-test``, must be installed to use the rocDecode samples. +All rocDecode packages, ``rocDecode``, ``rocdecode-dev``, ``rocdecode-host``, and ``rocdecode-test``, must be installed to use the rocDecode samples. -If you're using a :doc:`package installer <../install/rocDecode-package-install>`, install ``rocdecode``, ``rocdecode-dev``, and ``rocdecode-test``. +If you're using a :doc:`package installer <../install/rocDecode-package-install>`, install ``rocdecode``, ``rocdecode-dev``, ``rocdecode-host``, and ``rocdecode-test``. If you're building and installing rocDecode from its :doc:`source code <../install/rocDecode-build-and-install>`, ``rocDecode-setup.py`` needs to be run with ``--developer`` set to ``ON``: diff --git a/samples/rocdecDecode/CMakeLists.txt b/samples/rocdecDecode/CMakeLists.txt index 46a193a5f..08f4f4cb7 100644 --- a/samples/rocdecDecode/CMakeLists.txt +++ b/samples/rocdecDecode/CMakeLists.txt @@ -61,30 +61,42 @@ else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -DNDEBUG -fPIC -Wall") endif() +set (HIP_PLATFORM amd CACHE STRING "HIP platform") find_package(HIP QUIET) find_package(FFmpeg QUIET) find_package(rocdecode QUIET) find_package(rocdecode-host 1.0.0 QUIET) -if(HIP_FOUND AND FFMPEG_FOUND AND rocdecode_FOUND AND rocdecode-host_FOUND) +if(HIP_FOUND AND rocdecode_FOUND) # HIP set(LINK_LIBRARY_LIST ${LINK_LIBRARY_LIST} hip::host) - # FFMPEG - include_directories(${AVUTIL_INCLUDE_DIR} ${AVCODEC_INCLUDE_DIR} - ${AVFORMAT_INCLUDE_DIR}) - set(LINK_LIBRARY_LIST ${LINK_LIBRARY_LIST} ${FFMPEG_LIBRARIES}) + + if(FFMPEG_FOUND) + # FFMPEG + include_directories(${AVUTIL_INCLUDE_DIR} ${AVCODEC_INCLUDE_DIR} + ${AVFORMAT_INCLUDE_DIR}) + set(LINK_LIBRARY_LIST ${LINK_LIBRARY_LIST} ${FFMPEG_LIBRARIES}) + endif() + if(rocdecode-host_FOUND) + # rocdecode-host + include_directories(${rocdecode-host_INCLUDE_DIR}) + set(LINK_LIBRARY_LIST ${LINK_LIBRARY_LIST} rocdecode::rocdecode-host) + endif() + # rocdecode and utils include_directories(${rocdecode_INCLUDE_DIR} ${ROCM_PATH}/lib) set(LINK_LIBRARY_LIST ${LINK_LIBRARY_LIST} rocdecode::rocdecode) - # rocdecode-host - include_directories(${rocdecode-host_INCLUDE_DIR}) - set(LINK_LIBRARY_LIST ${LINK_LIBRARY_LIST} rocdecode::rocdecode-host) # rocdecode # sample app exe list(APPEND SOURCES ${PROJECT_SOURCE_DIR} rocdecdecode.cpp) add_executable(${PROJECT_NAME} ${SOURCES}) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17") + if(FFMPEG_FOUND AND rocdecode-host_FOUND) + target_compile_definitions(${PROJECT_NAME} PUBLIC ENABLE_HOST_DECODE=1) + else() + target_compile_definitions(${PROJECT_NAME} PUBLIC ENABLE_HOST_DECODE=0) + endif() target_link_libraries(${PROJECT_NAME} ${LINK_LIBRARY_LIST}) else() message("-- ERROR!: ${PROJECT_NAME} excluded! please install all the dependencies and try again!") diff --git a/samples/rocdecDecode/rocdecdecode.cpp b/samples/rocdecDecode/rocdecdecode.cpp index 2bf624a36..e2e52532e 100644 --- a/samples/rocdecDecode/rocdecdecode.cpp +++ b/samples/rocdecDecode/rocdecdecode.cpp @@ -28,7 +28,10 @@ THE SOFTWARE. #include #include #include -#include +#include +#if ENABLE_HOST_DECODE + #include +#endif namespace fs = std::filesystem; @@ -62,7 +65,7 @@ __attribute__((visibility("hidden"))) inline void report_error( << file_name << ":" << line) << ... << std::forward(args)) << std::endl; - std::abort(); + std::exit(EXIT_FAILURE); } //hardcoding for this sample @@ -359,11 +362,12 @@ void create_decoder(DecoderInfo& dec_info) { // 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 = 2; + create_info.bit_depth_minus_8 = 0; create_info.num_output_surfaces = 1; CHECK(rocDecCreateDecoder(&dec_info.decoder, &create_info)); } +#if ENABLE_HOST_DECODE int ROCDECAPI handle_video_sequence_host(void* user_data, RocdecVideoFormatHost* format_host) { DecoderInfo *p_dec_info = static_cast(user_data); RocdecVideoFormat *format = &format_host->video_format; @@ -451,6 +455,7 @@ void create_decoder_host(DecoderInfo& dec_info) { CHECK(rocDecCreateDecoderHost(&dec_info.decoder, &create_info)); dec_info.backend = DECODER_BACKEND_HOST; } +#endif int ROCDECAPI handle_video_sequence(void* user_data, RocdecVideoFormat* format) { DecoderInfo *p_dec_info = static_cast(user_data); @@ -551,7 +556,9 @@ void decode_frames(DecoderInfo& dec_info, const std::vector } CHECK(rocDecParseVideoData(dec_info.parser, &packet)); } - } else if (dec_info.backend == DECODER_BACKEND_HOST) { + } +#if ENABLE_HOST_DECODE + else if (dec_info.backend == DECODER_BACKEND_HOST) { for (int i=0; i < static_cast(frames.size()); ++i) { RocdecPicParamsHost pic_params = {}; pic_params.bitstream_data_len = frames[i].size(); @@ -562,14 +569,18 @@ void decode_frames(DecoderInfo& dec_info, const std::vector CHECK(rocDecDecodeFrameHost(dec_info.decoder, &pic_params)); } } +#endif } void destroy_decoder(DecoderInfo& dec_info) { - if (dec_info.backend == DECODER_BACKEND_DEVICE) + if (dec_info.backend == DECODER_BACKEND_DEVICE) { CHECK(rocDecDestroyDecoder(dec_info.decoder)); + } +#if ENABLE_HOST_DECODE else if (dec_info.backend == DECODER_BACKEND_HOST) { CHECK(rocDecDestroyDecoderHost(dec_info.decoder)); } +#endif } void destroy_parser(DecoderInfo& dec_info) { @@ -582,7 +593,11 @@ void ShowHelpAndExit(const char *option = NULL) { << "-i Input File Path - required" << std::endl << "-o Output File Path - dumps output if requested; optional" << std::endl << "-d GPU device ID (0 for the first device, 1 for the second, etc.); optional; default: 0" << std::endl +#if ENABLE_HOST_DECODE << "-b backend (0 for GPU, 1 CPU-FFMpeg); optional; default: 0" << std::endl +#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 << "-n Number of iteration - specify the number of iterations for performance evaluation; optional; default: 1" << std::endl << "-m output_surface_memory_type - decoded surface memory; optional; default - 0" @@ -725,9 +740,12 @@ int main(int argc, char** argv) { if (backend == DECODER_BACKEND_DEVICE) { create_parser(dec_info); create_decoder(dec_info); - } else { + } +#if ENABLE_HOST_DECODE + else { create_decoder_host(dec_info); } +#endif dec_info.dump_decoded_frames = dump_output_frames; auto input_frames = read_frames(input_file_names); auto start = std::chrono::high_resolution_clock::now(); diff --git a/samples/videoDecode/CMakeLists.txt b/samples/videoDecode/CMakeLists.txt index c8a1bdb55..45558172e 100644 --- a/samples/videoDecode/CMakeLists.txt +++ b/samples/videoDecode/CMakeLists.txt @@ -61,6 +61,7 @@ else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -DNDEBUG -fPIC") endif() +set (HIP_PLATFORM amd CACHE STRING "HIP platform") find_package(HIP QUIET) find_package(rocdecode QUIET) find_package(rocdecode-host 1.0.0 QUIET) @@ -76,20 +77,24 @@ if(HIP_FOUND AND FFMPEG_FOUND AND rocdecode_FOUND AND Threads_FOUND AND rocprofi ${AVFORMAT_INCLUDE_DIR}) set(LINK_LIBRARY_LIST ${LINK_LIBRARY_LIST} ${FFMPEG_LIBRARIES}) # rocdecode and utils - include_directories (${rocdecode_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/../../utils ${CMAKE_CURRENT_SOURCE_DIR}/../../utils/rocvideodecode ${CMAKE_CURRENT_SOURCE_DIR}/../../utils/ffmpegvideodecode) + include_directories (${rocdecode_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/../../utils ${CMAKE_CURRENT_SOURCE_DIR}/../../utils/rocvideodecode) set(LINK_LIBRARY_LIST ${LINK_LIBRARY_LIST} rocdecode::rocdecode) # threads set(THREADS_PREFER_PTHREAD_FLAG ON) set(LINK_LIBRARY_LIST ${LINK_LIBRARY_LIST} Threads::Threads) # rocprofiler-register set(LINK_LIBRARY_LIST ${LINK_LIBRARY_LIST} rocprofiler-register::rocprofiler-register) - # rocdecode-host - list(APPEND SOURCES ${PROJECT_SOURCE_DIR} videodecode.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../../utils/rocvideodecode/roc_video_dec.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../../utils/ffmpegvideodecode/ffmpeg_video_dec.cpp) + # rocdecode + list(APPEND SOURCES ${PROJECT_SOURCE_DIR} videodecode.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../../utils/rocvideodecode/roc_video_dec.cpp) + # Add rocdecode host utils if host library found + if(rocdecode-host_FOUND) + include_directories (${CMAKE_CURRENT_SOURCE_DIR}/../../utils/ffmpegvideodecode) + list(APPEND SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../../utils/ffmpegvideodecode/ffmpeg_video_dec.cpp) + endif() # sample app exe add_executable(${PROJECT_NAME} ${SOURCES}) set(LINK_LIBRARY_LIST ${LINK_LIBRARY_LIST} rocdecode::rocdecode) if(rocdecode-host_FOUND) - # rocdecode-host include_directories(${rocdecode-host_INCLUDE_DIR}) set(LINK_LIBRARY_LIST ${LINK_LIBRARY_LIST} rocdecode::rocdecode-host) target_compile_definitions(${PROJECT_NAME} PUBLIC ENABLE_HOST_DECODE=1) diff --git a/samples/videoDecode/videodecode.cpp b/samples/videoDecode/videodecode.cpp index dc3277219..3cc9074ad 100644 --- a/samples/videoDecode/videodecode.cpp +++ b/samples/videoDecode/videodecode.cpp @@ -39,8 +39,10 @@ THE SOFTWARE. #include "video_demuxer.h" #include "rocdecode/roc_bitstream_reader.h" #include "roc_video_dec.h" -#include "ffmpeg_video_dec.h" #include "common.h" +#if ENABLE_HOST_DECODE + #include "ffmpeg_video_dec.h" +#endif //hardcoding for host based decoder creation if demux is not available #define DEFAULT_WIDTH 2912 @@ -364,7 +366,7 @@ int main(int argc, char **argv) { } for (int i = 0; i < n_frame_returned; i++) { pframe = viddec->GetFrame(&pts); - if (b_generate_md5) { + if (b_generate_md5 && pframe) { md5_generator->UpdateMd5ForFrame(pframe, surf_info); } if (dump_output_frames && mem_type != OUT_SURFACE_MEM_NOT_MAPPED) { diff --git a/samples/videoDecodeBatch/CMakeLists.txt b/samples/videoDecodeBatch/CMakeLists.txt index 4a90a3035..ad0fb9729 100644 --- a/samples/videoDecodeBatch/CMakeLists.txt +++ b/samples/videoDecodeBatch/CMakeLists.txt @@ -61,6 +61,7 @@ else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -DNDEBUG -fPIC") endif() +set (HIP_PLATFORM amd CACHE STRING "HIP platform") find_package(HIP QUIET) find_package(rocdecode QUIET) find_package(rocprofiler-register QUIET) diff --git a/samples/videoDecodeMem/CMakeLists.txt b/samples/videoDecodeMem/CMakeLists.txt index 46c6a2a4a..f02dce9c6 100644 --- a/samples/videoDecodeMem/CMakeLists.txt +++ b/samples/videoDecodeMem/CMakeLists.txt @@ -62,6 +62,7 @@ else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -DNDEBUG -fPIC") endif() +set (HIP_PLATFORM amd CACHE STRING "HIP platform") find_package(HIP QUIET) find_package(rocdecode QUIET) find_package(rocprofiler-register QUIET) diff --git a/samples/videoDecodeMem/videodecodemem.cpp b/samples/videoDecodeMem/videodecodemem.cpp index 9145a508c..fd10784e6 100644 --- a/samples/videoDecodeMem/videodecodemem.cpp +++ b/samples/videoDecodeMem/videodecodemem.cpp @@ -235,7 +235,7 @@ int main(int argc, char **argv) { } for (int i = 0; i < n_frame_returned; i++) { pframe = viddec.GetFrame(&pts); - if (b_generate_md5) { + if (b_generate_md5 && pframe) { md5_generator->UpdateMd5ForFrame(pframe, surf_info); } if (dump_output_frames && mem_type != OUT_SURFACE_MEM_NOT_MAPPED) { diff --git a/samples/videoDecodeMultiFiles/CMakeLists.txt b/samples/videoDecodeMultiFiles/CMakeLists.txt index 38df62330..8ad8da16b 100644 --- a/samples/videoDecodeMultiFiles/CMakeLists.txt +++ b/samples/videoDecodeMultiFiles/CMakeLists.txt @@ -61,6 +61,7 @@ else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -DNDEBUG -fPIC") endif() +set (HIP_PLATFORM amd CACHE STRING "HIP platform") find_package(HIP QUIET) find_package(rocdecode QUIET) find_package(rocprofiler-register QUIET) diff --git a/samples/videoDecodePerf/CMakeLists.txt b/samples/videoDecodePerf/CMakeLists.txt index 5f6fdd4b4..57c799a75 100644 --- a/samples/videoDecodePerf/CMakeLists.txt +++ b/samples/videoDecodePerf/CMakeLists.txt @@ -61,6 +61,7 @@ else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -DNDEBUG -fPIC") endif() +set (HIP_PLATFORM amd CACHE STRING "HIP platform") find_package(HIP QUIET) find_package(rocdecode QUIET) find_package(rocdecode-host 1.0.0 QUIET) @@ -76,7 +77,7 @@ if(HIP_FOUND AND FFMPEG_FOUND AND rocdecode_FOUND AND Threads_FOUND AND rocprofi ${SWSCALE_INCLUDE_DIR} ${AVFORMAT_INCLUDE_DIR}) set(LINK_LIBRARY_LIST ${LINK_LIBRARY_LIST} ${FFMPEG_LIBRARIES}) # rocdecode and utils - include_directories (${rocdecode_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../../utils ${CMAKE_CURRENT_SOURCE_DIR}/../../utils/rocvideodecode ${CMAKE_CURRENT_SOURCE_DIR}/../../utils/ffmpegvideodecode/ ${CMAKE_CURRENT_SOURCE_DIR}/..) + include_directories (${rocdecode_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../../utils ${CMAKE_CURRENT_SOURCE_DIR}/../../utils/rocvideodecode ${CMAKE_CURRENT_SOURCE_DIR}/..) set(LINK_LIBRARY_LIST ${LINK_LIBRARY_LIST} rocdecode::rocdecode) # threads set(THREADS_PREFER_PTHREAD_FLAG ON) @@ -85,7 +86,11 @@ if(HIP_FOUND AND FFMPEG_FOUND AND rocdecode_FOUND AND Threads_FOUND AND rocprofi # rocprofiler-register set(LINK_LIBRARY_LIST ${LINK_LIBRARY_LIST} rocprofiler-register::rocprofiler-register) # sample app exe - list(APPEND SOURCES ${PROJECT_SOURCE_DIR} videodecodeperf.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../../utils/rocvideodecode/roc_video_dec.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../../utils/ffmpegvideodecode/ffmpeg_video_dec.cpp) + list(APPEND SOURCES ${PROJECT_SOURCE_DIR} videodecodeperf.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../../utils/rocvideodecode/roc_video_dec.cpp) + if(rocdecode-host_FOUND) + include_directories (${CMAKE_CURRENT_SOURCE_DIR}/../../utils/ffmpegvideodecode) + list(APPEND SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../../utils/ffmpegvideodecode/ffmpeg_video_dec.cpp) + endif() add_executable(${PROJECT_NAME} ${SOURCES}) if(rocdecode-host_FOUND) # rocdecode-host diff --git a/samples/videoDecodePerf/videodecodeperf.cpp b/samples/videoDecodePerf/videodecodeperf.cpp index d789f2ee4..ae905663c 100644 --- a/samples/videoDecodePerf/videodecodeperf.cpp +++ b/samples/videoDecodePerf/videodecodeperf.cpp @@ -35,8 +35,10 @@ THE SOFTWARE. #endif #include "video_demuxer.h" #include "roc_video_dec.h" -#include "ffmpeg_video_dec.h" #include "common.h" +#if ENABLE_HOST_DECODE + #include "ffmpeg_video_dec.h" +#endif void DecProc(RocVideoDecoder *p_dec, VideoDemuxer *demuxer, int *pn_frame, int *pn_pic_dec, double *pn_fps, double *pn_fps_dec, int max_num_frames, OutputSurfaceMemoryType mem_type) { int n_video_bytes = 0, n_frame_returned = 0, n_frame = 0; diff --git a/samples/videoDecodePicFiles/CMakeLists.txt b/samples/videoDecodePicFiles/CMakeLists.txt index 508408115..6d551ea19 100644 --- a/samples/videoDecodePicFiles/CMakeLists.txt +++ b/samples/videoDecodePicFiles/CMakeLists.txt @@ -61,8 +61,10 @@ else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -DNDEBUG -fPIC") endif() +set (HIP_PLATFORM amd CACHE STRING "HIP platform") find_package(HIP QUIET) find_package(rocdecode QUIET) +find_package(rocdecode-host 1.0.0 QUIET) find_package(rocprofiler-register QUIET) find_package(FFmpeg QUIET) find_package(Threads REQUIRED) @@ -75,7 +77,7 @@ if(HIP_FOUND AND FFMPEG_FOUND AND rocdecode_FOUND AND Threads_FOUND AND rocprofi ${AVFORMAT_INCLUDE_DIR}) set(LINK_LIBRARY_LIST ${LINK_LIBRARY_LIST} ${FFMPEG_LIBRARIES}) # rocdecode and utils - include_directories (${rocdecode_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/../../utils ${CMAKE_CURRENT_SOURCE_DIR}/../../utils/rocvideodecode ${CMAKE_CURRENT_SOURCE_DIR}/../../utils/ffmpegvideodecode) + include_directories (${rocdecode_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/../../utils ${CMAKE_CURRENT_SOURCE_DIR}/../../utils/rocvideodecode) set(LINK_LIBRARY_LIST ${LINK_LIBRARY_LIST} rocdecode::rocdecode) # threads set(THREADS_PREFER_PTHREAD_FLAG ON) @@ -83,15 +85,27 @@ if(HIP_FOUND AND FFMPEG_FOUND AND rocdecode_FOUND AND Threads_FOUND AND rocprofi # rocprofiler-register set(LINK_LIBRARY_LIST ${LINK_LIBRARY_LIST} rocprofiler-register::rocprofiler-register) # sample app exe - list(APPEND SOURCES ${PROJECT_SOURCE_DIR} videodecodepicfiles.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../../utils/rocvideodecode/roc_video_dec.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../../utils/ffmpegvideodecode/ffmpeg_video_dec.cpp) + list(APPEND SOURCES ${PROJECT_SOURCE_DIR} videodecodepicfiles.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../../utils/rocvideodecode/roc_video_dec.cpp) + if(rocdecode-host_FOUND) + include_directories (${CMAKE_CURRENT_SOURCE_DIR}/../../utils/ffmpegvideodecode) + list(APPEND SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../../utils/ffmpegvideodecode/ffmpeg_video_dec.cpp) + endif() add_executable(${PROJECT_NAME} ${SOURCES}) - target_link_libraries(${PROJECT_NAME} ${LINK_LIBRARY_LIST}) + if(rocdecode-host_FOUND) + # rocdecode-host + include_directories(${rocdecode-host_INCLUDE_DIR}) + set(LINK_LIBRARY_LIST ${LINK_LIBRARY_LIST} rocdecode::rocdecode-host) + target_compile_definitions(${PROJECT_NAME} PUBLIC ENABLE_HOST_DECODE=1) + else() + target_compile_definitions(${PROJECT_NAME} PUBLIC ENABLE_HOST_DECODE=0) + endif() # FFMPEG multi-version support if(_FFMPEG_AVCODEC_VERSION VERSION_LESS_EQUAL 58.134.100) target_compile_definitions(${PROJECT_NAME} PUBLIC USE_AVCODEC_GREATER_THAN_58_134=0) else() target_compile_definitions(${PROJECT_NAME} PUBLIC USE_AVCODEC_GREATER_THAN_58_134=1) endif() + target_link_libraries(${PROJECT_NAME} ${LINK_LIBRARY_LIST}) else() message("-- ERROR!: ${PROJECT_NAME} excluded! please install all the dependencies and try again!") if (NOT HIP_FOUND) diff --git a/samples/videoDecodePicFiles/videodecodepicfiles.cpp b/samples/videoDecodePicFiles/videodecodepicfiles.cpp index 09efbe093..a3cbb426b 100644 --- a/samples/videoDecodePicFiles/videodecodepicfiles.cpp +++ b/samples/videoDecodePicFiles/videodecodepicfiles.cpp @@ -34,8 +34,10 @@ THE SOFTWARE. #include "video_demuxer.h" #include "rocdecode/roc_bitstream_reader.h" #include "roc_video_dec.h" -#include "ffmpeg_video_dec.h" #include "common.h" +#if ENABLE_HOST_DECODE + #include "ffmpeg_video_dec.h" +#endif void ShowHelpAndExit(const char *option = NULL) { std::cout << "Options:" << std::endl @@ -316,7 +318,7 @@ int main(int argc, char **argv) { } for (int i = 0; i < n_frame_returned; i++) { pframe = viddec->GetFrame(&pts); - if (b_generate_md5) { + if (b_generate_md5 && pframe) { md5_generator->UpdateMd5ForFrame(pframe, surf_info); } if (dump_output_frames && mem_type != OUT_SURFACE_MEM_NOT_MAPPED) { @@ -387,8 +389,8 @@ int main(int argc, char **argv) { delete md5_generator; } } catch (const std::exception &ex) { - std::cout << ex.what() << std::endl; - exit(1); + std::cout << ex.what() << std::endl; + exit(1); } return 0; diff --git a/samples/videoDecodeRGB/CMakeLists.txt b/samples/videoDecodeRGB/CMakeLists.txt index 9691d3f4c..df1cb4ee7 100644 --- a/samples/videoDecodeRGB/CMakeLists.txt +++ b/samples/videoDecodeRGB/CMakeLists.txt @@ -30,6 +30,20 @@ elseif(ROCM_PATH) else() set(ROCM_PATH /opt/rocm CACHE PATH "Default ROCm installation path") endif() + +# Check if lib/rocm_sysdeps/lib exists in the ROCm path which indicates ROCm installation via TheRock +set(USING_THE_ROCK OFF) +if(EXISTS "${ROCM_PATH}/lib/rocm_sysdeps/lib") + set(USING_THE_ROCK ON) +endif() + +if(USING_THE_ROCK) + if(NOT DEFINED ENV{HIP_DEVICE_LIB_PATH}) + set(ENV{HIP_DEVICE_LIB_PATH} ${ROCM_PATH}/lib/llvm/amdgcn/bitcode) + set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "HIP_DEVICE_LIB_PATH=${ROCM_PATH}/lib/llvm/amdgcn/bitcode") + endif() +endif() + # Set AMD Clang as default compiler set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED On) @@ -69,7 +83,7 @@ if(NOT GPU_TARGETS AND NOT AMDGPU_TARGETS) endif() include(ROCMCheckTargetIds OPTIONAL RESULT_VARIABLE HAS_ROCM_CHECK_TARGET_IDS) - set(OPTIONAL_GPU_TARGETS "gfx950;gfx1200;gfx1201") + set(OPTIONAL_GPU_TARGETS "gfx950;gfx1151;gfx1200;gfx1201") if(HAS_ROCM_CHECK_TARGET_IDS) rocm_check_target_ids(OPTIONAL_GPU_TARGETS_AVAILABLE TARGETS ${OPTIONAL_GPU_TARGETS}) else() # if we don't have rocm_check_target_ids, just assume the targets are available @@ -97,6 +111,7 @@ else() endif() message("-- ${White}${PROJECT_NAME} -- AMD GPU_TARGETS: ${GPU_TARGETS}${ColourReset}") +set(HIP_PLATFORM amd CACHE STRING "HIP platform") find_package(HIP QUIET) find_package(rocdecode QUIET) find_package(rocprofiler-register QUIET) diff --git a/samples/videoDecodeRaw/CMakeLists.txt b/samples/videoDecodeRaw/CMakeLists.txt index e90d71d7d..ae7b3e0b5 100644 --- a/samples/videoDecodeRaw/CMakeLists.txt +++ b/samples/videoDecodeRaw/CMakeLists.txt @@ -61,6 +61,7 @@ else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -DNDEBUG -fPIC") endif() +set (HIP_PLATFORM amd CACHE STRING "HIP platform") find_package(HIP QUIET) find_package(rocdecode QUIET) find_package(rocprofiler-register QUIET) diff --git a/samples/videoToSequence/CMakeLists.txt b/samples/videoToSequence/CMakeLists.txt index 202d1ea21..3e1ac43e3 100644 --- a/samples/videoToSequence/CMakeLists.txt +++ b/samples/videoToSequence/CMakeLists.txt @@ -61,6 +61,7 @@ else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -DNDEBUG -fPIC") endif() +set (HIP_PLATFORM amd CACHE STRING "HIP platform") find_package(HIP QUIET) find_package(rocdecode QUIET) find_package(rocprofiler-register QUIET) diff --git a/src/bit_stream_reader/es_reader.cpp b/src/bit_stream_reader/es_reader.cpp index 101021a26..7ba68de86 100644 --- a/src/bit_stream_reader/es_reader.cpp +++ b/src/bit_stream_reader/es_reader.cpp @@ -26,12 +26,13 @@ THE SOFTWARE. #include "avc_defines.h" #include "av1_defines.h" #include "vp9_defines.h" -#include "roc_video_parser.h" RocVideoESParser::RocVideoESParser(const char *input_file_path) { + logger_.SetLogLevel(kRocDecLogError); + p_stream_file_.open(input_file_path, std::ifstream::in | std::ifstream::binary); if (!p_stream_file_) { - ERR("Failed to open the bitstream file."); + logger_.CriticalLog(MakeMsg("Failed to open the bitstream file.")); } end_of_file_ = false; end_of_stream_ = false; @@ -138,7 +139,7 @@ bool RocVideoESParser::ReadBytes(int offset, int size, uint8_t *data) { return false; } if (size > GetDataSizeInRB()) { - ERR("Could not read the requested bytes from ring buffer. Either ring buffer size is too small or not enough bytes left."); + logger_.CriticalLog(MakeMsg("Could not read the requested bytes from ring buffer. Either ring buffer size is too small or not enough bytes left.")); return false; } } @@ -297,7 +298,7 @@ int RocVideoESParser::GetPicDataAvcHevc(uint8_t **p_pic_data, int *pic_size) { while (!end_of_stream_) { if (!FindStartCode()) { - ERR("No start code in the bitstream."); + logger_.ErrorLog(MakeMsg("No start code in the bitstream.")); break; } CopyNalUnitFromRing(); diff --git a/src/bit_stream_reader/es_reader.h b/src/bit_stream_reader/es_reader.h index 5a216c0be..c8a68aca1 100644 --- a/src/bit_stream_reader/es_reader.h +++ b/src/bit_stream_reader/es_reader.h @@ -26,6 +26,7 @@ THE SOFTWARE. #include #include #include "rocdecode/rocdecode.h" +#include "roc_video_parser.h" #define BS_RING_SIZE (16 * 1024 * 1024) #define INIT_PIC_DATA_SIZE (2 * 1024 * 1024) @@ -100,6 +101,8 @@ class RocVideoESParser { bool ivf_file_header_read_; // indicator if IVF file header has been checked + RocDecLogger logger_; + /*! \brief Function to retrieve the bitstream of a picture for AVC/HEVC * \param [out] p_pic_data Pointer to the picture data * \param [out] pic_size Size of the picture in bytes diff --git a/src/bit_stream_reader/roc_bs_reader_api.cpp b/src/bit_stream_reader/roc_bs_reader_api.cpp index 830cb4316..6fd51be68 100644 --- a/src/bit_stream_reader/roc_bs_reader_api.cpp +++ b/src/bit_stream_reader/roc_bs_reader_api.cpp @@ -33,7 +33,7 @@ rocDecStatus ROCDECAPI rocDecCreateBitstreamReader(RocdecBitstreamReader *bs_rea handle = new RocBitstreamReaderHandle(input_file_path); } catch (const std::exception& e) { - ERR( STR("Failed to create RocBitstreamReader handle, ") + STR(e.what())) + RocDecLogger::AlwaysLog(STR("Failed to create RocBitstreamReader handle, ") + STR(e.what())); return ROCDEC_RUNTIME_ERROR; } *bs_reader_handle = handle; @@ -51,7 +51,7 @@ rocDecStatus ROCDECAPI rocDecGetBitstreamCodecType(RocdecBitstreamReader bs_read } catch (const std::exception& e) { roc_bs_reader_handle->CaptureError(e.what()); - ERR(e.what()) + RocDecLogger::AlwaysLog(e.what()); return ROCDEC_RUNTIME_ERROR; } return ret; @@ -68,7 +68,7 @@ rocDecStatus ROCDECAPI rocDecGetBitstreamBitDepth(RocdecBitstreamReader bs_reade } catch (const std::exception& e) { roc_bs_reader_handle->CaptureError(e.what()); - ERR(e.what()) + RocDecLogger::AlwaysLog(e.what()); return ROCDEC_RUNTIME_ERROR; } return ret; @@ -85,7 +85,7 @@ rocDecStatus ROCDECAPI rocDecGetBitstreamPicData(RocdecBitstreamReader bs_reader } catch (const std::exception& e) { roc_bs_reader_handle->CaptureError(e.what()); - ERR(e.what()) + RocDecLogger::AlwaysLog(e.what()); return ROCDEC_RUNTIME_ERROR; } return ret; diff --git a/src/commons.h b/src/commons.h index af49ad85f..ccd9a0645 100644 --- a/src/commons.h +++ b/src/commons.h @@ -25,6 +25,7 @@ THE SOFTWARE. #include #include #include +#include #define TOSTR(X) std::to_string(static_cast(X)) #define STR(X) std::string(X) @@ -40,11 +41,75 @@ THE SOFTWARE. #endif #define ERR(X) std::cerr << "[ERR] " << " {" << __func__ <<"} " << " " << X << std::endl; +// Logging control +enum RocDecLogLevel { + kRocDecLogCritical = 0, // Only ouput critical messages + kRocDecLogError = 1, + kRocDecLogWarning = 2, + kRocDecLogInfo = 3, + kRocDecLogDebug = 4, + kRocDecLogLevelMax = 4 +}; + +#define MakeMsg(msg) STR(__func__) + "(), Line " + TOSTR(__LINE__) + ": " + msg +#define OutputMsg(msg) std::cout << msg << std::endl + +class RocDecLogger { +public: + RocDecLogger() : log_level_(kRocDecLogCritical) { + char *env_log_level = std::getenv("ROCDEC_LOG_LEVEL"); + if (env_log_level != nullptr) { + log_level_ = std::clamp(std::atoi(env_log_level), 0, static_cast(kRocDecLogLevelMax)); + } + } + RocDecLogger(int log_level) : log_level_(log_level) {}; + ~RocDecLogger() {}; + + void SetLogLevel(int log_level) {log_level_ = std::clamp(log_level, 0, static_cast(kRocDecLogLevelMax));}; + int GetLogLevel() {return log_level_;}; + + static void AlwaysLog(std::string msg) { + OutputMsg(msg); + }; + + void CriticalLog(std::string msg) { + if (log_level_ >= kRocDecLogCritical) { + OutputMsg("[Critical] " + msg); + } + }; + + void ErrorLog(std::string msg) { + if (log_level_ >= kRocDecLogError) { + OutputMsg("[Error] " + msg); + } + }; + + void WarningLog(std::string msg) { + if (log_level_ >= kRocDecLogWarning) { + OutputMsg("[Warning] " + msg); + } + }; + + void InfoLog(std::string msg) { + if (log_level_ >= kRocDecLogInfo) { + OutputMsg("[Info] " + msg); + } + }; + + void DebugLog(std::string msg) { + if (log_level_ >= kRocDecLogDebug) { + OutputMsg("[Debug] " + msg); + } + }; + +private: + int log_level_ = kRocDecLogCritical; +}; class rocDecodeException : public std::exception { public: - explicit rocDecodeException(const std::string& message):_message(message){} + explicit rocDecodeException(const std::string& OutputMsg):_message(OutputMsg){} virtual const char* what() const throw() override { return _message.c_str(); } diff --git a/src/parser/av1_parser.cpp b/src/parser/av1_parser.cpp index ddddddf4c..65d207d2d 100644 --- a/src/parser/av1_parser.cpp +++ b/src/parser/av1_parser.cpp @@ -58,7 +58,7 @@ rocDecStatus Av1VideoParser::ParseVideoData(RocdecSourceDataPacket *p_data) { if (p_data->payload && p_data->payload_size) { curr_pts_ = p_data->pts; if (ParsePictureData(p_data->payload, p_data->payload_size) != PARSER_OK) { - ERR("Error occurred in picture data parsing."); + logger_.ErrorLog(MakeMsg("Error occurred in picture data parsing.")); return ROCDEC_RUNTIME_ERROR; } } else if (!(p_data->flags & ROCDEC_PKT_ENDOFSTREAM)) { @@ -91,7 +91,7 @@ ParserResult Av1VideoParser::ParsePictureData(const uint8_t *p_stream, uint32_t } case kObuFrameHeader: { if (seen_frame_header_ != 0) { - ERR("If obu_type is equal to OBU_FRAME_HEADER, it is a requirement of bitstream conformance that SeenFrameHeader is equal to 0."); + logger_.ErrorLog(MakeMsg("If obu_type is equal to OBU_FRAME_HEADER, it is a requirement of bitstream conformance that SeenFrameHeader is equal to 0.")); return PARSER_INVALID_ARG; } int bytes_parsed; @@ -102,7 +102,7 @@ ParserResult Av1VideoParser::ParsePictureData(const uint8_t *p_stream, uint32_t } case kObuRedundantFrameHeader: { if (seen_frame_header_ != 1) { - ERR("If obu_type is equal to OBU_REDUNDANT_FRAME_HEADER, it is a requirement of bitstream conformance that SeenFrameHeader is equal to 1."); + logger_.ErrorLog(MakeMsg("If obu_type is equal to OBU_REDUNDANT_FRAME_HEADER, it is a requirement of bitstream conformance that SeenFrameHeader is equal to 1.")); return PARSER_INVALID_ARG; } int bytes_parsed; @@ -120,18 +120,18 @@ ParserResult Av1VideoParser::ParsePictureData(const uint8_t *p_stream, uint32_t if (obu_size_ > bytes_parsed) { obu_size_ -= bytes_parsed; if (ParseTileGroupObu(pic_data_buffer_ptr_ + obu_byte_offset_, obu_size_) != PARSER_OK) { - ERR("Error occurred in ParseTileGroupObu(). Skip this OBU."); + logger_.ErrorLog(MakeMsg("Error occurred in ParseTileGroupObu(). Skip this OBU.")); break; } } else { - ERR("Frame OBU size error."); + logger_.ErrorLog(MakeMsg("Frame OBU size error.")); return PARSER_OUT_OF_RANGE; } break; } case kObuTileGroup: { if (ParseTileGroupObu(pic_data_buffer_ptr_ + obu_byte_offset_, obu_size_) != PARSER_OK) { - ERR("Error occurred in ParseTileGroupObu(). Skip this OBU."); + logger_.ErrorLog(MakeMsg("Error occurred in ParseTileGroupObu(). Skip this OBU.")); } break; } @@ -151,7 +151,7 @@ ParserResult Av1VideoParser::ParsePictureData(const uint8_t *p_stream, uint32_t if (frame_header_.show_existing_frame) { int disp_idx = dpb_buffer_.virtual_buffer_index[frame_header_.frame_to_show_map_idx]; if (disp_idx == INVALID_INDEX) { - ERR("Invalid existing frame index to show."); + logger_.ErrorLog(MakeMsg("Invalid existing frame index to show.")); return PARSER_INVALID_ARG; } if (pfn_display_picture_cb_) { @@ -164,7 +164,7 @@ ParserResult Av1VideoParser::ParsePictureData(const uint8_t *p_stream, uint32_t decode_buffer_pool_[disp_idx].pts = curr_pts_; // Insert into output/display picture list if (num_output_pics_ >= dec_buf_pool_size_) { - ERR("Display list size larger than decode buffer pool size!"); + logger_.ErrorLog(MakeMsg("Display list size larger than decode buffer pool size!")); return PARSER_OUT_OF_RANGE; } else { output_pic_list_[num_output_pics_] = disp_idx; @@ -182,7 +182,7 @@ ParserResult Av1VideoParser::ParsePictureData(const uint8_t *p_stream, uint32_t return ret; } if ((ret = SendPicForDecode()) != PARSER_OK) { - ERR(STR("Failed to decode!")); + logger_.ErrorLog(MakeMsg(STR("Failed to decode!"))); return ret; } pic_count_++; @@ -218,7 +218,7 @@ ParserResult Av1VideoParser::NotifyNewSequence(Av1SequenceHeader *p_seq_header, } else if (p_seq_header->color_config.mono_chrome == 0 && p_seq_header->color_config.subsampling_x == 0 && p_seq_header->color_config.subsampling_y == 0) { video_format_params_.chroma_format = rocDecVideoChromaFormat_444; } else { - ERR("Incorrect chroma format."); + logger_.ErrorLog(MakeMsg("Incorrect chroma format.")); return PARSER_INVALID_FORMAT; } @@ -243,7 +243,7 @@ ParserResult Av1VideoParser::NotifyNewSequence(Av1SequenceHeader *p_seq_header, // callback function with RocdecVideoFormat params filled out if (pfn_sequence_cb_(parser_params_.user_data, &video_format_params_) == 0) { - ERR("Sequence callback function failed."); + logger_.ErrorLog(MakeMsg("Sequence callback function failed.")); return PARSER_FAIL; } else { return PARSER_OK; @@ -479,7 +479,7 @@ ParserResult Av1VideoParser::SendPicForDecode() { #endif // DBGINFO if (pfn_decode_picture_cb_(parser_params_.user_data, &dec_pic_params_) == 0) { - ERR("Decode error occurred."); + logger_.ErrorLog(MakeMsg("Decode error occurred.")); return PARSER_FAIL; } else { return PARSER_OK; @@ -620,7 +620,7 @@ ParserResult Av1VideoParser::FindFreeInDecBufPool() { } } if (dec_buf_index == dec_buf_pool_size_) { - ERR("Could not find a free buffer in decode buffer pool for decoded image."); + logger_.ErrorLog(MakeMsg("Could not find a free buffer in decode buffer pool for decoded image.")); return PARSER_NOT_FOUND; } curr_pic_.dec_buf_idx = dec_buf_index; @@ -635,7 +635,7 @@ ParserResult Av1VideoParser::FindFreeInDecBufPool() { } } if (dec_buf_index == dec_buf_pool_size_) { - ERR("Could not find a free buffer in decode buffer pool for FG output."); + logger_.ErrorLog(MakeMsg("Could not find a free buffer in decode buffer pool for FG output.")); return PARSER_NOT_FOUND; } curr_pic_.fg_buf_idx = dec_buf_index; @@ -656,7 +656,7 @@ ParserResult Av1VideoParser::FindFreeInDpbAndMark() { } } if (i == BUFFER_POOL_MAX_SIZE) { - ERR("DPB buffer overflow!"); + logger_.ErrorLog(MakeMsg("DPB buffer overflow!")); return PARSER_NOT_FOUND; } curr_pic_.pic_idx = i; @@ -675,7 +675,7 @@ ParserResult Av1VideoParser::FindFreeInDpbAndMark() { decode_buffer_pool_[disp_idx].pts = curr_pts_; // Insert into output/display picture list if (num_output_pics_ >= dec_buf_pool_size_) { - ERR("Display list size larger than decode buffer pool size!"); + logger_.ErrorLog(MakeMsg("Display list size larger than decode buffer pool size!")); return PARSER_OUT_OF_RANGE; } else { output_pic_list_[num_output_pics_] = disp_idx; @@ -699,18 +699,18 @@ ParserResult Av1VideoParser::ParseObuHeader(const uint8_t *p_stream) { size_t offset = 0; obu_header_.size = 1; if (Parser::GetBit(p_stream, offset) != 0) { - ERR("Syntax error: obu_forbidden_bit must be set to 0."); + logger_.ErrorLog(MakeMsg("Syntax error: obu_forbidden_bit must be set to 0.")); return PARSER_INVALID_ARG; } obu_header_.obu_type = Parser::ReadBits(p_stream, offset, 4); obu_header_.obu_extension_flag = Parser::GetBit(p_stream, offset); obu_header_.obu_has_size_field = Parser::GetBit(p_stream, offset); if (!obu_header_.obu_has_size_field) { - ERR("Syntax error: Section 5.2: obu_has_size_field must be equal to 1."); + logger_.ErrorLog(MakeMsg("Syntax error: Section 5.2: obu_has_size_field must be equal to 1.")); return PARSER_INVALID_ARG; } if (Parser::GetBit(p_stream, offset) != 0) { - ERR("Syntax error: obu_reserved_1bit must be set to 0."); + logger_.ErrorLog(MakeMsg("Syntax error: obu_reserved_1bit must be set to 0.")); return PARSER_INVALID_ARG; } if (obu_header_.obu_extension_flag) { @@ -718,7 +718,7 @@ ParserResult Av1VideoParser::ParseObuHeader(const uint8_t *p_stream) { obu_header_.temporal_id = Parser::ReadBits(p_stream, offset, 3); obu_header_.spatial_id = Parser::ReadBits(p_stream, offset, 2); if (Parser::ReadBits(p_stream, offset, 3) != 0) { - ERR("Syntax error: extension_header_reserved_3bits must be set to 0."); + logger_.ErrorLog(MakeMsg("Syntax error: extension_header_reserved_3bits must be set to 0.")); return PARSER_INVALID_ARG; } } @@ -731,7 +731,7 @@ ParserResult Av1VideoParser::ReadObuHeaderAndSize() { } uint8_t *p_stream = pic_data_buffer_ptr_ + curr_byte_offset_; if (ParseObuHeader(p_stream) != PARSER_OK) { - ERR("Syntax error(s) found in OBU header.") + logger_.ErrorLog(MakeMsg("Syntax error(s) found in OBU header.")); } curr_byte_offset_ += obu_header_.size; p_stream += obu_header_.size; @@ -741,7 +741,7 @@ ParserResult Av1VideoParser::ReadObuHeaderAndSize() { obu_byte_offset_ = curr_byte_offset_ + bytes_read; curr_byte_offset_ = obu_byte_offset_ + obu_size_; if (curr_byte_offset_ > pic_data_size_) { - ERR("Invalid obu_size value."); + logger_.ErrorLog(MakeMsg("Invalid obu_size value.")); return PARSER_EOF; } else { return PARSER_OK; @@ -758,7 +758,7 @@ ParserResult Av1VideoParser::ParseSequenceHeaderObu(uint8_t *p_stream, size_t si p_seq_header->still_picture = Parser::GetBit(p_stream, offset); p_seq_header->reduced_still_picture_header = Parser::GetBit(p_stream, offset); if (p_seq_header->reduced_still_picture_header == 1 && p_seq_header->still_picture != 1) { - ERR("If reduced_still_picture_header is 1, still_picture is required to be 1."); + logger_.ErrorLog(MakeMsg("If reduced_still_picture_header is 1, still_picture is required to be 1.")); return PARSER_WRONG_STATE; } @@ -778,12 +778,12 @@ ParserResult Av1VideoParser::ParseSequenceHeaderObu(uint8_t *p_stream, size_t si // timing_info() p_seq_header->timing_info.num_units_in_display_tick = Parser::ReadBits(p_stream, offset, 32); if (p_seq_header->timing_info.num_units_in_display_tick == 0) { - ERR("num_units_in_display_tick is 0."); + logger_.ErrorLog(MakeMsg("num_units_in_display_tick is 0.")); return PARSER_WRONG_STATE; } p_seq_header->timing_info.time_scale = Parser::ReadBits(p_stream, offset, 32); if (p_seq_header->timing_info.time_scale == 0) { - ERR("time_scale is 0."); + logger_.ErrorLog(MakeMsg("time_scale is 0.")); return PARSER_WRONG_STATE; } p_seq_header->timing_info.equal_picture_interval = Parser::GetBit(p_stream, offset); @@ -809,13 +809,13 @@ ParserResult Av1VideoParser::ParseSequenceHeaderObu(uint8_t *p_stream, size_t si if (i > 0) { for (int j = 0; j < i - 1; j++) { if (p_seq_header->operating_point_idc[i] == p_seq_header->operating_point_idc[j]) { - ERR("operating_point_idc[" + TOSTR(i) + "] is equal to operating_point_idc[" + TOSTR(j) + "]"); + logger_.ErrorLog(MakeMsg("operating_point_idc[" + TOSTR(i) + "] is equal to operating_point_idc[" + TOSTR(j) + "]")); return PARSER_WRONG_STATE; } } } if (p_seq_header->operating_point_idc[i] && obu_header_.obu_extension_flag != 1) { - ERR("When operating_point_idc is not 0, obu_extension_flag is required to be 1."); + logger_.ErrorLog(MakeMsg("When operating_point_idc is not 0, obu_extension_flag is required to be 1.")); return PARSER_WRONG_STATE; } p_seq_header->seq_level_idx[i] = Parser::ReadBits(p_stream, offset, 5); @@ -962,7 +962,7 @@ ParserResult Av1VideoParser::ParseUncompressedHeader(uint8_t *p_stream, size_t s p_frame_header->is_received = 0; if (p_seq_header->is_received == 0) { - ERR("No valid sequence header received before frame header."); + logger_.ErrorLog(MakeMsg("No valid sequence header received before frame header.")); return PARSER_WRONG_STATE; } @@ -980,7 +980,7 @@ ParserResult Av1VideoParser::ParseUncompressedHeader(uint8_t *p_stream, size_t s p_frame_header->show_existing_frame = Parser::GetBit(p_stream, offset); if (p_frame_header->show_existing_frame == 1) { if (obu_header_.obu_type == kObuFrame) { - ERR("show_existing_frame is 1 when obu_type is equal to OBU_FRAME."); + logger_.ErrorLog(MakeMsg("show_existing_frame is 1 when obu_type is equal to OBU_FRAME.")); return PARSER_WRONG_STATE; } p_frame_header->frame_to_show_map_idx = Parser::ReadBits(p_stream, offset, 3); @@ -1100,7 +1100,7 @@ ParserResult Av1VideoParser::ParseUncompressedHeader(uint8_t *p_stream, size_t s } else { p_frame_header->refresh_frame_flags = Parser::ReadBits(p_stream, offset, 8); if (p_frame_header->frame_type == kIntraOnlyFrame && p_frame_header->refresh_frame_flags == 0xFF) { - ERR("When frame_type is equal to INTRA_ONLY_FRAME, it is a requirement of bitstream conformance that refresh_frame_flags is not equal to 0xff."); + logger_.ErrorLog(MakeMsg("When frame_type is equal to INTRA_ONLY_FRAME, it is a requirement of bitstream conformance that refresh_frame_flags is not equal to 0xff.")); return PARSER_WRONG_STATE; } } @@ -1145,7 +1145,7 @@ ParserResult Av1VideoParser::ParseUncompressedHeader(uint8_t *p_stream, size_t s uint32_t delta_frame_id = p_frame_header->delta_frame_id_minus_1 + 1; p_frame_header->expected_frame_id[i] = ((p_frame_header->current_frame_id + (1 << frame_id_len) - delta_frame_id ) % (1 << frame_id_len)); if (p_frame_header->expected_frame_id[i] != dpb_buffer_.ref_frame_id[p_frame_header->ref_frame_idx[i]] || dpb_buffer_.ref_valid[p_frame_header->ref_frame_idx[i]] == 0) { - ERR("Syntax Error: Reference buffer frame ID mismatch.\n"); + logger_.ErrorLog(MakeMsg("Syntax Error: Reference buffer frame ID mismatch.\n")); return PARSER_INVALID_ARG; } } @@ -1255,7 +1255,7 @@ ParserResult Av1VideoParser::ParseUncompressedHeader(uint8_t *p_stream, size_t s } } if (p_frame_header->coded_lossless == 1 && p_frame_header->delta_q_params.delta_q_present == 1) { - ERR("It is a requirement of bitstream conformance that delta_q_present is equal to 0 when CodedLossless is equal to 1."); + logger_.ErrorLog(MakeMsg("It is a requirement of bitstream conformance that delta_q_present is equal to 0 when CodedLossless is equal to 1.")); return PARSER_WRONG_STATE; } @@ -1305,7 +1305,7 @@ ParserResult Av1VideoParser::ParseTileGroupObu(uint8_t *p_stream, size_t size) { uint32_t tg_size = size; if (p_frame_header->is_received == 0) { - ERR("No valid frame header received before tile group."); + logger_.ErrorLog(MakeMsg("No valid frame header received before tile group.")); return PARSER_WRONG_STATE; } @@ -1318,7 +1318,7 @@ ParserResult Av1VideoParser::ParseTileGroupObu(uint8_t *p_stream, size_t size) { if (p_tile_group->num_tiles > 1) { tile_start_and_end_present_flag = Parser::GetBit(p_stream, offset); if (obu_header_.obu_type == kObuFrame && tile_start_and_end_present_flag != 0) { - ERR("If obu_type is equal to OBU_FRAME, it is a requirement of bitstream conformance that the value of tile_start_and_end_present_flag is equal to 0."); + logger_.ErrorLog(MakeMsg("If obu_type is equal to OBU_FRAME, it is a requirement of bitstream conformance that the value of tile_start_and_end_present_flag is equal to 0.")); return PARSER_WRONG_STATE; } } @@ -1329,12 +1329,12 @@ ParserResult Av1VideoParser::ParseTileGroupObu(uint8_t *p_stream, size_t size) { uint32_t tile_bits = p_frame_header->tile_info.tile_cols_log2 + p_frame_header->tile_info.tile_rows_log2; p_tile_group->tg_start = Parser::ReadBits(p_stream, offset, tile_bits); if (p_tile_group->tg_start != p_tile_group->num_tiles_parsed) { - ERR("It is a requirement of bitstream conformance that the value of tg_start (" + TOSTR(p_tile_group->tg_start) + ") is equal to the value of TileNum (" + TOSTR(p_tile_group->num_tiles_parsed) + ") at the point that tile_group_obu is invoked."); + logger_.ErrorLog(MakeMsg("It is a requirement of bitstream conformance that the value of tg_start (" + TOSTR(p_tile_group->tg_start) + ") is equal to the value of TileNum (" + TOSTR(p_tile_group->num_tiles_parsed) + ") at the point that tile_group_obu is invoked.")); return PARSER_WRONG_STATE; } p_tile_group->tg_end = Parser::ReadBits(p_stream, offset, tile_bits); if (p_tile_group->tg_end < p_tile_group->tg_start) { - ERR("It is a requirement of bitstream conformance that the value of tg_end (" + TOSTR(p_tile_group->tg_end) + ") is greater than or equal to tg_start (" + TOSTR(p_tile_group->tg_start) + ")."); + logger_.ErrorLog(MakeMsg("It is a requirement of bitstream conformance that the value of tg_end (" + TOSTR(p_tile_group->tg_end) + ") is greater than or equal to tg_start (" + TOSTR(p_tile_group->tg_start) + ").")); return PARSER_WRONG_STATE; } } @@ -1344,7 +1344,7 @@ ParserResult Av1VideoParser::ParseTileGroupObu(uint8_t *p_stream, size_t size) { tg_size -= header_bytes; for (int tile_num = p_tile_group->tg_start; tile_num <= p_tile_group->tg_end; tile_num++) { if (tile_cols == 0) { - ERR("Tile columns is 0."); + logger_.ErrorLog(MakeMsg("Tile columns is 0.")); return PARSER_WRONG_STATE; } p_tile_group->tile_data_info[tile_num].tile_row = tile_num / tile_cols; @@ -2442,7 +2442,7 @@ ParserResult Av1VideoParser::FilmGrainParams(const uint8_t *p_stream, size_t &of for (i = 0; i < p_frame_header->film_grain_params.num_y_points; i++) { p_frame_header->film_grain_params.point_y_value[i] = Parser::ReadBits(p_stream, offset, 8); if (i > 0 && p_frame_header->film_grain_params.point_y_value[i] <= p_frame_header->film_grain_params.point_y_value[i - 1]) { - ERR("point_y_value["+ TOSTR(i) + "] (" + TOSTR(p_frame_header->film_grain_params.point_y_value[i]) + ") should be greater than point_y_value[" + TOSTR(i - 1) + "] (" + TOSTR(p_frame_header->film_grain_params.point_y_value[i - 1]) + ")"); + logger_.ErrorLog(MakeMsg("point_y_value["+ TOSTR(i) + "] (" + TOSTR(p_frame_header->film_grain_params.point_y_value[i]) + ") should be greater than point_y_value[" + TOSTR(i - 1) + "] (" + TOSTR(p_frame_header->film_grain_params.point_y_value[i - 1]) + ")")); return PARSER_INVALID_ARG; } p_frame_header->film_grain_params.point_y_scaling[i] = Parser::ReadBits(p_stream, offset, 8); @@ -2463,7 +2463,7 @@ ParserResult Av1VideoParser::FilmGrainParams(const uint8_t *p_stream, size_t &of for (i = 0; i < p_frame_header->film_grain_params.num_cb_points; i++) { p_frame_header->film_grain_params.point_cb_value[i] = Parser::ReadBits(p_stream, offset, 8); if (i > 0 && p_frame_header->film_grain_params.point_cb_value[i] <= p_frame_header->film_grain_params.point_cb_value[i - 1]) { - ERR("point_cb_value["+ TOSTR(i) + "] (" + TOSTR(p_frame_header->film_grain_params.point_cb_value[i]) + ") should be greater than point_cb_value[" + TOSTR(i - 1) + "] (" + TOSTR(p_frame_header->film_grain_params.point_cb_value[i - 1]) + ")"); + logger_.ErrorLog(MakeMsg("point_cb_value["+ TOSTR(i) + "] (" + TOSTR(p_frame_header->film_grain_params.point_cb_value[i]) + ") should be greater than point_cb_value[" + TOSTR(i - 1) + "] (" + TOSTR(p_frame_header->film_grain_params.point_cb_value[i - 1]) + ")")); return PARSER_INVALID_ARG; } p_frame_header->film_grain_params.point_cb_scaling[i] = Parser::ReadBits(p_stream, offset, 8); @@ -2472,11 +2472,11 @@ ParserResult Av1VideoParser::FilmGrainParams(const uint8_t *p_stream, size_t &of CHECK_ALLOWED_MAX("num_cr_points", p_frame_header->film_grain_params.num_cr_points, 10); if (p_seq_header->color_config.subsampling_x == 1 && p_seq_header->color_config.subsampling_y == 1) { if (p_frame_header->film_grain_params.num_cb_points == 0 && p_frame_header->film_grain_params.num_cr_points != 0) { - ERR("If subsampling_x is equal to 1 and subsampling_y is equal to 1 and num_cb_points is equal to 0, it is a requirement of bitstream conformance that num_cr_points is equal to 0."); + logger_.ErrorLog(MakeMsg("If subsampling_x is equal to 1 and subsampling_y is equal to 1 and num_cb_points is equal to 0, it is a requirement of bitstream conformance that num_cr_points is equal to 0.")); return PARSER_WRONG_STATE; } if (p_frame_header->film_grain_params.num_cb_points != 0 && p_frame_header->film_grain_params.num_cr_points == 0) { - ERR("If subsampling_x is equal to 1 and subsampling_y is equal to 1 and num_cb_points is not equal to 0, it is a requirement of bitstream conformance that num_cr_points is not equal to 0."); + logger_.ErrorLog(MakeMsg("If subsampling_x is equal to 1 and subsampling_y is equal to 1 and num_cb_points is not equal to 0, it is a requirement of bitstream conformance that num_cr_points is not equal to 0.")); return PARSER_WRONG_STATE; } } @@ -2484,7 +2484,7 @@ ParserResult Av1VideoParser::FilmGrainParams(const uint8_t *p_stream, size_t &of { p_frame_header->film_grain_params.point_cr_value[i] = Parser::ReadBits(p_stream, offset, 8); if (i > 0 && p_frame_header->film_grain_params.point_cr_value[i] <= p_frame_header->film_grain_params.point_cr_value[i - 1]) { - ERR("point_cr_value["+ TOSTR(i) + "] (" + TOSTR(p_frame_header->film_grain_params.point_cr_value[i]) + ") should be greater than point_cr_value[" + TOSTR(i - 1) + "] (" + TOSTR(p_frame_header->film_grain_params.point_cr_value[i - 1]) + ")"); + logger_.ErrorLog(MakeMsg("point_cr_value["+ TOSTR(i) + "] (" + TOSTR(p_frame_header->film_grain_params.point_cr_value[i]) + ") should be greater than point_cr_value[" + TOSTR(i - 1) + "] (" + TOSTR(p_frame_header->film_grain_params.point_cr_value[i - 1]) + ")")); return PARSER_INVALID_ARG; } p_frame_header->film_grain_params.point_cr_scaling[i] = Parser::ReadBits(p_stream, offset, 8); diff --git a/src/parser/avc_parser.cpp b/src/parser/avc_parser.cpp index d40f1ebc5..bbc9ba256 100644 --- a/src/parser/avc_parser.cpp +++ b/src/parser/avc_parser.cpp @@ -65,7 +65,7 @@ rocDecStatus AvcVideoParser::ParseVideoData(RocdecSourceDataPacket *p_data) { if (p_data->payload && p_data->payload_size) { curr_pts_ = p_data->pts; if (ParsePictureData(p_data->payload, p_data->payload_size) != PARSER_OK) { - ERR(STR("Parser failed!")); + logger_.ErrorLog(MakeMsg(STR("Parser failed!"))); return ROCDEC_RUNTIME_ERROR; } @@ -99,7 +99,7 @@ rocDecStatus AvcVideoParser::ParseVideoData(RocdecSourceDataPacket *p_data) { // Decode the picture if (SendPicForDecode() != PARSER_OK) { - ERR(STR("Failed to decode!")); + logger_.ErrorLog(MakeMsg(STR("Failed to decode!"))); return ROCDEC_RUNTIME_ERROR; } @@ -149,7 +149,7 @@ ParserResult AvcVideoParser::ParsePictureData(const uint8_t *p_stream, uint32_t do { ret = GetNalUnit(); if (ret == PARSER_NOT_FOUND) { - ERR(STR("Error: no start code found in the frame data.")); + logger_.ErrorLog(MakeMsg(STR("Error: no start code found in the frame data."))); return ret; } @@ -164,7 +164,7 @@ ParserResult AvcVideoParser::ParsePictureData(const uint8_t *p_stream, uint32_t memcpy(rbsp_buf_, (pic_data_buffer_ptr_ + curr_start_code_offset_ + 4), ebsp_size); rbsp_size_ = EbspToRbsp(rbsp_buf_, 0, ebsp_size); if ((ret2 = ParseSps(rbsp_buf_, rbsp_size_)) != PARSER_OK) { - ERR("Error occurred in SPS parsing. This SPS NAL unit is skipped."); + logger_.ErrorLog(MakeMsg("Error occurred in SPS parsing. This SPS NAL unit is skipped.")); } break; } @@ -173,7 +173,7 @@ ParserResult AvcVideoParser::ParsePictureData(const uint8_t *p_stream, uint32_t memcpy(rbsp_buf_, (pic_data_buffer_ptr_ + curr_start_code_offset_ + 4), ebsp_size); rbsp_size_ = EbspToRbsp(rbsp_buf_, 0, ebsp_size); if ((ret2 = ParsePps(rbsp_buf_, rbsp_size_)) != PARSER_OK) { - ERR("Error occurred in PPS parsing. This PPS NAL unit is skipped."); + logger_.ErrorLog(MakeMsg("Error occurred in PPS parsing. This PPS NAL unit is skipped.")); } break; } @@ -195,7 +195,7 @@ ParserResult AvcVideoParser::ParsePictureData(const uint8_t *p_stream, uint32_t rbsp_size_ = EbspToRbsp(rbsp_buf_, 0, ebsp_size); AvcSliceHeader *p_slice_header = &slice_info_list_[num_slices_].slice_header; if ((ret2 = ParseSliceHeader(rbsp_buf_, rbsp_size_, p_slice_header)) != PARSER_OK) { - ERR("Error occurred in slice header parsing. This slice NAL unit is skipped."); + logger_.ErrorLog(MakeMsg("Error occurred in slice header parsing. This slice NAL unit is skipped.")); break; // ignore and continue to next nal_unit } slice_info_list_[num_slices_].slice_data_offset = curr_start_code_offset_; @@ -243,7 +243,7 @@ ParserResult AvcVideoParser::ParsePictureData(const uint8_t *p_stream, uint32_t // Reference picture lists construction (8.2.4) if (SetupReflist(&slice_info_list_[num_slices_]) != PARSER_OK) { - ERR("Error occurred in SetupReflist(). Ignore and continue."); + logger_.ErrorLog(MakeMsg("Error occurred in SetupReflist(). Ignore and continue.")); } if (num_slices_ == 0) { @@ -343,7 +343,7 @@ ParserResult AvcVideoParser::NotifyNewSps(AvcSeqParameterSet *p_sps) { break; } default: - ERR(STR("Error: Sequence Callback function - Chroma Format is not supported")); + logger_.ErrorLog(MakeMsg(STR("Error: Sequence Callback function - Chroma Format is not supported"))); return PARSER_FAIL; } int chroma_array_type = p_sps->separate_colour_plane_flag ? 0 : p_sps->chroma_format_idc; @@ -411,7 +411,7 @@ ParserResult AvcVideoParser::NotifyNewSps(AvcSeqParameterSet *p_sps) { // callback function with RocdecVideoFormat params filled out if (pfn_sequence_cb_(parser_params_.user_data, &video_format_params_) == 0) { - ERR("Sequence callback function failed."); + logger_.ErrorLog(MakeMsg("Sequence callback function failed.")); return PARSER_FAIL; } else { return PARSER_OK; @@ -716,7 +716,7 @@ ParserResult AvcVideoParser::SendPicForDecode() { #endif // DBGINFO if (pfn_decode_picture_cb_(parser_params_.user_data, &dec_pic_params_) == 0) { - ERR("Decode error occurred."); + logger_.ErrorLog(MakeMsg("Decode error occurred.")); return PARSER_FAIL; } else { return PARSER_OK; @@ -1036,7 +1036,7 @@ ParserResult AvcVideoParser::ParsePps(uint8_t *p_stream, size_t stream_size_in_b uint32_t seq_parameter_set_id = Parser::ExpGolomb::ReadUe(p_stream, offset); CHECK_ALLOWED_RANGE("seq_parameter_set_id", seq_parameter_set_id, 0, 31); if (sps_list_[seq_parameter_set_id].is_received == 0) { - ERR("Empty SPS is referred."); + logger_.ErrorLog(MakeMsg("Empty SPS is referred.")); return PARSER_WRONG_STATE; } p_sps = &sps_list_[seq_parameter_set_id]; @@ -1051,7 +1051,7 @@ ParserResult AvcVideoParser::ParsePps(uint8_t *p_stream, size_t stream_size_in_b p_pps->num_slice_groups_minus1 = Parser::ExpGolomb::ReadUe(p_stream, offset); if (p_pps->num_slice_groups_minus1 > 0) { // Note: VCN supports High Profile only (num_slice_groups_minus1 = 0) - ERR("Multiple slice groups are not supported"); + logger_.ErrorLog(MakeMsg("Multiple slice groups are not supported")); return PARSER_NOT_SUPPORTED; } @@ -1224,7 +1224,7 @@ ParserResult AvcVideoParser::ParseSliceHeader(uint8_t *p_stream, size_t stream_s int32_t active_pps_id = Parser::ExpGolomb::ReadUe(p_stream, offset); CHECK_ALLOWED_RANGE("pic_parameter_set_id", active_pps_id, 0, 255); if (pps_list_[active_pps_id].is_received == 0) { - ERR("Empty PPS is referred."); + logger_.ErrorLog(MakeMsg("Empty PPS is referred.")); return PARSER_WRONG_STATE; } active_pps_id_ = active_pps_id; @@ -1233,14 +1233,14 @@ ParserResult AvcVideoParser::ParseSliceHeader(uint8_t *p_stream, size_t stream_s int32_t active_sps_id = p_pps->seq_parameter_set_id; if (sps_list_[active_sps_id].is_received == 0) { - ERR("Empty SPS is referred."); + logger_.ErrorLog(MakeMsg("Empty SPS is referred.")); return PARSER_WRONG_STATE; } if (active_sps_id_ != p_pps->seq_parameter_set_id) { active_sps_id_ = p_pps->seq_parameter_set_id; p_sps = &sps_list_[active_sps_id_]; if ( p_sps->is_received == 0) { - ERR("Empty SPS is referred."); + logger_.ErrorLog(MakeMsg("Empty SPS is referred.")); return PARSER_WRONG_STATE; } new_seq_activated_ = true; // Note: clear this flag after the actions are taken. @@ -1922,7 +1922,7 @@ ParserResult AvcVideoParser::DecodeFrameNumGaps() { if (slice_nal_unit_header_.nal_unit_type == kAvcNalTypeSlice_IDR) { prev_ref_frame_num_ = 0; } else if ((p_slice_header->frame_num != prev_ref_frame_num_) && (p_slice_header->frame_num != ((prev_ref_frame_num_ + 1) % max_frame_num))) { - ERR("Support for gaps in frame_num is currently disabled.\n"); + logger_.ErrorLog(MakeMsg("Support for gaps in frame_num is currently disabled.")); return PARSER_NOT_SUPPORTED; #if 0 int unused_short_term_frame_num = (prev_ref_frame_num_ + 1) % max_frame_num; @@ -2061,7 +2061,7 @@ ParserResult AvcVideoParser::DecodeFrameNumGaps() { if (min_index < dpb_buffer_.dpb_size) { dpb_buffer_.frame_buffer_list[min_index].is_reference = kUnusedForReference; } else { - ERR("Could not find any short term ref picture."); + logger_.ErrorLog(MakeMsg("Could not find any short term ref picture.")); return PARSER_FAIL; } dpb_buffer_.num_short_term--; @@ -2086,7 +2086,7 @@ ParserResult AvcVideoParser::DecodeFrameNumGaps() { dpb_buffer_.dpb_fullness++; dpb_buffer_.num_short_term++; } else { - ERR("Could not find any free frame buffer in DPB."); + logger_.ErrorLog(MakeMsg("Could not find any free frame buffer in DPB.")); return PARSER_FAIL; } @@ -2627,7 +2627,7 @@ ParserResult AvcVideoParser::ModifiyRefList(AvcPicture *ref_pic_list_x, AvcListM } } if (i == num_short_term_pics) { - ERR("Could not find a short-term reference with the modified pic num."); + logger_.ErrorLog(MakeMsg("Could not find a short-term reference with the modified pic num.")); return PARSER_OUT_OF_RANGE; } ref_pic_list_mod[ref_idx_lx] = ref_pic_list_x[i]; @@ -2654,7 +2654,7 @@ ParserResult AvcVideoParser::ModifiyRefList(AvcPicture *ref_pic_list_x, AvcListM } } if (i == num_short_term_pics + num_long_term_pics) { - ERR("Could not find long-term reference with the modified long term pic num."); + logger_.ErrorLog(MakeMsg("Could not find long-term reference with the modified long term pic num.")); return PARSER_OUT_OF_RANGE; } ref_pic_list_mod[ref_idx_lx] = ref_pic_list_x[i]; @@ -2701,7 +2701,7 @@ ParserResult AvcVideoParser::FindFreeInDecBufPool() { } } if (dec_buf_index == dec_buf_pool_size_) { - ERR("Could not find a free buffer in decode buffer pool."); + logger_.ErrorLog(MakeMsg("Could not find a free buffer in decode buffer pool.")); return PARSER_NOT_FOUND; } @@ -2740,7 +2740,7 @@ ParserResult AvcVideoParser::FindFreeBufInDpb() { curr_pic_.use_status = kBottomFieldUsedForDecode; } } else { - ERR("Could not find any free frame buffer in DPB."); + logger_.ErrorLog(MakeMsg("Could not find any free frame buffer in DPB.")); return PARSER_FAIL; } @@ -3047,7 +3047,7 @@ ParserResult AvcVideoParser::MarkDecodedRefPics() { break; default: { - ERR("Invalid memory management control operation!"); + logger_.ErrorLog(MakeMsg("Invalid memory management control operation!")); return PARSER_INVALID_ARG; } } @@ -3079,7 +3079,7 @@ ParserResult AvcVideoParser::MarkDecodedRefPics() { dpb_buffer_.field_pic_list[min_index * 2].is_reference = kUnusedForReference; dpb_buffer_.field_pic_list[min_index * 2 + 1].is_reference = kUnusedForReference; } else { - ERR("Could not find any short term ref picture."); + logger_.ErrorLog(MakeMsg("Could not find any short term ref picture.")); return PARSER_FAIL; } dpb_buffer_.num_short_term--; @@ -3114,7 +3114,7 @@ ParserResult AvcVideoParser::BumpPicFromDpb() { } } if (min_poc_pic_idx_no_ref >= dpb_buffer_.dpb_size) { - ERR("Error! Could not find a non-reference buffer to bump."); + logger_.ErrorLog(MakeMsg("Error! Could not find a non-reference buffer to bump.")); return PARSER_OUT_OF_RANGE; } @@ -3126,7 +3126,7 @@ ParserResult AvcVideoParser::BumpPicFromDpb() { // Insert into output/display picture list if (pfn_display_picture_cb_) { if (num_output_pics_ >= dec_buf_pool_size_) { - ERR("Error! Decode buffer pool overflow!"); + logger_.ErrorLog(MakeMsg("Error! Decode buffer pool overflow!")); return PARSER_OUT_OF_RANGE; } else { output_pic_list_[num_output_pics_] = dpb_buffer_.frame_buffer_list[min_poc_pic_idx_ref].dec_buf_idx; @@ -3154,7 +3154,7 @@ ParserResult AvcVideoParser::BumpPicFromDpb() { // Insert into output/display picture list if (pfn_display_picture_cb_) { if (num_output_pics_ >= dec_buf_pool_size_) { - ERR("Error! Decode buffer pool overflow!"); + logger_.ErrorLog(MakeMsg("Error! Decode buffer pool overflow!")); return PARSER_OUT_OF_RANGE; } else { output_pic_list_[num_output_pics_] = dpb_buffer_.frame_buffer_list[min_poc_pic_idx_no_ref].dec_buf_idx; @@ -3237,7 +3237,7 @@ ParserResult AvcVideoParser::InsertCurrPicIntoDpb() { decode_buffer_pool_[curr_pic_.dec_buf_idx].pic_order_cnt = curr_pic_.pic_order_cnt; decode_buffer_pool_[curr_pic_.dec_buf_idx].pts = curr_pts_; } else { - ERR("Could not find the reserved frame buffer for the current picture in DPB."); + logger_.ErrorLog(MakeMsg("Could not find the reserved frame buffer for the current picture in DPB.")); return PARSER_FAIL; } diff --git a/src/parser/hevc_parser.cpp b/src/parser/hevc_parser.cpp index d74cf30db..7191bd15f 100644 --- a/src/parser/hevc_parser.cpp +++ b/src/parser/hevc_parser.cpp @@ -59,7 +59,7 @@ rocDecStatus HevcVideoParser::ParseVideoData(RocdecSourceDataPacket *p_data) { if (p_data->payload && p_data->payload_size) { curr_pts_ = p_data->pts; if (ParsePictureData(p_data->payload, p_data->payload_size) != PARSER_OK) { - ERR(STR("Parser failed!")); + logger_.ErrorLog(MakeMsg(STR("Parser failed!"))); return ROCDEC_RUNTIME_ERROR; } @@ -83,7 +83,7 @@ rocDecStatus HevcVideoParser::ParseVideoData(RocdecSourceDataPacket *p_data) { // Decode the picture if (SendPicForDecode() != PARSER_OK) { - ERR(STR("Failed to decode!")); + logger_.ErrorLog(MakeMsg(STR("Failed to decode!"))); return ROCDEC_RUNTIME_ERROR; } @@ -148,7 +148,7 @@ int HevcVideoParser::FillSeqCallbackFn(HevcSeqParamSet* sps_data) { break; } default: - ERR(STR("Error: Sequence Callback function - Chroma Format is not supported")); + logger_.ErrorLog(MakeMsg(STR("Error: Sequence Callback function - Chroma Format is not supported"))); return PARSER_FAIL; } if(sps_data->conformance_window_flag) { @@ -207,7 +207,7 @@ int HevcVideoParser::FillSeqCallbackFn(HevcSeqParamSet* sps_data) { // callback function with RocdecVideoFormat params filled out if (pfn_sequence_cb_(parser_params_.user_data, &video_format_params_) == 0) { - ERR("Sequence callback function failed."); + logger_.ErrorLog(MakeMsg("Sequence callback function failed.")); return PARSER_FAIL; } else { return PARSER_OK; @@ -412,7 +412,7 @@ int HevcVideoParser::SendPicForDecode() { } } if (j == 15) { - ERR("Could not find matching pic in ref_frames list. The slice type is P/B, and the idx from the ref_pic_list_0_ is: " + TOSTR(idx)); + logger_.ErrorLog(MakeMsg("Could not find matching pic in ref_frames list. The slice type is P/B, and the idx from the ref_pic_list_0_ is: " + TOSTR(idx))); return PARSER_FAIL; } else { slice_params_ptr->ref_pic_list[0][i] = j; @@ -429,7 +429,7 @@ int HevcVideoParser::SendPicForDecode() { } } if (j == 15) { - ERR("Could not find matching pic in ref_frames list. The slice type is B, and the idx from the ref_pic_list_1_ is: " + TOSTR(idx)); + logger_.ErrorLog(MakeMsg("Could not find matching pic in ref_frames list. The slice type is B, and the idx from the ref_pic_list_1_ is: " + TOSTR(idx))); return PARSER_FAIL; } else { slice_params_ptr->ref_pic_list[1][i] = j; @@ -520,7 +520,7 @@ int HevcVideoParser::SendPicForDecode() { #endif // DBGINFO if (pfn_decode_picture_cb_(parser_params_.user_data, &dec_pic_params_) == 0) { - ERR("Decode error occurred."); + logger_.ErrorLog(MakeMsg("Decode error occurred.")); return PARSER_FAIL; } else { return PARSER_OK; @@ -545,7 +545,7 @@ ParserResult HevcVideoParser::ParsePictureData(const uint8_t* p_stream, uint32_t do { ret = GetNalUnit(); if (ret == PARSER_NOT_FOUND) { - ERR(STR("Error: no start code found in the frame data.")); + logger_.ErrorLog(MakeMsg(STR("Error: no start code found in the frame data."))); return ret; } // Parse the NAL unit @@ -1254,7 +1254,7 @@ ParserResult HevcVideoParser::ParseVps(uint8_t *nalu, size_t size) { p_vps->vps_temporal_id_nesting_flag = Parser::GetBit(nalu, offset); p_vps->vps_reserved_0xffff_16bits = Parser::ReadBits(nalu, offset, 16); if (p_vps->vps_reserved_0xffff_16bits != 0xFFFF) { - ERR("vps_reserved_0xffff_16bits is not equal to 0xFFFF."); + logger_.ErrorLog(MakeMsg("vps_reserved_0xffff_16bits is not equal to 0xFFFF.")); return PARSER_INVALID_ARG; } ParsePtl(&p_vps->profile_tier_level, true, p_vps->vps_max_sub_layers_minus1, nalu, size, offset); @@ -1374,12 +1374,12 @@ ParserResult HevcVideoParser::ParseSps(uint8_t *nalu, size_t size) { } sps_ptr->bit_depth_luma_minus8 = Parser::ExpGolomb::ReadUe(nalu, offset); if ( sps_ptr->bit_depth_luma_minus8 != 0 && sps_ptr->bit_depth_luma_minus8 != 2) { - ERR("bit_depth_luma_minus8 = " + TOSTR(sps_ptr->bit_depth_luma_minus8) + " is not supported"); + logger_.ErrorLog(MakeMsg("bit_depth_luma_minus8 = " + TOSTR(sps_ptr->bit_depth_luma_minus8) + " is not supported")); return PARSER_OUT_OF_RANGE; } sps_ptr->bit_depth_chroma_minus8 = Parser::ExpGolomb::ReadUe(nalu, offset); if ( sps_ptr->bit_depth_chroma_minus8 != 0 && sps_ptr->bit_depth_chroma_minus8 != 2) { - ERR("bit_depth_chroma_minus8 = " + TOSTR(sps_ptr->bit_depth_chroma_minus8) + " is not supported"); + logger_.ErrorLog(MakeMsg("bit_depth_chroma_minus8 = " + TOSTR(sps_ptr->bit_depth_chroma_minus8) + " is not supported")); return PARSER_OUT_OF_RANGE; } sps_ptr->log2_max_pic_order_cnt_lsb_minus4 = Parser::ExpGolomb::ReadUe(nalu, offset); @@ -1444,7 +1444,7 @@ ParserResult HevcVideoParser::ParseSps(uint8_t *nalu, size_t size) { sps_ptr->log2_min_pcm_luma_coding_block_size_minus3 = Parser::ExpGolomb::ReadUe(nalu, offset); //CHECK_ALLOWED_RANGE("log2_min_pcm_luma_coding_block_size", sps_ptr->log2_min_pcm_luma_coding_block_size_minus3 + 3, std::min(min_cb_log2_size_y, 5), std::min(ctb_log2_size_y_, 5)); if ((sps_ptr->log2_min_pcm_luma_coding_block_size_minus3 + 3) < std::min(min_cb_log2_size_y, 5) || (sps_ptr->log2_min_pcm_luma_coding_block_size_minus3 + 3) > std::min(ctb_log2_size_y_, 5)) { - ERR("log2_min_pcm_luma_coding_block_size = " + TOSTR(sps_ptr->log2_min_pcm_luma_coding_block_size_minus3 + 3) + " not in allowd range: " + TOSTR(std::min(min_cb_log2_size_y, 5)) + ", " + TOSTR(std::min(ctb_log2_size_y_, 5))); + logger_.ErrorLog(MakeMsg("log2_min_pcm_luma_coding_block_size = " + TOSTR(sps_ptr->log2_min_pcm_luma_coding_block_size_minus3 + 3) + " not in allowd range: " + TOSTR(std::min(min_cb_log2_size_y, 5)) + ", " + TOSTR(std::min(ctb_log2_size_y_, 5)))); } sps_ptr->log2_diff_max_min_pcm_luma_coding_block_size = Parser::ExpGolomb::ReadUe(nalu, offset); CHECK_ALLOWED_MAX("log2_max_ipcm_cb_size_y", sps_ptr->log2_diff_max_min_pcm_luma_coding_block_size + sps_ptr->log2_min_pcm_luma_coding_block_size_minus3 + 3, std::min(ctb_log2_size_y_, 5)); @@ -1650,7 +1650,7 @@ ParserResult HevcVideoParser::ParseSliceHeader(uint8_t *nalu, size_t size, HevcS int32_t active_pps_id = Parser::ExpGolomb::ReadUe(nalu, offset); CHECK_ALLOWED_MAX("active_pps_id", active_pps_id, (MAX_PPS_COUNT - 1)); if (pps_list_[active_pps_id].is_received == 0) { - ERR("Empty PPS is referred."); + logger_.ErrorLog(MakeMsg("Empty PPS is referred.")); return PARSER_WRONG_STATE; } active_pps_id_ = active_pps_id; @@ -1659,7 +1659,7 @@ ParserResult HevcVideoParser::ParseSliceHeader(uint8_t *nalu, size_t size, HevcS int32_t active_sps_id = pps_ptr->pps_seq_parameter_set_id; if (sps_list_[active_sps_id].is_received == 0) { - ERR("Empty SPS is referred."); + logger_.ErrorLog(MakeMsg("Empty SPS is referred.")); return PARSER_WRONG_STATE; } if (active_sps_id_ != active_sps_id) { @@ -1671,7 +1671,7 @@ ParserResult HevcVideoParser::ParseSliceHeader(uint8_t *nalu, size_t size, HevcS int active_vps_id = sps_ptr->sps_video_parameter_set_id; if (vps_list_[active_vps_id].is_received == 0) { - ERR("Empty VPS is referred."); + logger_.ErrorLog(MakeMsg("Empty VPS is referred.")); return PARSER_WRONG_STATE; } active_vps_id_ = active_vps_id; @@ -2345,7 +2345,7 @@ int HevcVideoParser::MarkOutputPictures() { if (dpb_buffer_.dpb_fullness > 0) { dpb_buffer_.dpb_fullness--; } else { - ERR("Invalid DPB buffer fullness:" + TOSTR(dpb_buffer_.dpb_fullness)); + logger_.ErrorLog(MakeMsg("Invalid DPB buffer fullness:" + TOSTR(dpb_buffer_.dpb_fullness))); return PARSER_FAIL; } } @@ -2384,7 +2384,7 @@ ParserResult HevcVideoParser::FindFreeInDecBufPool() { } } if (dec_buf_index == dec_buf_pool_size_) { - ERR("Could not find a free buffer in decode buffer pool."); + logger_.ErrorLog(MakeMsg("Could not find a free buffer in decode buffer pool.")); return PARSER_NOT_FOUND; } curr_pic_info_.dec_buf_idx = dec_buf_index; @@ -2406,7 +2406,7 @@ ParserResult HevcVideoParser::FindFreeInDpbAndMark() { } } if (index == dpb_buffer_.dpb_size) { - ERR("Error! DPB buffer overflow! Fullness = " + TOSTR(dpb_buffer_.dpb_fullness)); + logger_.ErrorLog(MakeMsg("Error! DPB buffer overflow! Fullness = " + TOSTR(dpb_buffer_.dpb_fullness))); return PARSER_NOT_FOUND; } @@ -2487,7 +2487,7 @@ int HevcVideoParser::BumpPicFromDpb() { // Insert into output/display picture list if (pfn_display_picture_cb_) { if (num_output_pics_ >= dec_buf_pool_size_) { - ERR("Error! Decode buffer pool overflow!"); + logger_.ErrorLog(MakeMsg("Error! Decode buffer pool overflow!")); return PARSER_OUT_OF_RANGE; } else { output_pic_list_[num_output_pics_] = dpb_buffer_.frame_buffer_list[min_poc_pic_idx].dec_buf_idx; diff --git a/src/parser/roc_video_parser.cpp b/src/parser/roc_video_parser.cpp index 888357b1a..1d05951c2 100644 --- a/src/parser/roc_video_parser.cpp +++ b/src/parser/roc_video_parser.cpp @@ -56,7 +56,7 @@ RocVideoParser::~RocVideoParser() { */ rocDecStatus RocVideoParser::Initialize(RocdecParserParams *pParams) { if(pParams == nullptr) { - ERR(STR("Parser parameters are not set for the parser")); + logger_.CriticalLog(STR("Parser parameters are not set for the parser")); return ROCDEC_NOT_INITIALIZED; } // Initialize callback function pointers diff --git a/src/parser/roc_video_parser.h b/src/parser/roc_video_parser.h index 807fbc958..45c3f0735 100644 --- a/src/parser/roc_video_parser.h +++ b/src/parser/roc_video_parser.h @@ -82,14 +82,14 @@ typedef struct { #define CHECK_ALLOWED_RANGE(str, val, min, max) { \ if (val < min || val > max) { \ - ERR (STR(str) + " value not in valid range: " + TOSTR(val) + ", allowed (min,max): " + TOSTR(min) + "," + TOSTR(max));\ + logger_.ErrorLog(MakeMsg(STR(str) + " value not in valid range: " + TOSTR(val) + ", allowed (min,max): " + TOSTR(min) + "," + TOSTR(max)));\ return PARSER_OUT_OF_RANGE; \ } \ } #define CHECK_ALLOWED_MAX(str, val, max) { \ if (val > max) { \ - ERR (STR(str) + " value greater than maximum allowed value: " + TOSTR(val) + ", max: " + TOSTR(max));\ + logger_.ErrorLog(MakeMsg(STR(str) + " value greater than maximum allowed value: " + TOSTR(val) + ", max: " + TOSTR(max))); \ return PARSER_OUT_OF_RANGE; \ } \ } @@ -110,7 +110,7 @@ class RocVideoParser { public: RocVideoParser(); // default constructor virtual ~RocVideoParser(); - RocVideoParser(RocdecParserParams *pParams) : parser_params_(*pParams) {}; + RocVideoParser(RocdecParserParams *pParams, u_int log_level) : parser_params_(*pParams) {logger_.SetLogLevel(log_level);}; virtual void SetParserParams(RocdecParserParams *pParams) { parser_params_ = *pParams; }; RocdecParserParams *GetParserParams() {return &parser_params_;}; virtual rocDecStatus Initialize(RocdecParserParams *pParams); @@ -190,6 +190,8 @@ class RocVideoParser { uint32_t sei_payload_buf_size_; uint32_t sei_payload_size_; // total SEI payload size of the current frame + RocDecLogger logger_; + /*! \brief Function to check the initially set (by decoder) decode buffer pool size and adjust if needed * \param dpb_size The DPB buffer size of the current sequence */ diff --git a/src/parser/rocparser_api.cpp b/src/parser/rocparser_api.cpp index 48e5ed2fc..fdbce2342 100644 --- a/src/parser/rocparser_api.cpp +++ b/src/parser/rocparser_api.cpp @@ -38,7 +38,7 @@ rocDecCreateVideoParser(RocdecVideoParser *parser_handle, RocdecParserParams *pa parser_params->codec_type != rocDecVideoCodec_AVC && parser_params->codec_type != rocDecVideoCodec_VP9 && parser_params->codec_type != rocDecVideoCodec_AV1) { - ERR("The current version of rocDecode officially supports only the H.265 (HEVC), H.264 (AVC) and AV1 codecs."); + RocDecLogger::AlwaysLog("Error: The current version of rocDecode officially supports only the H.265 (HEVC), H.264 (AVC), AV1 and VP9 codecs."); return ROCDEC_NOT_IMPLEMENTED; } @@ -47,7 +47,7 @@ rocDecCreateVideoParser(RocdecVideoParser *parser_handle, RocdecParserParams *pa handle = new RocParserHandle(parser_params); } catch(const std::exception& e) { - ERR( STR("Failed to init the rocDecode handle, ") + STR(e.what())) + RocDecLogger::AlwaysLog(STR("Error: Failed to init the rocDecode handle, ") + STR(e.what())); return ROCDEC_RUNTIME_ERROR; } *parser_handle = handle; @@ -76,7 +76,7 @@ rocDecParseVideoData(RocdecVideoParser parser_handle, RocdecSourceDataPacket *pa } catch(const std::exception& e) { roc_parser_handle->CaptureError(e.what()); - ERR(e.what()) + RocDecLogger::AlwaysLog(e.what()); return ROCDEC_RUNTIME_ERROR; } return ret; @@ -100,7 +100,7 @@ rocDecDestroyVideoParser(RocdecVideoParser parser_handle) { catch(const std::exception& e) { roc_parser_handle->CaptureError(e.what()); delete roc_parser_handle; - ERR(e.what()) + RocDecLogger::AlwaysLog(e.what()); return ROCDEC_RUNTIME_ERROR; } delete roc_parser_handle; diff --git a/src/parser/vp9_parser.cpp b/src/parser/vp9_parser.cpp index 7d5184ea3..01ae28731 100644 --- a/src/parser/vp9_parser.cpp +++ b/src/parser/vp9_parser.cpp @@ -64,7 +64,7 @@ rocDecStatus Vp9VideoParser::ParseVideoData(RocdecSourceDataPacket *p_data) { if (p_data->payload && p_data->payload_size) { curr_pts_ = p_data->pts; if (ParsePictureData(p_data->payload, p_data->payload_size) != PARSER_OK) { - ERR("Error occurred in ParsePictureData()."); + logger_.ErrorLog(MakeMsg("Error occurred in ParsePictureData().")); return ROCDEC_RUNTIME_ERROR; } } else if (!(p_data->flags & ROCDEC_PKT_ENDOFSTREAM)) { @@ -87,7 +87,7 @@ ParserResult Vp9VideoParser::ParsePictureData(const uint8_t *p_stream, uint32_t uint8_t *pic_data_ptr = const_cast(p_stream); for (int frame_index = 0; frame_index < num_frames_in_chunck_; frame_index++) { if ((ret = ParseUncompressedHeader(pic_data_ptr, frame_sizes_[frame_index])) != PARSER_OK) { - ERR("Error occurred in ParseUncompressedHeader(). Skip this picture."); + logger_.ErrorLog(MakeMsg("Error occurred in ParseUncompressedHeader(). Skip this picture.")); } else { // Init Roc decoder for the first time or reconfigure the existing decoder if (new_seq_activated_) { @@ -103,7 +103,7 @@ ParserResult Vp9VideoParser::ParsePictureData(const uint8_t *p_stream, uint32_t if (uncompressed_header_.show_existing_frame) { int disp_idx = dpb_buffer_.virtual_buffer_index[uncompressed_header_.frame_to_show_map_idx]; if (disp_idx == INVALID_INDEX) { - ERR("Invalid existing frame index to show."); + logger_.ErrorLog(MakeMsg("Invalid existing frame index to show.")); return PARSER_INVALID_ARG; } if (pfn_display_picture_cb_) { @@ -115,7 +115,7 @@ ParserResult Vp9VideoParser::ParsePictureData(const uint8_t *p_stream, uint32_t output_pic_list_[num_output_pics_] = disp_idx; num_output_pics_++; } else { - ERR("Display list size larger than decode buffer pool size!"); + logger_.ErrorLog(MakeMsg("Display list size larger than decode buffer pool size!")); return PARSER_OUT_OF_RANGE; } } @@ -134,7 +134,7 @@ ParserResult Vp9VideoParser::ParsePictureData(const uint8_t *p_stream, uint32_t return ret; } if ((ret = SendPicForDecode()) != PARSER_OK) { - ERR(STR("Failed to decode!")); + logger_.ErrorLog(MakeMsg(STR("Failed to decode!"))); return ret; } #if DBGINFO @@ -213,7 +213,7 @@ ParserResult Vp9VideoParser::NotifyNewSequence(Vp9UncompressedHeader *p_uncomp_h } else if (p_uncomp_header->color_config.subsampling_x == 0 && p_uncomp_header->color_config.subsampling_y == 0) { video_format_params_.chroma_format = rocDecVideoChromaFormat_444; } else { - ERR("Unsupported chroma format."); + logger_.ErrorLog(MakeMsg("Unsupported chroma format.")); return PARSER_INVALID_FORMAT; } @@ -238,7 +238,7 @@ ParserResult Vp9VideoParser::NotifyNewSequence(Vp9UncompressedHeader *p_uncomp_h // callback function with RocdecVideoFormat params filled out if (pfn_sequence_cb_(parser_params_.user_data, &video_format_params_) == 0) { - ERR("Sequence callback function failed."); + logger_.ErrorLog(MakeMsg("Sequence callback function failed.")); return PARSER_FAIL; } else { return PARSER_OK; @@ -335,7 +335,7 @@ ParserResult Vp9VideoParser::SendPicForDecode() { #endif // DBGINFO if (pfn_decode_picture_cb_(parser_params_.user_data, &dec_pic_params_) == 0) { - ERR("Decode error occurred."); + logger_.ErrorLog(MakeMsg("Decode error occurred.")); return PARSER_FAIL; } else { return PARSER_OK; @@ -390,7 +390,7 @@ ParserResult Vp9VideoParser::FindFreeInDecBufPool() { } } if (dec_buf_index == dec_buf_pool_size_) { - ERR("Could not find a free buffer in decode buffer pool for decoded image."); + logger_.ErrorLog(MakeMsg("Could not find a free buffer in decode buffer pool for decoded image.")); return PARSER_NOT_FOUND; } curr_pic_.dec_buf_idx = dec_buf_index; @@ -407,7 +407,7 @@ ParserResult Vp9VideoParser::FindFreeInDpbAndMark() { } } if (i == VP9_BUFFER_POOL_MAX_SIZE) { - ERR("DPB buffer overflow!"); + logger_.ErrorLog(MakeMsg("DPB buffer overflow!")); return PARSER_NOT_FOUND; } curr_pic_.pic_idx = i; @@ -424,7 +424,7 @@ ParserResult Vp9VideoParser::FindFreeInDpbAndMark() { output_pic_list_[num_output_pics_] = disp_idx; num_output_pics_++; } else { - ERR("Display list size larger than decode buffer pool size!"); + logger_.ErrorLog(MakeMsg("Display list size larger than decode buffer pool size!")); return PARSER_OUT_OF_RANGE; } } @@ -453,7 +453,7 @@ ParserResult Vp9VideoParser::ParseUncompressedHeader(uint8_t *p_stream, size_t s if (p_uncomp_header->profile == 3) { p_uncomp_header->reserved_zero = Parser::GetBit(p_stream, offset); if (p_uncomp_header->reserved_zero) { - ERR("Syntax error: reserved_zero in Uncompressed header is not 0 when Profile is 3"); + logger_.ErrorLog(MakeMsg("Syntax error: reserved_zero in Uncompressed header is not 0 when Profile is 3")); return PARSER_INVALID_ARG; } } @@ -529,7 +529,7 @@ ParserResult Vp9VideoParser::ParseUncompressedHeader(uint8_t *p_stream, size_t s } } if (p_uncomp_header->frame_size.frame_width == 0 && p_uncomp_header->frame_size.frame_height == 0) { - ERR("Invalid picture size: width = " + TOSTR(p_uncomp_header->frame_size.frame_width) + ", height = " + TOSTR(p_uncomp_header->frame_size.frame_height) + "."); + logger_.ErrorLog(MakeMsg("Invalid picture size: width = " + TOSTR(p_uncomp_header->frame_size.frame_width) + ", height = " + TOSTR(p_uncomp_header->frame_size.frame_height) + ".")); return PARSER_WRONG_STATE; } @@ -578,7 +578,7 @@ ParserResult Vp9VideoParser::ParseUncompressedHeader(uint8_t *p_stream, size_t s if (pic_width_ <= curr_surface_width_ && pic_height_ <= curr_surface_height_) { reconfig_option_ = ROCDEC_RECONFIG_KEEP_SURFACES; // Keep the existing surfaces } else { - ERR("VP9 video size (up) change on non-key frames is not supported."); + logger_.ErrorLog(MakeMsg("VP9 video size (up) change on non-key frames is not supported.")); return PARSER_WRONG_STATE; } } @@ -586,11 +586,11 @@ ParserResult Vp9VideoParser::ParseUncompressedHeader(uint8_t *p_stream, size_t s } uncomp_header_size_ = (offset + 7) >> 3; if (uncomp_header_size_ > size) { - ERR("Uncompressed header size (" + TOSTR(uncomp_header_size_) + ") exceeds frame data size (" + TOSTR(size) + ")"); + logger_.ErrorLog(MakeMsg("Uncompressed header size (" + TOSTR(uncomp_header_size_) + ") exceeds frame data size (" + TOSTR(size) + ")")); return PARSER_WRONG_STATE; } if (p_uncomp_header->header_size_in_bytes > (size - uncomp_header_size_)) { - ERR("header_size_in_bytes (" + TOSTR(p_uncomp_header->header_size_in_bytes) + ") exceeds allowed size (" + TOSTR(size - uncomp_header_size_) + ")"); + logger_.ErrorLog(MakeMsg("header_size_in_bytes (" + TOSTR(p_uncomp_header->header_size_in_bytes) + ") exceeds allowed size (" + TOSTR(size - uncomp_header_size_) + ")")); return PARSER_WRONG_STATE; } return PARSER_OK; @@ -599,17 +599,17 @@ ParserResult Vp9VideoParser::ParseUncompressedHeader(uint8_t *p_stream, size_t s ParserResult Vp9VideoParser::FrameSyncCode(const uint8_t *p_stream, size_t &offset, Vp9UncompressedHeader *p_uncomp_header) { p_uncomp_header->frame_sync_code.frame_sync_byte_0 = Parser::ReadBits(p_stream, offset, 8); if (p_uncomp_header->frame_sync_code.frame_sync_byte_0 != 0x49) { - ERR("Syntax error: frame_sync_byte_0 is " + TOSTR(p_uncomp_header->frame_sync_code.frame_sync_byte_0) + " but shall be equal to 0x49."); + logger_.ErrorLog(MakeMsg("Syntax error: frame_sync_byte_0 is " + TOSTR(p_uncomp_header->frame_sync_code.frame_sync_byte_0) + " but shall be equal to 0x49.")); return PARSER_INVALID_ARG; } p_uncomp_header->frame_sync_code.frame_sync_byte_1 = Parser::ReadBits(p_stream, offset, 8); if (p_uncomp_header->frame_sync_code.frame_sync_byte_1 != 0x83) { - ERR("Syntax error: frame_sync_byte_1 is " + TOSTR(p_uncomp_header->frame_sync_code.frame_sync_byte_1) + " but shall be equal to 0x83."); + logger_.ErrorLog(MakeMsg("Syntax error: frame_sync_byte_1 is " + TOSTR(p_uncomp_header->frame_sync_code.frame_sync_byte_1) + " but shall be equal to 0x83.")); return PARSER_INVALID_ARG; } p_uncomp_header->frame_sync_code.frame_sync_byte_2 = Parser::ReadBits(p_stream, offset, 8); if (p_uncomp_header->frame_sync_code.frame_sync_byte_2 != 0x42) { - ERR("Syntax error: frame_sync_byte_2 is " + TOSTR(p_uncomp_header->frame_sync_code.frame_sync_byte_2) + " but shall be equal to 0x42."); + logger_.ErrorLog(MakeMsg("Syntax error: frame_sync_byte_2 is " + TOSTR(p_uncomp_header->frame_sync_code.frame_sync_byte_2) + " but shall be equal to 0x42.")); return PARSER_INVALID_ARG; } return PARSER_OK; @@ -624,7 +624,7 @@ ParserResult Vp9VideoParser::ColorConfig(const uint8_t *p_stream, size_t &offset } p_uncomp_header->color_config.color_space = Parser::ReadBits(p_stream, offset, 3); if (p_uncomp_header->profile_low_bit == 0 && p_uncomp_header->color_config.color_space == CS_RGB) { - ERR("It is a requirement of bitstream conformance that color_space is not equal to CS_RGB when profile_low_bit is equal to 0."); + logger_.ErrorLog(MakeMsg("It is a requirement of bitstream conformance that color_space is not equal to CS_RGB when profile_low_bit is equal to 0.")); return PARSER_WRONG_STATE; } if (p_uncomp_header->color_config.color_space != CS_RGB) { @@ -634,7 +634,7 @@ ParserResult Vp9VideoParser::ColorConfig(const uint8_t *p_stream, size_t &offset p_uncomp_header->color_config.subsampling_y = Parser::GetBit(p_stream, offset); p_uncomp_header->color_config.reserved_zero = Parser::GetBit(p_stream, offset); if (p_uncomp_header->color_config.reserved_zero) { - ERR("Syntax error: reserved_zero in color config is not 0 when Profile is 1 or 3"); + logger_.ErrorLog(MakeMsg("Syntax error: reserved_zero in color config is not 0 when Profile is 1 or 3")); return PARSER_INVALID_ARG; } } else { @@ -648,13 +648,13 @@ ParserResult Vp9VideoParser::ColorConfig(const uint8_t *p_stream, size_t &offset p_uncomp_header->color_config.subsampling_y = 0; p_uncomp_header->color_config.reserved_zero = Parser::GetBit(p_stream, offset); if (p_uncomp_header->color_config.reserved_zero) { - ERR("Syntax error: reserved_zero in color config is not 0 when Profile is 1 or 3"); + logger_.ErrorLog(MakeMsg("Syntax error: reserved_zero in color config is not 0 when Profile is 1 or 3")); return PARSER_INVALID_ARG; } } } if (p_uncomp_header->profile_low_bit == 1 && p_uncomp_header->color_config.subsampling_x == 1 && p_uncomp_header->color_config.subsampling_y == 1) { - ERR("It is a requirement of bitstream conformance that either subsampling_x is equal to 0 or subsampling_y is equal to 0 when profile_low_bit is equal to 1."); + logger_.ErrorLog(MakeMsg("It is a requirement of bitstream conformance that either subsampling_x is equal to 0 or subsampling_y is equal to 0 when profile_low_bit is equal to 1.")); return PARSER_WRONG_STATE; } return PARSER_OK; @@ -804,7 +804,7 @@ ParserResult Vp9VideoParser::SegmentationParams(const uint8_t *p_stream, size_t uint8_t feature_sign = Parser::GetBit(p_stream, offset); if (feature_sign) { if (p_uncomp_header->segmentation_params.segmentation_abs_or_delta_update == 1) { - ERR("It is a requirement of bitstream conformance that feature_sign is equal to 0 when segmentation_abs_or_delta_update is equal to 1."); + logger_.ErrorLog(MakeMsg("It is a requirement of bitstream conformance that feature_sign is equal to 0 when segmentation_abs_or_delta_update is equal to 1.")); return PARSER_WRONG_STATE; } feature_value *= -1; diff --git a/src/rocdecode-host/CMakeLists.txt b/src/rocdecode-host/CMakeLists.txt index d514058df..332c35185 100644 --- a/src/rocdecode-host/CMakeLists.txt +++ b/src/rocdecode-host/CMakeLists.txt @@ -30,6 +30,11 @@ elseif(ROCM_PATH) else() set(ROCM_PATH /opt/rocm CACHE PATH "Default ROCm installation path") endif() +# Check if lib/rocm_sysdeps/lib exists in the ROCm path which indicates ROCm installation via TheRock +set(USING_THE_ROCK OFF) +if(EXISTS "${ROCM_PATH}/lib/rocm_sysdeps/lib") + set(USING_THE_ROCK ON) +endif() # Set AMD Clang as default compiler set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED On) @@ -49,6 +54,7 @@ project(rocdecode-host VERSION ${VERSION} LANGUAGES CXX) list(APPEND CMAKE_PREFIX_PATH ${ROCM_PATH}/lib/cmake) list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/../../cmake) +set (HIP_PLATFORM amd CACHE STRING "HIP platform") find_package(HIP QUIET) find_package(Threads QUIET) find_package(rocprofiler-register QUIET) @@ -67,9 +73,9 @@ if(HIP_FOUND AND Threads_FOUND AND FFMPEG_FOUND) endif() # local include files - include_directories(api rocdecode-host ../src/rocdecode ../src/parser) + include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../api ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../rocdecode ${CMAKE_CURRENT_SOURCE_DIR}/../parser) # source files - file(GLOB_RECURSE SOURCES "./*.cpp") + file(GLOB_RECURSE SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp") # rocdecode-host.so add_library(${PROJECT_NAME} SHARED ${SOURCES}) @@ -87,25 +93,31 @@ if(HIP_FOUND AND Threads_FOUND AND FFMPEG_FOUND) endif() #FFMpeg version >= 7.1 set_target_properties(${PROJECT_NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON) + if(USING_THE_ROCK) + set_target_properties(${PROJECT_NAME} PROPERTIES INSTALL_RPATH "$ORIGIN;$ORIGIN/rocm_sysdeps/lib" BUILD_WITH_INSTALL_RPATH TRUE) + endif() + message("-- ${White}AMD ROCm ${PROJECT_NAME} -- CMAKE_CXX_FLAGS:${CMAKE_CXX_FLAGS}${ColourReset}") message("-- ${White}AMD ROCm ${PROJECT_NAME} -- Link Libraries: ${LINK_LIBRARY_LIST}${ColourReset}") # Generate BUILD_INFO - configure_file( ${CMAKE_SOURCE_DIR}/api/rocdecode-host_version.h.in ${CMAKE_CURRENT_BINARY_DIR}/rocdecode-host_version.h @ONLY ) + configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/../../api/rocdecode-host_version.h.in ${CMAKE_CURRENT_BINARY_DIR}/rocdecode-host_version.h @ONLY ) # install rocdecode-host libs -- {ROCM_PATH}/lib set_target_properties(${PROJECT_NAME} PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR}) - install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT runtime NAMELINK_SKIP) - install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}-targets LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT dev NAMELINK_ONLY) - install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT asan) + install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT host NAMELINK_SKIP) + install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}-targets LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT host NAMELINK_ONLY) + install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT host) # install rocdecode include files -- {ROCM_PATH}/include/rocdecode install(FILES ${PROJECT_SOURCE_DIR}/../../api/rocdecode/rocdecode_host.h - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/rocdecode COMPONENT dev) + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/rocdecode COMPONENT host) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}_version.h - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/rocdecode COMPONENT dev) + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/rocdecode COMPONENT host) + # TBD: NOTE the host utils are temp delivered with dev package, need to update downstream apps to move to host package + install(DIRECTORY ${PROJECT_SOURCE_DIR}/../../utils/ffmpegvideodecode DESTINATION ${CMAKE_INSTALL_DATADIR}/rocdecode/utils COMPONENT dev) # Cmake module config file configurations - set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_modules/" CACHE INTERNAL "Default module path.") + set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake_modules/" CACHE INTERNAL "Default module path.") # Export the package for use from the build-tree ## (this registers the build-tree with a global CMake-registry) @@ -139,7 +151,7 @@ if(HIP_FOUND AND Threads_FOUND AND FFMPEG_FOUND) "${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake" "${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" - COMPONENT dev + COMPONENT host ) # Install the export set for use with the install-tree @@ -147,7 +159,7 @@ if(HIP_FOUND AND Threads_FOUND AND FFMPEG_FOUND) FILE ${PROJECT_NAME}-targets.cmake NAMESPACE rocdecode:: DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" - COMPONENT dev + COMPONENT host ) else() diff --git a/src/rocdecode-host/avcodec/avcodec_videodecoder.cpp b/src/rocdecode-host/avcodec/avcodec_videodecoder.cpp index 51d372581..fbbde03f9 100644 --- a/src/rocdecode-host/avcodec/avcodec_videodecoder.cpp +++ b/src/rocdecode-host/avcodec/avcodec_videodecoder.cpp @@ -164,13 +164,13 @@ AvcodecVideoDecoder::~AvcodecVideoDecoder() { rocDecStatus AvcodecVideoDecoder::InitializeDecoder() { if (!decoder_) decoder_ = avcodec_find_decoder(RocDecVideoCodec2AVCodec(decoder_create_info_.codec_type)); if(!decoder_) { - ERR("rocDecode:: Codec not supported by FFMpeg "); + logger_.CriticalLog(MakeMsg("rocDecode:: Codec not supported by FFMpeg ")); return ROCDEC_NOT_SUPPORTED; } if (!dec_context_) { dec_context_ = avcodec_alloc_context3(decoder_); //alloc dec_context_ if (!dec_context_) { - ERR("Could not allocate video codec context"); + logger_.CriticalLog(MakeMsg("Could not allocate video codec context")); return ROCDEC_RUNTIME_ERROR; } // set codec to automatically determine how many threads suits best for the decoding job @@ -185,7 +185,7 @@ rocDecStatus AvcodecVideoDecoder::InitializeDecoder() { // open the codec if (avcodec_open2(dec_context_, decoder_, NULL) < 0) { - ERR("Could not open codec"); + logger_.CriticalLog(MakeMsg("Could not open codec")); return ROCDEC_RUNTIME_ERROR; } // get the output pixel format from dec_context_ @@ -238,7 +238,7 @@ rocDecStatus AvcodecVideoDecoder::SubmitDecode(RocdecPicParamsHost *pPicParams) if (pPicParams->bitstream_data_len > packet_data->second) { void *new_pkt_data = av_realloc(av_pkt->data, (pPicParams->bitstream_data_len + MAX_AV_PACKET_DATA_SIZE)); // add more to avoid frequence reallocation if (!new_pkt_data) { - ERR("ERROR: couldn't allocate packet data"); + logger_.ErrorLog(MakeMsg("ERROR: couldn't allocate packet data")); return ROCDEC_OUTOF_MEMORY; } packet_data->first = static_cast(new_pkt_data); @@ -293,11 +293,11 @@ rocDecStatus AvcodecVideoDecoder::GetDecodeStatus(int pic_idx, RocdecDecodeStatu rocDecStatus AvcodecVideoDecoder::GetVideoFrame(int pic_idx, void **frame_ptr, uint32_t *line_size, RocdecProcParams *vid_postproc_params){ if (p_disp_frame_ == nullptr) { - ERR("GetVideoFrame: No frame available to display"); + logger_.ErrorLog(MakeMsg("GetVideoFrame: No frame available to display")); return ROCDEC_RUNTIME_ERROR; } if (p_disp_frame_->picture_index != pic_idx) { - ERR("GetVideoFrame: pic_index is invalid" ); + logger_.ErrorLog(MakeMsg("GetVideoFrame: pic_index is invalid")); return ROCDEC_INVALID_PARAMETER; } auto p_av_frame = p_disp_frame_->av_frame_ptr; @@ -342,7 +342,7 @@ int AvcodecVideoDecoder::DecodeAvFrame(AVPacket *av_pkt, AVFrame *p_frame) { status = avcodec_send_packet(dec_context_, av_pkt); if (status < 0) { if (av_pkt->data && av_pkt->size) - ERR("Error sending av packet for decoding: status: "); + logger_.ErrorLog(MakeMsg("Error sending av packet for decoding: status:")); return status; } while (status >= 0) { @@ -353,7 +353,7 @@ int AvcodecVideoDecoder::DecodeAvFrame(AVPacket *av_pkt, AVFrame *p_frame) { return 0; } else if (status < 0) { - ERR("Error during decoding"); + logger_.ErrorLog(MakeMsg("Error during decoding")); return 0; } // for the first frame, initialize OutputsurfaceInfo @@ -403,7 +403,7 @@ rocDecStatus AvcodecVideoDecoder::NotifyNewSequence(AVFrame *p_frame) { p_video_format->display_aspect_ratio.y = p_frame->sample_aspect_ratio.den; if (pfn_sequece_cb_ && decoder_create_info_.user_data && pfn_sequece_cb_(decoder_create_info_.user_data, &video_format_host_) == 0) { - ERR("Sequence callback function failed."); + logger_.CriticalLog(MakeMsg("Sequence callback function failed.")); return ROCDEC_RUNTIME_ERROR; } else { return ROCDEC_SUCCESS; diff --git a/src/rocdecode-host/avcodec/avcodec_videodecoder.h b/src/rocdecode-host/avcodec/avcodec_videodecoder.h index c18e8a24c..3310f607c 100644 --- a/src/rocdecode-host/avcodec/avcodec_videodecoder.h +++ b/src/rocdecode-host/avcodec/avcodec_videodecoder.h @@ -164,4 +164,5 @@ class AvcodecVideoDecoder { AVFormatContext * formatContext = nullptr; AVInputFormat * inputFormat = nullptr; + RocDecLogger logger_; }; diff --git a/src/rocdecode-host/roc_decoder_host.cpp b/src/rocdecode-host/roc_decoder_host.cpp index 026903da0..ae10f5f22 100644 --- a/src/rocdecode-host/roc_decoder_host.cpp +++ b/src/rocdecode-host/roc_decoder_host.cpp @@ -30,12 +30,12 @@ RocDecoderHost::~RocDecoderHost() {} rocDecStatus RocDecoderHost::InitializeDecoder() { rocDecStatus rocdec_status = ROCDEC_SUCCESS; if (!decoder_create_info_.user_data) { - ERR("Invalid function callback pointer passed"); + logger_.CriticalLog(MakeMsg("Invalid function callback pointer passed")); return ROCDEC_NOT_INITIALIZED; } rocdec_status = avcodec_video_decoder_.InitializeDecoder(); if (rocdec_status != ROCDEC_SUCCESS) { - ERR("Failed to initialize the FFMpeg Video decoder."); + logger_.CriticalLog(MakeMsg("Failed to initialize the FFMpeg Video decoder.")); return rocdec_status; } return rocdec_status; @@ -45,7 +45,7 @@ rocDecStatus RocDecoderHost::DecodeFrame(RocdecPicParamsHost *pic_params) { rocDecStatus rocdec_status = ROCDEC_SUCCESS; rocdec_status = avcodec_video_decoder_.SubmitDecode(pic_params); if (rocdec_status != ROCDEC_SUCCESS) { - ERR("Decode submission is not successful."); + logger_.ErrorLog(MakeMsg("Decode submission is not successful.")); } return rocdec_status; @@ -55,7 +55,7 @@ rocDecStatus RocDecoderHost::GetDecodeStatus(int pic_idx, RocdecDecodeStatus* de rocDecStatus rocdec_status = ROCDEC_SUCCESS; rocdec_status = avcodec_video_decoder_.GetDecodeStatus(pic_idx, decode_status); if (rocdec_status != ROCDEC_SUCCESS) { - ERR("Failed to query the decode status."); + logger_.ErrorLog(MakeMsg("Failed to query the decode status.")); } return rocdec_status; } @@ -66,7 +66,7 @@ rocDecStatus RocDecoderHost::ReconfigureDecoder(RocdecReconfigureDecoderInfo *re } rocDecStatus rocdec_status = avcodec_video_decoder_.ReconfigureDecoder(reconfig_params); if (rocdec_status != ROCDEC_SUCCESS) { - ERR("Reconfiguration of the decoder failed."); + logger_.CriticalLog(MakeMsg("Reconfiguration of the decoder failed.")); return rocdec_status; } return rocdec_status; @@ -78,7 +78,7 @@ rocDecStatus RocDecoderHost::GetVideoFrame(int pic_idx, void **frame_ptr, uint32 } rocDecStatus rocdec_status = avcodec_video_decoder_.GetVideoFrame(pic_idx, frame_ptr, line_size, vid_postproc_params); if (rocdec_status != ROCDEC_SUCCESS) { - ERR("GetVideoFrame failed."); + logger_.ErrorLog(MakeMsg("GetVideoFrame failed.")); return rocdec_status; } return rocdec_status; diff --git a/src/rocdecode-host/roc_decoder_host.h b/src/rocdecode-host/roc_decoder_host.h index 3410be67a..bbb7f23da 100644 --- a/src/rocdecode-host/roc_decoder_host.h +++ b/src/rocdecode-host/roc_decoder_host.h @@ -48,4 +48,6 @@ class RocDecoderHost { private: AvcodecVideoDecoder avcodec_video_decoder_; RocDecoderHostCreateInfo decoder_create_info_; + + RocDecLogger logger_; }; \ No newline at end of file diff --git a/src/rocdecode-host/rocdecode_host_api.cpp b/src/rocdecode-host/rocdecode_host_api.cpp index 057cd5647..f468edb93 100644 --- a/src/rocdecode-host/rocdecode_host_api.cpp +++ b/src/rocdecode-host/rocdecode_host_api.cpp @@ -37,7 +37,7 @@ rocDecCreateDecoderHost(rocDecDecoderHandle *decoder_handle, RocDecoderHostCreat handle = new DecHandleHost(*decoder_create_info); } catch(const std::exception& e) { - ERR( STR("Failed to init the rocDecode handle, ") + STR(e.what())) + RocDecLogger::AlwaysLog(STR("Error: Failed to init the rocDecode handle, ") + STR(e.what())); return ROCDEC_NOT_INITIALIZED; } *decoder_handle = handle; @@ -92,7 +92,7 @@ rocDecDecodeFrameHost(rocDecDecoderHandle decoder_handle, _RocdecPicParamsHost * } catch(const std::exception& e) { handle->CaptureError(e.what()); - ERR(e.what()) + RocDecLogger::AlwaysLog(e.what()); return ROCDEC_RUNTIME_ERROR; } return ret; @@ -116,7 +116,7 @@ rocDecGetDecodeStatusHost(rocDecDecoderHandle decoder_handle, int pic_idx, Rocde } catch(const std::exception& e) { handle->CaptureError(e.what()); - ERR(e.what()) + RocDecLogger::AlwaysLog(e.what()); return ROCDEC_RUNTIME_ERROR; } return ret; @@ -139,7 +139,7 @@ rocDecReconfigureDecoderHost(rocDecDecoderHandle decoder_handle, RocdecReconfigu } catch(const std::exception& e) { handle->CaptureError(e.what()); - ERR(e.what()) + RocDecLogger::AlwaysLog(e.what()); return ROCDEC_RUNTIME_ERROR; } return ret; @@ -165,7 +165,7 @@ rocDecGetVideoFrameHost(rocDecDecoderHandle decoder_handle, int pic_idx, } catch(const std::exception& e) { handle->CaptureError(e.what()); - ERR(e.what()) + RocDecLogger::AlwaysLog(e.what()); return ROCDEC_RUNTIME_ERROR; } return ret; diff --git a/src/rocdecode/roc_decoder.cpp b/src/rocdecode/roc_decoder.cpp index efdc507ce..090259810 100644 --- a/src/rocdecode/roc_decoder.cpp +++ b/src/rocdecode/roc_decoder.cpp @@ -31,13 +31,13 @@ RocDecoder::RocDecoder(RocDecoderCreateInfo& decoder_create_info): va_video_deco if (hip_interop_[i].hip_mapped_device_mem != nullptr) { hipError_t hip_status = hipFree(hip_interop_[i].hip_mapped_device_mem); if (hip_status != hipSuccess) { - ERR("hipFree failed for picture idx = " + TOSTR(i)); + logger_.CriticalLog(MakeMsg("hipFree failed for picture idx = " + TOSTR(i))); } } if (hip_interop_[i].hip_ext_mem != nullptr) { hipError_t hip_status = hipDestroyExternalMemory(hip_interop_[i].hip_ext_mem); if (hip_status != hipSuccess) { - ERR("hipDestroyExternalMemory failed for picture idx = " + TOSTR(i)); + logger_.CriticalLog(MakeMsg("hipDestroyExternalMemory failed for picture idx = " + TOSTR(i))); } } } @@ -46,7 +46,7 @@ RocDecoder::RocDecoder(RocDecoderCreateInfo& decoder_create_info): va_video_deco rocDecStatus RocDecoder::InitializeDecoder() { rocDecStatus rocdec_status = ROCDEC_SUCCESS; if (decoder_create_info_.num_decode_surfaces < 1) { - ERR("Invalid number of decode surfaces."); + logger_.CriticalLog(MakeMsg("Invalid number of decode surfaces.")); return ROCDEC_INVALID_PARAMETER; } hip_interop_.resize(decoder_create_info_.num_decode_surfaces); @@ -55,7 +55,7 @@ RocDecoder::RocDecoder(RocDecoderCreateInfo& decoder_create_info): va_video_deco } rocdec_status = va_video_decoder_.InitializeDecoder(); if (rocdec_status != ROCDEC_SUCCESS) { - ERR("Failed to initilize the VAAPI Video decoder."); + logger_.CriticalLog(MakeMsg("Failed to initilize the VAAPI Video decoder.")); return rocdec_status; } @@ -66,7 +66,7 @@ rocDecStatus RocDecoder::DecodeFrame(RocdecPicParams *pic_params) { rocDecStatus rocdec_status = ROCDEC_SUCCESS; rocdec_status = va_video_decoder_.SubmitDecode(pic_params); if (rocdec_status != ROCDEC_SUCCESS) { - ERR("Decode submission is not successful."); + logger_.ErrorLog(MakeMsg("Decode submission is not successful.")); } return rocdec_status; @@ -76,7 +76,7 @@ rocDecStatus RocDecoder::GetDecodeStatus(int pic_idx, RocdecDecodeStatus* decode rocDecStatus rocdec_status = ROCDEC_SUCCESS; rocdec_status = va_video_decoder_.GetDecodeStatus(pic_idx, decode_status); if (rocdec_status != ROCDEC_SUCCESS) { - ERR("Failed to query the decode status."); + logger_.ErrorLog(MakeMsg("Failed to query the decode status.")); } return rocdec_status; } @@ -90,7 +90,7 @@ rocDecStatus RocDecoder::ReconfigureDecoder(RocdecReconfigureDecoderInfo *reconf for (int pic_idx = 0; pic_idx < hip_interop_.size(); pic_idx++) { rocdec_status = FreeVideoFrame(pic_idx); if (rocdec_status != ROCDEC_SUCCESS) { - ERR("Releasing the video frame for picture idx = " + TOSTR(pic_idx) + " failed during reconfiguration."); + logger_.ErrorLog(MakeMsg("Releasing the video frame for picture idx = " + TOSTR(pic_idx) + " failed during reconfiguration.")); return rocdec_status; } } @@ -99,7 +99,7 @@ rocDecStatus RocDecoder::ReconfigureDecoder(RocdecReconfigureDecoderInfo *reconf } rocdec_status = va_video_decoder_.ReconfigureDecoder(reconfig_params); if (rocdec_status != ROCDEC_SUCCESS) { - ERR("Reconfiguration of the decoder failed."); + logger_.CriticalLog(MakeMsg("Reconfiguration of the decoder failed.")); return rocdec_status; } return rocdec_status; @@ -114,7 +114,7 @@ rocDecStatus RocDecoder::GetVideoFrame(int pic_idx, void *dev_mem_ptr[3], uint32 // wait on current surface to make sure that it is ready for the HIP interop rocdec_status = va_video_decoder_.SyncSurface(pic_idx); if (rocdec_status != ROCDEC_SUCCESS) { - ERR("Failed to export surface for picture idx = " + TOSTR(pic_idx)); + logger_.ErrorLog(MakeMsg("Failed to export surface for picture idx = " + TOSTR(pic_idx))); return rocdec_status; } @@ -126,7 +126,7 @@ rocDecStatus RocDecoder::GetVideoFrame(int pic_idx, void *dev_mem_ptr[3], uint32 rocdec_status = va_video_decoder_.ExportSurface(pic_idx, va_drm_prime_surface_desc); if (rocdec_status != ROCDEC_SUCCESS) { - ERR("Failed to export surface for picture idx = " + TOSTR(pic_idx)); + logger_.ErrorLog(MakeMsg("Failed to export surface for picture idx = " + TOSTR(pic_idx))); return rocdec_status; } diff --git a/src/rocdecode/roc_decoder.h b/src/rocdecode/roc_decoder.h index 05fae1f37..e85bdcce8 100644 --- a/src/rocdecode/roc_decoder.h +++ b/src/rocdecode/roc_decoder.h @@ -59,4 +59,6 @@ class RocDecoder { VaapiVideoDecoder va_video_decoder_; RocDecoderCreateInfo decoder_create_info_; std::vector hip_interop_; + + RocDecLogger logger_; }; \ No newline at end of file diff --git a/src/rocdecode/rocdecode_api.cpp b/src/rocdecode/rocdecode_api.cpp index c95ed8ee4..4db05ff92 100644 --- a/src/rocdecode/rocdecode_api.cpp +++ b/src/rocdecode/rocdecode_api.cpp @@ -39,7 +39,7 @@ rocDecCreateDecoder(rocDecDecoderHandle *decoder_handle, RocDecoderCreateInfo *d handle = new DecHandle(*decoder_create_info); } catch(const std::exception& e) { - ERR( STR("Failed to init the rocDecode handle, ") + STR(e.what())) + RocDecLogger::AlwaysLog(STR("Error: Failed to init the rocDecode handle, ") + STR(e.what())); return ROCDEC_NOT_INITIALIZED; } *decoder_handle = handle; @@ -75,7 +75,7 @@ rocDecGetDecoderCaps(RocdecDecodeCaps *pdc) { VaContext& va_ctx = VaContext::GetInstance(); rocDecStatus ret = ROCDEC_SUCCESS; if ((ret = va_ctx.CheckDecCapForCodecType(pdc)) != ROCDEC_SUCCESS) { - ERR("Failed to obtain decoder capabilities from driver."); + RocDecLogger::AlwaysLog("Error: Failed to obtain decoder capabilities from driver."); return ret; } else { return ROCDEC_SUCCESS; @@ -99,7 +99,7 @@ rocDecDecodeFrame(rocDecDecoderHandle decoder_handle, RocdecPicParams *pic_param } catch(const std::exception& e) { handle->CaptureError(e.what()); - ERR(e.what()) + RocDecLogger::AlwaysLog(e.what()); return ROCDEC_RUNTIME_ERROR; } return ret; @@ -124,7 +124,7 @@ rocDecGetDecodeStatus(rocDecDecoderHandle decoder_handle, int pic_idx, RocdecDec } catch(const std::exception& e) { handle->CaptureError(e.what()); - ERR(e.what()) + RocDecLogger::AlwaysLog(e.what()); return ROCDEC_RUNTIME_ERROR; } return ret; @@ -147,7 +147,7 @@ rocDecReconfigureDecoder(rocDecDecoderHandle decoder_handle, RocdecReconfigureDe } catch(const std::exception& e) { handle->CaptureError(e.what()); - ERR(e.what()) + RocDecLogger::AlwaysLog(e.what()); return ROCDEC_RUNTIME_ERROR; } return ret; @@ -174,7 +174,7 @@ rocDecGetVideoFrame(rocDecDecoderHandle decoder_handle, int pic_idx, } catch(const std::exception& e) { handle->CaptureError(e.what()); - ERR(e.what()) + RocDecLogger::AlwaysLog(e.what()); return ROCDEC_RUNTIME_ERROR; } return ret; diff --git a/src/rocdecode/vaapi/vaapi_videodecoder.cpp b/src/rocdecode/vaapi/vaapi_videodecoder.cpp index 3cc15848b..d457fbe0f 100644 --- a/src/rocdecode/vaapi/vaapi_videodecoder.cpp +++ b/src/rocdecode/vaapi/vaapi_videodecoder.cpp @@ -32,27 +32,27 @@ VaapiVideoDecoder::~VaapiVideoDecoder() { rocDecStatus rocdec_status = ROCDEC_SUCCESS; rocdec_status = DestroyDataBuffers(); if (rocdec_status != ROCDEC_SUCCESS) { - ERR("DestroyDataBuffers failed"); + logger_.CriticalLog(MakeMsg("DestroyDataBuffers failed")); } VAStatus va_status = VA_STATUS_SUCCESS; va_status = vaDestroySurfaces(va_display_, va_surface_ids_.data(), va_surface_ids_.size()); if (va_status != VA_STATUS_SUCCESS) { - ERR("vaDestroySurfaces failed"); + logger_.CriticalLog(MakeMsg("vaDestroySurfaces failed")); } if (va_context_id_) { va_status = vaDestroyContext(va_display_, va_context_id_); if (va_status != VA_STATUS_SUCCESS) { - ERR("vaDestroyContext failed"); + logger_.CriticalLog(MakeMsg("vaDestroyContext failed")); } } if (va_config_id_) { va_status = vaDestroyConfig(va_display_, va_config_id_); if (va_status != VA_STATUS_SUCCESS) { - ERR("vaDestroyConfig failed"); + logger_.CriticalLog(MakeMsg("vaDestroyConfig failed")); } } if (vaTerminate(va_display_) != VA_STATUS_SUCCESS) { - ERR("Failed to termiate VA"); + logger_.CriticalLog(MakeMsg("Failed to termiate VA")); } } } @@ -63,33 +63,33 @@ rocDecStatus VaapiVideoDecoder::InitializeDecoder() { // 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)) { - ERR("The codec config combination is not supported."); + logger_.CriticalLog(MakeMsg("The codec config combination is not supported.")); return ROCDEC_NOT_SUPPORTED; } VaContext& va_ctx = VaContext::GetInstance(); uint32_t va_ctx_id; if ((rocdec_status = va_ctx.GetVaContext(decoder_create_info_.device_id, &va_ctx_id)) != ROCDEC_SUCCESS) { - ERR("Failed to get VA context."); + logger_.CriticalLog(MakeMsg("Failed to get VA context.")); return rocdec_status; } if ((rocdec_status = va_ctx.GetVaDisplay(va_ctx_id, &va_display_)) != ROCDEC_SUCCESS) { - ERR("Failed to get VA display."); + logger_.CriticalLog(MakeMsg("Failed to get VA display.")); return rocdec_status; } rocdec_status = CreateDecoderConfig(); if (rocdec_status != ROCDEC_SUCCESS) { - ERR("Failed to create a VAAPI decoder configuration."); + logger_.CriticalLog(MakeMsg("Failed to create a VAAPI decoder configuration.")); return rocdec_status; } rocdec_status = CreateSurfaces(); if (rocdec_status != ROCDEC_SUCCESS) { - ERR("Failed to create VAAPI surfaces."); + logger_.CriticalLog(MakeMsg("Failed to create VAAPI surfaces.")); return rocdec_status; } rocdec_status = CreateContext(); if (rocdec_status != ROCDEC_SUCCESS) { - ERR("Failed to create a VAAPI context."); + logger_.CriticalLog(MakeMsg("Failed to create a VAAPI context.")); return rocdec_status; } return rocdec_status; @@ -103,7 +103,7 @@ rocDecStatus VaapiVideoDecoder::SubmitDecode(RocdecPicParams *pPicParams) { // Get the surface id for the current picture, assuming 1:1 mapping between DPB and VAAPI decoded surfaces. if (pPicParams->curr_pic_idx >= va_surface_ids_.size() || pPicParams->curr_pic_idx < 0) { - ERR("curr_pic_idx exceeded the VAAPI surface pool limit."); + logger_.ErrorLog(MakeMsg("curr_pic_idx exceeded the VAAPI surface pool limit.")); return ROCDEC_INVALID_PARAMETER; } curr_surface_id = va_surface_ids_[pPicParams->curr_pic_idx]; @@ -115,7 +115,7 @@ rocDecStatus VaapiVideoDecoder::SubmitDecode(RocdecPicParams *pPicParams) { for (int i = 0; i < 15; i++) { if (pPicParams->pic_params.hevc.ref_frames[i].pic_idx != 0xFF) { if (pPicParams->pic_params.hevc.ref_frames[i].pic_idx >= va_surface_ids_.size() || pPicParams->pic_params.hevc.ref_frames[i].pic_idx < 0) { - ERR("Reference frame index exceeded the VAAPI surface pool limit."); + logger_.ErrorLog(MakeMsg("Reference frame index exceeded the VAAPI surface pool limit.")); return ROCDEC_INVALID_PARAMETER; } pPicParams->pic_params.hevc.ref_frames[i].pic_idx = va_surface_ids_[pPicParams->pic_params.hevc.ref_frames[i].pic_idx]; @@ -135,7 +135,7 @@ rocDecStatus VaapiVideoDecoder::SubmitDecode(RocdecPicParams *pPicParams) { if ((pic_params_size != sizeof(VAPictureParameterBufferHEVC)) || (scaling_list_enabled && (iq_matrix_size != sizeof(VAIQMatrixBufferHEVC))) || (slice_params_size != sizeof(VASliceParameterBufferHEVC))) { - ERR("HEVC data_buffer parameter_size not matching vaapi parameter buffer size."); + logger_.ErrorLog(MakeMsg("HEVC data_buffer parameter_size not matching vaapi parameter buffer size.")); return ROCDEC_RUNTIME_ERROR; } break; @@ -146,7 +146,7 @@ rocDecStatus VaapiVideoDecoder::SubmitDecode(RocdecPicParams *pPicParams) { for (int i = 0; i < 16; i++) { if (pPicParams->pic_params.avc.ref_frames[i].pic_idx != 0xFF) { if (pPicParams->pic_params.avc.ref_frames[i].pic_idx >= va_surface_ids_.size() || pPicParams->pic_params.avc.ref_frames[i].pic_idx < 0) { - ERR("Reference frame index exceeded the VAAPI surface pool limit."); + logger_.ErrorLog(MakeMsg("Reference frame index exceeded the VAAPI surface pool limit.")); return ROCDEC_INVALID_PARAMETER; } pPicParams->pic_params.avc.ref_frames[i].pic_idx = va_surface_ids_[pPicParams->pic_params.avc.ref_frames[i].pic_idx]; @@ -163,7 +163,7 @@ rocDecStatus VaapiVideoDecoder::SubmitDecode(RocdecPicParams *pPicParams) { slice_params_size = sizeof(RocdecAvcSliceParams); if ((pic_params_size != sizeof(VAPictureParameterBufferH264)) || (iq_matrix_size != sizeof(VAIQMatrixBufferH264)) || (slice_params_size != sizeof(VASliceParameterBufferH264))) { - ERR("AVC data_buffer parameter_size not matching vaapi parameter buffer size."); + logger_.ErrorLog(MakeMsg("AVC data_buffer parameter_size not matching vaapi parameter buffer size.")); return ROCDEC_RUNTIME_ERROR; } break; @@ -173,7 +173,7 @@ rocDecStatus VaapiVideoDecoder::SubmitDecode(RocdecPicParams *pPicParams) { for (int i = 0; i < 8; i++) { if (pPicParams->pic_params.vp9.reference_frames[i] != 0xFF) { if (pPicParams->pic_params.vp9.reference_frames[i] >= va_surface_ids_.size()) { - ERR("Reference frame index exceeded the VAAPI surface pool limit."); + logger_.ErrorLog(MakeMsg("Reference frame index exceeded the VAAPI surface pool limit.")); return ROCDEC_INVALID_PARAMETER; } pPicParams->pic_params.vp9.reference_frames[i] = va_surface_ids_[pPicParams->pic_params.vp9.reference_frames[i]]; @@ -184,7 +184,7 @@ rocDecStatus VaapiVideoDecoder::SubmitDecode(RocdecPicParams *pPicParams) { slice_params_ptr = (void*)pPicParams->slice_params.vp9; slice_params_size = sizeof(RocdecVp9SliceParams); if ((pic_params_size != sizeof(VADecPictureParameterBufferVP9)) || (slice_params_size != sizeof(VASliceParameterBufferVP9))) { - ERR("VP9 data_buffer parameter_size not matching vaapi parameter buffer size."); + logger_.ErrorLog(MakeMsg("VP9 data_buffer parameter_size not matching vaapi parameter buffer size.")); return ROCDEC_RUNTIME_ERROR; } break; @@ -195,7 +195,7 @@ rocDecStatus VaapiVideoDecoder::SubmitDecode(RocdecPicParams *pPicParams) { if (pPicParams->pic_params.av1.current_display_picture != 0xFF) { if (pPicParams->pic_params.av1.current_display_picture >= va_surface_ids_.size() || pPicParams->pic_params.av1.current_display_picture < 0) { - ERR("Current display picture index exceeded the VAAPI surface pool limit."); + logger_.ErrorLog(MakeMsg("Current display picture index exceeded the VAAPI surface pool limit.")); return ROCDEC_INVALID_PARAMETER; } pPicParams->pic_params.av1.current_display_picture = va_surface_ids_[pPicParams->pic_params.av1.current_display_picture]; @@ -203,7 +203,7 @@ rocDecStatus VaapiVideoDecoder::SubmitDecode(RocdecPicParams *pPicParams) { for (int i = 0; i < pPicParams->pic_params.av1.anchor_frames_num; i++) { if (pPicParams->pic_params.av1.anchor_frames_list[i] >= va_surface_ids_.size() || pPicParams->pic_params.av1.anchor_frames_list[i] < 0) { - ERR("Anchor frame index exceeded the VAAPI surface pool limit."); + logger_.ErrorLog(MakeMsg("Anchor frame index exceeded the VAAPI surface pool limit.")); return ROCDEC_INVALID_PARAMETER; } pPicParams->pic_params.av1.anchor_frames_list[i] = va_surface_ids_[pPicParams->pic_params.av1.anchor_frames_list[i]]; @@ -212,7 +212,7 @@ rocDecStatus VaapiVideoDecoder::SubmitDecode(RocdecPicParams *pPicParams) { for (int i = 0; i < 8; i++) { if (pPicParams->pic_params.av1.ref_frame_map[i] != 0xFF) { if (pPicParams->pic_params.av1.ref_frame_map[i] >= va_surface_ids_.size() || pPicParams->pic_params.av1.ref_frame_map[i] < 0) { - ERR("Reference frame index exceeded the VAAPI surface pool limit."); + logger_.ErrorLog(MakeMsg("Reference frame index exceeded the VAAPI surface pool limit.")); return ROCDEC_INVALID_PARAMETER; } pPicParams->pic_params.av1.ref_frame_map[i] = va_surface_ids_[pPicParams->pic_params.av1.ref_frame_map[i]]; @@ -226,14 +226,14 @@ rocDecStatus VaapiVideoDecoder::SubmitDecode(RocdecPicParams *pPicParams) { slice_params_size = sizeof(RocdecAv1SliceParams); if ((pic_params_size != sizeof(VADecPictureParameterBufferAV1)) || (slice_params_size != sizeof(VASliceParameterBufferAV1))) { - ERR("AV1 data_buffer parameter_size not matching vaapi parameter buffer size."); + logger_.CriticalLog(MakeMsg("AV1 data_buffer parameter_size not matching vaapi parameter buffer size.")); return ROCDEC_RUNTIME_ERROR; } break; } default: { - ERR("The codec type is not supported."); + logger_.CriticalLog(MakeMsg("The codec type is not supported.")); return ROCDEC_NOT_SUPPORTED; } } @@ -241,7 +241,7 @@ rocDecStatus VaapiVideoDecoder::SubmitDecode(RocdecPicParams *pPicParams) { // Destroy the data buffers of the previous frame rocDecStatus rocdec_status = DestroyDataBuffers(); if (rocdec_status != ROCDEC_SUCCESS) { - ERR("Failed to destroy VAAPI buffer."); + logger_.CriticalLog(MakeMsg("Failed to destroy VAAPI buffer.")); return rocdec_status; } @@ -318,7 +318,7 @@ rocDecStatus VaapiVideoDecoder::ReconfigureDecoder(RocdecReconfigureDecoderInfo return ROCDEC_INVALID_PARAMETER; } if (va_display_ == 0) { - ERR("VAAPI decoder has not been initialized but reconfiguration of the decoder has been requested."); + logger_.CriticalLog(MakeMsg("VAAPI decoder has not been initialized but reconfiguration of the decoder has been requested.")); return ROCDEC_NOT_SUPPORTED; } CHECK_VAAPI(vaDestroySurfaces(va_display_, va_surface_ids_.data(), va_surface_ids_.size())); @@ -345,18 +345,18 @@ rocDecStatus VaapiVideoDecoder::ReconfigureDecoder(RocdecReconfigureDecoderInfo if (create_va_config) { rocdec_status = CreateDecoderConfig(); if (rocdec_status != ROCDEC_SUCCESS) { - ERR("Failed to create a VAAPI decoder configuration."); + logger_.CriticalLog(MakeMsg("Failed to create a VAAPI decoder configuration.")); return rocdec_status; } } rocdec_status = CreateSurfaces(); if (rocdec_status != ROCDEC_SUCCESS) { - ERR("Failed to create VAAPI surfaces during the decoder reconfiguration."); + logger_.CriticalLog(MakeMsg("Failed to create VAAPI surfaces during the decoder reconfiguration.")); return rocdec_status; } rocdec_status = CreateContext(); if (rocdec_status != ROCDEC_SUCCESS) { - ERR("Failed to create a VAAPI context during the decoder reconfiguration."); + logger_.CriticalLog(MakeMsg("Failed to create a VAAPI context during the decoder reconfiguration.")); return rocdec_status; } return rocdec_status; @@ -405,7 +405,7 @@ rocDecStatus VaapiVideoDecoder::CreateDecoderConfig() { } break; default: - ERR("The codec type is not supported."); + logger_.CriticalLog(MakeMsg("The codec type is not supported.")); return ROCDEC_NOT_SUPPORTED; } va_config_attrib_.type = VAConfigAttribRTFormat; @@ -426,7 +426,7 @@ rocDecStatus VaapiVideoDecoder::CreateDecoderConfig() { rocDecStatus VaapiVideoDecoder::CreateSurfaces() { if (decoder_create_info_.num_decode_surfaces < 1) { - ERR("Invalid number of decode surfaces."); + logger_.CriticalLog(MakeMsg("Invalid number of decode surfaces.")); return ROCDEC_INVALID_PARAMETER; } va_surface_ids_.resize(decoder_create_info_.num_decode_surfaces); @@ -460,7 +460,7 @@ rocDecStatus VaapiVideoDecoder::CreateSurfaces() { surface_format = VA_RT_FORMAT_YUV444; break; default: - ERR("The surface type is not supported"); + logger_.CriticalLog(MakeMsg("The surface type is not supported")); return ROCDEC_NOT_SUPPORTED; } surf_attribs.push_back(surf_attrib); @@ -519,7 +519,7 @@ VaContext::~VaContext() { } if (va_contexts_[i].va_display) { if (vaTerminate(va_contexts_[i].va_display) != VA_STATUS_SUCCESS) { - ERR("Failed to termiate VA"); + logger_.CriticalLog(MakeMsg("Failed to termiate VA")); } } } @@ -533,7 +533,7 @@ rocDecStatus VaContext::GetVaContext(int device_id, uint32_t *va_ctx_id) { rocDecStatus rocdec_status = ROCDEC_SUCCESS; rocdec_status = InitHIP(device_id, hip_dev_prop); if (rocdec_status != ROCDEC_SUCCESS) { - ERR("Failed to initilize the HIP."); + logger_.CriticalLog(MakeMsg("Failed to initilize the HIP.")); return rocdec_status; } std::string gpu_uuid(hip_dev_prop.uuid.bytes, sizeof(hip_dev_prop.uuid.bytes)); @@ -574,18 +574,18 @@ rocDecStatus VaContext::GetVaContext(int device_id, uint32_t *va_ctx_id) { drm_node += std::to_string(render_node_id + offset); rocdec_status = InitVAAPI(va_ctx_idx, drm_node); if (rocdec_status != ROCDEC_SUCCESS) { - ERR("Failed to initilize the VAAPI."); + logger_.CriticalLog(MakeMsg("Failed to initilize the VAAPI.")); return rocdec_status; } amdgpu_device_handle dev_handle; uint32_t major_version = 0, minor_version = 0; if (amdgpu_device_initialize(va_contexts_[va_ctx_idx].drm_fd, &major_version, &minor_version, &dev_handle)) { - ERR("GPU device initialization failed: " + drm_node); + logger_.CriticalLog(MakeMsg("GPU device initialization failed: " + drm_node)); return ROCDEC_DEVICE_INVALID; } if (amdgpu_query_hw_ip_count(dev_handle, AMDGPU_HW_IP_VCN_DEC, &va_contexts_[va_ctx_idx].num_dec_engines)) { - ERR("Failed to get the number of video decode engines."); + logger_.CriticalLog(MakeMsg("Failed to get the number of video decode engines.")); } amdgpu_device_deinitialize(dev_handle); @@ -601,13 +601,13 @@ rocDecStatus VaContext::GetVaContext(int device_id, uint32_t *va_ctx_id) { rocDecStatus VaContext::GetVaDisplay(uint32_t va_ctx_id, VADisplay *va_display) { if (va_ctx_id >= va_contexts_.size()) { - ERR("Invalid VA context Id."); + logger_.CriticalLog(MakeMsg("Invalid VA context Id.")); *va_display = 0; return ROCDEC_INVALID_PARAMETER; } else { VADisplay new_va_display = vaGetDisplayDRM(va_contexts_[va_ctx_id].drm_fd); if (!new_va_display) { - ERR("Failed to create VA display."); + logger_.CriticalLog(MakeMsg("Failed to create VA display.")); return ROCDEC_NOT_INITIALIZED; } vaSetInfoCallback(new_va_display, NULL, NULL); @@ -620,14 +620,14 @@ rocDecStatus VaContext::GetVaDisplay(uint32_t va_ctx_id, VADisplay *va_display) rocDecStatus VaContext::CheckDecCapForCodecType(RocdecDecodeCaps *dec_cap) { if (dec_cap == nullptr) { - ERR("Null decode capability struct pointer."); + logger_.CriticalLog(MakeMsg("Null decode capability struct pointer.")); return ROCDEC_INVALID_PARAMETER; } rocDecStatus rocdec_status = ROCDEC_SUCCESS; uint32_t va_ctx_id; rocdec_status = GetVaContext(dec_cap->device_id, &va_ctx_id); if (rocdec_status != ROCDEC_SUCCESS) { - ERR("Failed to initilize."); + logger_.CriticalLog(MakeMsg("Failed to initilize.")); return rocdec_status; } @@ -810,11 +810,11 @@ rocDecStatus VaContext::CheckDecCapForCodecType(RocdecDecodeCaps *dec_cap) { rocDecStatus VaContext::InitHIP(int device_id, hipDeviceProp_t& hip_dev_prop) { CHECK_HIP(hipGetDeviceCount(&num_devices_)); if (num_devices_ < 1) { - ERR("Didn't find any GPU."); + logger_.CriticalLog(MakeMsg("Didn't find any GPU.")); return ROCDEC_DEVICE_INVALID; } if (device_id >= num_devices_) { - ERR("ERROR: the requested device_id is not found! "); + logger_.CriticalLog(MakeMsg("ERROR: the requested device_id is not found!")); return ROCDEC_DEVICE_INVALID; } CHECK_HIP(hipSetDevice(device_id)); @@ -825,12 +825,12 @@ rocDecStatus VaContext::InitHIP(int device_id, hipDeviceProp_t& hip_dev_prop) { rocDecStatus VaContext::InitVAAPI(int va_ctx_idx, std::string drm_node) { va_contexts_[va_ctx_idx].drm_fd = open(drm_node.c_str(), O_RDWR); if (va_contexts_[va_ctx_idx].drm_fd < 0) { - ERR("Failed to open drm node." + drm_node); + logger_.CriticalLog(MakeMsg("Failed to open drm node." + drm_node)); return ROCDEC_NOT_INITIALIZED; } va_contexts_[va_ctx_idx].va_display = vaGetDisplayDRM(va_contexts_[va_ctx_idx].drm_fd); if (!va_contexts_[va_ctx_idx].va_display) { - ERR("Failed to create VA display."); + logger_.CriticalLog(MakeMsg("Failed to create VA display.")); return ROCDEC_NOT_INITIALIZED; } vaSetInfoCallback(va_contexts_[va_ctx_idx].va_display, NULL, NULL); diff --git a/src/rocdecode/vaapi/vaapi_videodecoder.h b/src/rocdecode/vaapi/vaapi_videodecoder.h index 9a290a41c..bc0013bf8 100644 --- a/src/rocdecode/vaapi/vaapi_videodecoder.h +++ b/src/rocdecode/vaapi/vaapi_videodecoder.h @@ -45,7 +45,7 @@ THE SOFTWARE. #define CHECK_HIP(call) {\ hipError_t hip_status = call;\ if (hip_status != hipSuccess) {\ - std::cout << "HIP failure: " << #call << " failed with 'status: " << hipGetErrorName(hip_status) << "' at " << __FILE__ << ":" << __LINE__ << std::endl;\ + logger_.CriticalLog(MakeMsg("HIP failure: " + #call + " failed with 'status: " + STR(hipGetErrorName(hip_status)) + "' at " + __FILE__ + ":" + TOSTR(__LINE__)));\ return ROCDEC_RUNTIME_ERROR;\ }\ } @@ -53,7 +53,7 @@ THE SOFTWARE. #define CHECK_VAAPI(call) {\ VAStatus va_status = call;\ if (va_status != VA_STATUS_SUCCESS) {\ - std::cout << "VAAPI failure: " << #call << " failed with status: " << std::hex << "0x" << va_status << std::dec << " = '" << vaErrorStr(va_status) << "' at " << __FILE__ << ":" << __LINE__ << std::endl;\ + logger_.CriticalLog(MakeMsg("VAAPI failure: " + #call + " failed with 'status: " + TOSTR(va_status) + ": " + vaErrorStr(va_status) + "' at " + __FILE__ + ":" + TOSTR(__LINE__)));\ return ROCDEC_RUNTIME_ERROR;\ }\ } @@ -115,6 +115,8 @@ class VaapiVideoDecoder { uint32_t num_slices_; VABufferID slice_data_buf_id_; + RocDecLogger logger_; + bool IsCodecConfigSupported(int device_id, rocDecVideoCodec codec_type, rocDecVideoChromaFormat chroma_format, uint32_t bit_depth_minus8, rocDecVideoSurfaceFormat output_format); rocDecStatus CreateDecoderConfig(); rocDecStatus CreateSurfaces(); @@ -152,6 +154,8 @@ class VaContext { VaContext& operator = (const VaContext) = delete; ~VaContext(); + RocDecLogger logger_; + rocDecStatus InitHIP(int device_id, hipDeviceProp_t& hip_dev_prop); rocDecStatus InitVAAPI(int va_ctx_idx, std::string drm_node); void GetVisibleDevices(std::vector& visible_devices_vetor); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d6a51c6cb..5b0daca45 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -56,6 +56,7 @@ include(CTest) # add ROCm find Config location list(APPEND CMAKE_PREFIX_PATH ${ROCM_PATH}/lib/cmake) +list(APPEND CMAKE_MODULE_PATH ${ROCM_PATH}/share/rocdecode/cmake) # find rocdecode if(BUILD_FROM_SOURCE) @@ -87,202 +88,278 @@ else() message("-- \t${White}rocdecode-host_VERSION_MINOR -- ${rocdecode-host_VERSION_MINOR}${ColourReset}") message("-- \t${White}rocdecode-host_VERSION_PATCH -- ${rocdecode-host_VERSION_PATCH}${ColourReset}") else() - message("-- ${Yellow}${PROJECT_NAME} requires rocdecode-host. Install rocdecode-host before running CTests") + message("-- ${Yellow}${PROJECT_NAME} rocdecode-host is optional. Install rocdecode-host to run additional tests before running CTests") endif(rocdecode-host_FOUND) endif(BUILD_FROM_SOURCE) +find_package(FFmpeg QUIET) -# 1 - videoDecode HEVC +# Check if lib/rocm_sysdeps/lib exists in the ROCm path which indicates ROCm installation via TheRock +set(USING_THE_ROCK OFF) +if(EXISTS "${ROCM_PATH}/lib/rocm_sysdeps/lib") + set(USING_THE_ROCK ON) +endif() + +# 1 - videoDecodeRaw HEVC add_test( NAME - video_decode-HEVC + video_decodeRaw-HEVC COMMAND "${CMAKE_CTEST_COMMAND}" - --build-and-test "${ROCM_PATH}/share/rocdecode/samples/videoDecode" - "${CMAKE_CURRENT_BINARY_DIR}/videoDecode" + --build-and-test "${ROCM_PATH}/share/rocdecode/samples/videoDecodeRaw" + "${CMAKE_CURRENT_BINARY_DIR}/videoDecodeRaw-HEVC" --build-generator "${CMAKE_GENERATOR}" - --test-command "videodecode" - -i ${ROCM_PATH}/share/rocdecode/video/AMD_driving_virtual_20-H265.mp4 + --test-command "videodecoderaw" + -i ${ROCM_PATH}/share/rocdecode/video/AMD_driving_virtual_20-H265.265 ) +if(USING_THE_ROCK) + set_property(TEST video_decodeRaw-HEVC PROPERTY ENVIRONMENT "LIBVA_DRIVERS_PATH=${ROCM_PATH}/lib/rocm_sysdeps/lib") +endif() -# 2 - videoDecode AVC +# 2 - videoDecodeRaw AVC add_test( NAME - video_decode-AVC + video_decodeRaw-AVC COMMAND "${CMAKE_CTEST_COMMAND}" - --build-and-test "${ROCM_PATH}/share/rocdecode/samples/videoDecode" - "${CMAKE_CURRENT_BINARY_DIR}/videoDecode" + --build-and-test "${ROCM_PATH}/share/rocdecode/samples/videoDecodeRaw" + "${CMAKE_CURRENT_BINARY_DIR}/videoDecodeRaw-AVC" --build-generator "${CMAKE_GENERATOR}" - --test-command "videodecode" - -i ${ROCM_PATH}/share/rocdecode/video/AMD_driving_virtual_20-H264.mp4 + --test-command "videodecoderaw" + -i ${ROCM_PATH}/share/rocdecode/video/AMD_driving_virtual_20-H264.264 ) +if(USING_THE_ROCK) + set_property(TEST video_decodeRaw-AVC PROPERTY ENVIRONMENT "LIBVA_DRIVERS_PATH=${ROCM_PATH}/lib/rocm_sysdeps/lib") +endif() -# 3 - videoDecode AV1 +# 3 - videoDecodeRaw AV1 add_test( NAME - video_decode-AV1 + video_decodeRaw-AV1 COMMAND "${CMAKE_CTEST_COMMAND}" - --build-and-test "${ROCM_PATH}/share/rocdecode/samples/videoDecode" - "${CMAKE_CURRENT_BINARY_DIR}/videoDecode" + --build-and-test "${ROCM_PATH}/share/rocdecode/samples/videoDecodeRaw" + "${CMAKE_CURRENT_BINARY_DIR}/videoDecodeRaw-AV1" --build-generator "${CMAKE_GENERATOR}" - --test-command "videodecode" - -i ${ROCM_PATH}/share/rocdecode/video/AMD_driving_virtual_20-AV1.mp4 + --test-command "videodecoderaw" + -i ${ROCM_PATH}/share/rocdecode/video/AMD_driving_virtual_20-AV1.ivf ) +if(USING_THE_ROCK) + set_property(TEST video_decodeRaw-AV1 PROPERTY ENVIRONMENT "LIBVA_DRIVERS_PATH=${ROCM_PATH}/lib/rocm_sysdeps/lib") +endif() -# 4 - videoDecode VP9 +# 4 - videoDecodeRaw VP9 add_test( NAME - video_decode-VP9 + video_decodeRaw-VP9 COMMAND "${CMAKE_CTEST_COMMAND}" - --build-and-test "${ROCM_PATH}/share/rocdecode/samples/videoDecode" - "${CMAKE_CURRENT_BINARY_DIR}/videoDecode" + --build-and-test "${ROCM_PATH}/share/rocdecode/samples/videoDecodeRaw" + "${CMAKE_CURRENT_BINARY_DIR}/videoDecodeRaw-VP9" --build-generator "${CMAKE_GENERATOR}" - --test-command "videodecode" + --test-command "videodecoderaw" -i ${ROCM_PATH}/share/rocdecode/video/AMD_driving_virtual_20-VP9.ivf ) +if(USING_THE_ROCK) + set_property(TEST video_decodeRaw-VP9 PROPERTY ENVIRONMENT "LIBVA_DRIVERS_PATH=${ROCM_PATH}/lib/rocm_sysdeps/lib") +endif() -# 5 - videoDecodePerf +# 5 - rocdecDecode add_test( NAME - video_decodePerf-HEVC + rocdec_Decode-HEVC COMMAND "${CMAKE_CTEST_COMMAND}" - --build-and-test "${ROCM_PATH}/share/rocdecode/samples/videoDecodePerf" - "${CMAKE_CURRENT_BINARY_DIR}/videoDecodePerf" + --build-and-test "${ROCM_PATH}/share/rocdecode/samples/rocdecDecode" + "${CMAKE_CURRENT_BINARY_DIR}/rocdecDecode" --build-generator "${CMAKE_GENERATOR}" - --test-command "videodecodeperf" - -i ${ROCM_PATH}/share/rocdecode/video/AMD_driving_virtual_20-H265.mp4 + --test-command "rocdecdecode" + -i ${ROCM_PATH}/share/rocdecode/frames ) +if(USING_THE_ROCK) + set_property(TEST rocdec_Decode-HEVC PROPERTY ENVIRONMENT "LIBVA_DRIVERS_PATH=${ROCM_PATH}/lib/rocm_sysdeps/lib") +endif() -# 6 - videoDecodeBatch +# 6 - rocDecodeNegativeApiTests add_test( NAME - video_decodeBatch + rocDecode_Negative_API_Tests COMMAND "${CMAKE_CTEST_COMMAND}" - --build-and-test "${ROCM_PATH}/share/rocdecode/samples/videoDecodeBatch" - "${CMAKE_CURRENT_BINARY_DIR}/videoDecodeBatch" + --build-and-test "${ROCM_PATH}/share/rocdecode/test/rocDecodeNegativeApiTests" + "${CMAKE_CURRENT_BINARY_DIR}/rocdecodenegativetest" --build-generator "${CMAKE_GENERATOR}" - --test-command "videodecodebatch" - -i ${ROCM_PATH}/share/rocdecode/video/ -t 2 + --test-command "rocdecodenegativetest" ) +if(USING_THE_ROCK) + set_property(TEST rocDecode_Negative_API_Tests PROPERTY ENVIRONMENT "LIBVA_DRIVERS_PATH=${ROCM_PATH}/lib/rocm_sysdeps/lib") +endif() -# 7 - videoDecodeRGB -add_test( - NAME - video_decodeRGB-HEVC - COMMAND - "${CMAKE_CTEST_COMMAND}" - --build-and-test "${ROCM_PATH}/share/rocdecode/samples/videoDecodeRGB" - "${CMAKE_CURRENT_BINARY_DIR}/videoDecodeRGB" +if(FFMPEG_FOUND) + message("-- ${Green}${PROJECT_NAME} FFmpeg found - rocdecode tests requiring FFmpeg added") + # 7 - videoDecode HEVC + add_test( + NAME + video_decode-HEVC + COMMAND + "${CMAKE_CTEST_COMMAND}" + --build-and-test "${ROCM_PATH}/share/rocdecode/samples/videoDecode" + "${CMAKE_CURRENT_BINARY_DIR}/videoDecode-HEVC" --build-generator "${CMAKE_GENERATOR}" - --test-command "videodecodergb" - -i ${ROCM_PATH}/share/rocdecode/video/AMD_driving_virtual_20-H265.mp4 -of rgb -) + --test-command "videodecode" + -i ${ROCM_PATH}/share/rocdecode/video/AMD_driving_virtual_20-H265.mp4 + ) + if(USING_THE_ROCK) + set_property(TEST video_decode-HEVC PROPERTY ENVIRONMENT "LIBVA_DRIVERS_PATH=${ROCM_PATH}/lib/rocm_sysdeps/lib") + endif() + # 8 - videoDecode AVC + add_test( + NAME + video_decode-AVC + COMMAND + "${CMAKE_CTEST_COMMAND}" + --build-and-test "${ROCM_PATH}/share/rocdecode/samples/videoDecode" + "${CMAKE_CURRENT_BINARY_DIR}/videoDecode-AVC" + --build-generator "${CMAKE_GENERATOR}" + --test-command "videodecode" + -i ${ROCM_PATH}/share/rocdecode/video/AMD_driving_virtual_20-H264.mp4 + ) + if(USING_THE_ROCK) + set_property(TEST video_decode-AVC PROPERTY ENVIRONMENT "LIBVA_DRIVERS_PATH=${ROCM_PATH}/lib/rocm_sysdeps/lib") + endif() -# 8 - videoDecodeMem -add_test( - NAME - video_decodeMem-HEVC - COMMAND - "${CMAKE_CTEST_COMMAND}" - --build-and-test "${ROCM_PATH}/share/rocdecode/samples/videoDecodeMem" - "${CMAKE_CURRENT_BINARY_DIR}/videoDecodeMem" + # 9 - videoDecode AV1 + add_test( + NAME + video_decode-AV1 + COMMAND + "${CMAKE_CTEST_COMMAND}" + --build-and-test "${ROCM_PATH}/share/rocdecode/samples/videoDecode" + "${CMAKE_CURRENT_BINARY_DIR}/videoDecode-AV1" --build-generator "${CMAKE_GENERATOR}" - --test-command "videodecodemem" - -i ${ROCM_PATH}/share/rocdecode/video/AMD_driving_virtual_20-H265.mp4 -) + --test-command "videodecode" + -i ${ROCM_PATH}/share/rocdecode/video/AMD_driving_virtual_20-AV1.mp4 + ) + if(USING_THE_ROCK) + set_property(TEST video_decode-AV1 PROPERTY ENVIRONMENT "LIBVA_DRIVERS_PATH=${ROCM_PATH}/lib/rocm_sysdeps/lib") + endif() -# 9 - videoDecodeRaw HEVC -add_test( - NAME - video_decodeRaw-HEVC - COMMAND - "${CMAKE_CTEST_COMMAND}" - --build-and-test "${ROCM_PATH}/share/rocdecode/samples/videoDecodeRaw" - "${CMAKE_CURRENT_BINARY_DIR}/videoDecodeRaw" + # 10 - videoDecode VP9 + add_test( + NAME + video_decode-VP9 + COMMAND + "${CMAKE_CTEST_COMMAND}" + --build-and-test "${ROCM_PATH}/share/rocdecode/samples/videoDecode" + "${CMAKE_CURRENT_BINARY_DIR}/videoDecode-VP9" --build-generator "${CMAKE_GENERATOR}" - --test-command "videodecoderaw" - -i ${ROCM_PATH}/share/rocdecode/video/AMD_driving_virtual_20-H265.265 -) + --test-command "videodecode" + -i ${ROCM_PATH}/share/rocdecode/video/AMD_driving_virtual_20-VP9.ivf + ) + if(USING_THE_ROCK) + set_property(TEST video_decode-VP9 PROPERTY ENVIRONMENT "LIBVA_DRIVERS_PATH=${ROCM_PATH}/lib/rocm_sysdeps/lib") + endif() -# 10 - videoDecodeRaw AVC -add_test( - NAME - video_decodeRaw-AVC - COMMAND - "${CMAKE_CTEST_COMMAND}" - --build-and-test "${ROCM_PATH}/share/rocdecode/samples/videoDecodeRaw" - "${CMAKE_CURRENT_BINARY_DIR}/videoDecodeRaw" + # 11 - videoDecodePerf + add_test( + NAME + video_decodePerf-HEVC + COMMAND + "${CMAKE_CTEST_COMMAND}" + --build-and-test "${ROCM_PATH}/share/rocdecode/samples/videoDecodePerf" + "${CMAKE_CURRENT_BINARY_DIR}/videoDecodePerf" --build-generator "${CMAKE_GENERATOR}" - --test-command "videodecoderaw" - -i ${ROCM_PATH}/share/rocdecode/video/AMD_driving_virtual_20-H264.264 -) + --test-command "videodecodeperf" + -i ${ROCM_PATH}/share/rocdecode/video/AMD_driving_virtual_20-H265.mp4 + ) + if(USING_THE_ROCK) + set_property(TEST video_decodePerf-HEVC PROPERTY ENVIRONMENT "LIBVA_DRIVERS_PATH=${ROCM_PATH}/lib/rocm_sysdeps/lib") + endif() -# 11 - videoDecodeRaw AV1 -add_test( - NAME - video_decodeRaw-AV1 - COMMAND - "${CMAKE_CTEST_COMMAND}" - --build-and-test "${ROCM_PATH}/share/rocdecode/samples/videoDecodeRaw" - "${CMAKE_CURRENT_BINARY_DIR}/videoDecodeRaw" + # 12 - videoDecodeBatch + add_test( + NAME + video_decodeBatch + COMMAND + "${CMAKE_CTEST_COMMAND}" + --build-and-test "${ROCM_PATH}/share/rocdecode/samples/videoDecodeBatch" + "${CMAKE_CURRENT_BINARY_DIR}/videoDecodeBatch" --build-generator "${CMAKE_GENERATOR}" - --test-command "videodecoderaw" - -i ${ROCM_PATH}/share/rocdecode/video/AMD_driving_virtual_20-AV1.ivf -) + --test-command "videodecodebatch" + -i ${ROCM_PATH}/share/rocdecode/video/ -t 2 + ) + if(USING_THE_ROCK) + set_property(TEST video_decodeBatch PROPERTY ENVIRONMENT "LIBVA_DRIVERS_PATH=${ROCM_PATH}/lib/rocm_sysdeps/lib") + endif() -# 12 - videoDecodeRaw VP9 -add_test( - NAME - video_decodeRaw-VP9 - COMMAND - "${CMAKE_CTEST_COMMAND}" - --build-and-test "${ROCM_PATH}/share/rocdecode/samples/videoDecodeRaw" - "${CMAKE_CURRENT_BINARY_DIR}/videoDecodeRaw" + # 13 - videoDecodeRGB + add_test( + NAME + video_decodeRGB-HEVC + COMMAND + "${CMAKE_CTEST_COMMAND}" + --build-and-test "${ROCM_PATH}/share/rocdecode/samples/videoDecodeRGB" + "${CMAKE_CURRENT_BINARY_DIR}/videoDecodeRGB" --build-generator "${CMAKE_GENERATOR}" - --test-command "videodecoderaw" - -i ${ROCM_PATH}/share/rocdecode/video/AMD_driving_virtual_20-VP9.ivf -) + --test-command "videodecodergb" + -i ${ROCM_PATH}/share/rocdecode/video/AMD_driving_virtual_20-H265.mp4 -of rgb + ) + if(USING_THE_ROCK) + set_property(TEST video_decodeRGB-HEVC PROPERTY ENVIRONMENT "LIBVA_DRIVERS_PATH=${ROCM_PATH}/lib/rocm_sysdeps/lib") + endif() -# 13 - rocDecodeNegativeApiTests -add_test( - NAME - rocDecode_Negative_API_Tests - COMMAND - "${CMAKE_CTEST_COMMAND}" - --build-and-test "${ROCM_PATH}/share/rocdecode/test/rocDecodeNegativeApiTests" - "${CMAKE_CURRENT_BINARY_DIR}/rocdecodenegativetest" + # 14 - videoDecodeMem + add_test( + NAME + video_decodeMem-HEVC + COMMAND + "${CMAKE_CTEST_COMMAND}" + --build-and-test "${ROCM_PATH}/share/rocdecode/samples/videoDecodeMem" + "${CMAKE_CURRENT_BINARY_DIR}/videoDecodeMem" --build-generator "${CMAKE_GENERATOR}" - --test-command "rocdecodenegativetest" -) + --test-command "videodecodemem" + -i ${ROCM_PATH}/share/rocdecode/video/AMD_driving_virtual_20-H265.mp4 + ) + if(USING_THE_ROCK) + set_property(TEST video_decodeMem-HEVC PROPERTY ENVIRONMENT "LIBVA_DRIVERS_PATH=${ROCM_PATH}/lib/rocm_sysdeps/lib") + endif() -# 14 - videoDecodeRGBResize -add_test( - NAME - video_decodeRGB-Resize - COMMAND - "${CMAKE_CTEST_COMMAND}" + # 15 - videoDecodeRGBResize + add_test( + NAME + video_decodeRGB-Resize + COMMAND + "${CMAKE_CTEST_COMMAND}" --build-and-test "${ROCM_PATH}/share/rocdecode/samples/videoDecodeRGB" - "${CMAKE_CURRENT_BINARY_DIR}/videoDecodeRGB" + "${CMAKE_CURRENT_BINARY_DIR}/videoDecodeRGB-Resize" --build-generator "${CMAKE_GENERATOR}" --test-command "videodecodergb" -i "${ROCM_PATH}/share/rocdecode/video/AMD_driving_virtual_20-H265.mp4" -resize 640x360 -of rgb -) + ) + if(USING_THE_ROCK) + set_property(TEST video_decodeRGB-Resize PROPERTY ENVIRONMENT "LIBVA_DRIVERS_PATH=${ROCM_PATH}/lib/rocm_sysdeps/lib") + endif() -# 15 - videoDecode Host backend -add_test( - NAME - video_decode-Host-Backend - COMMAND - "${CMAKE_CTEST_COMMAND}" + if(rocdecode-host_FOUND) + # 16 - videoDecode Host backend + add_test( + NAME + video_decode-Host-Backend + COMMAND + "${CMAKE_CTEST_COMMAND}" --build-and-test "${ROCM_PATH}/share/rocdecode/samples/videoDecode" - "${CMAKE_CURRENT_BINARY_DIR}/videoDecode" + "${CMAKE_CURRENT_BINARY_DIR}/videoDecode-Host" --build-generator "${CMAKE_GENERATOR}" --test-command "videodecode" -i ${ROCM_PATH}/share/rocdecode/video/AMD_driving_virtual_20-H265.mp4 -backend 1 -) + ) + if(USING_THE_ROCK) + set_property(TEST video_decode-Host-Backend PROPERTY ENVIRONMENT "LIBVA_DRIVERS_PATH=${ROCM_PATH}/lib/rocm_sysdeps/lib") + endif() + else() + message("-- ${Yellow}${PROJECT_NAME} rocdecode-host NOT found. rocdecode tests requiring rocdecode-host excluded") + endif(rocdecode-host_FOUND) +else() + message("-- ${Yellow}${PROJECT_NAME} FFmpeg NOT found. rocdecode tests requiring FFmpeg excluded") +endif(FFMPEG_FOUND) diff --git a/test/rocDecodeNegativeApiTests/CMakeLists.txt b/test/rocDecodeNegativeApiTests/CMakeLists.txt index ac634e86f..e4e9af214 100644 --- a/test/rocDecodeNegativeApiTests/CMakeLists.txt +++ b/test/rocDecodeNegativeApiTests/CMakeLists.txt @@ -61,6 +61,7 @@ else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -DNDEBUG -fPIC") endif() +set (HIP_PLATFORM amd CACHE STRING "HIP platform") find_package(HIP QUIET) find_package(rocdecode QUIET) find_package(rocprofiler-register QUIET) diff --git a/utils/md5.h b/utils/md5.h index 0be8a43d4..86e8a712c 100644 --- a/utils/md5.h +++ b/utils/md5.h @@ -87,6 +87,11 @@ class MD5Generator { } else hst_ptr = static_cast (surf_mem); + if (hst_ptr == nullptr) { + ROCDEC_ERR("Null surface pointer."); + return; + } + // Need to covert interleaved planar to stacked planar, assuming 4:2:0 chroma sampling. uint8_t *stacked_ptr = new uint8_t [output_image_size]; uint8_t *tmp_hst_ptr = hst_ptr; diff --git a/utils/rocvideodecode/roc_video_dec.cpp b/utils/rocvideodecode/roc_video_dec.cpp index 0c4ffc39e..5529231ab 100644 --- a/utils/rocvideodecode/roc_video_dec.cpp +++ b/utils/rocvideodecode/roc_video_dec.cpp @@ -388,7 +388,10 @@ int RocVideoDecoder::HandleVideoSequence(RocdecVideoFormat *p_video_format) { output_surface_info_.output_height = target_height_; output_surface_info_.output_pitch = surface_stride_; output_surface_info_.output_vstride = (out_mem_type_ == OUT_SURFACE_MEM_DEV_INTERNAL) ? surface_vstride_ : videoDecodeCreateInfo.target_height; - output_surface_info_.disp_rect = disp_rect_; + output_surface_info_.disp_rect.top = videoDecodeCreateInfo.display_rect.top; + output_surface_info_.disp_rect.bottom = videoDecodeCreateInfo.display_rect.bottom; + output_surface_info_.disp_rect.left = videoDecodeCreateInfo.display_rect.left; + output_surface_info_.disp_rect.right = videoDecodeCreateInfo.display_rect.right; output_surface_info_.chroma_height = chroma_height_; output_surface_info_.bit_depth = bitdepth_minus_8_ + 8; output_surface_info_.bytes_per_pixel = byte_per_pixel_; @@ -567,7 +570,11 @@ int RocVideoDecoder::ReconfigureDecoder(RocdecVideoFormat *p_video_format) { output_surface_info_.output_height = target_height_; output_surface_info_.output_pitch = surface_stride_; output_surface_info_.output_vstride = (out_mem_type_ == OUT_SURFACE_MEM_DEV_INTERNAL) ? surface_vstride_ : target_height_; - output_surface_info_.disp_rect = disp_rect_; + if (!(crop_rect_.right && crop_rect_.bottom)) { + output_surface_info_.disp_rect = disp_rect_; + } else { + output_surface_info_.disp_rect = crop_rect_; + } output_surface_info_.chroma_height = chroma_height_; output_surface_info_.bit_depth = bitdepth_minus_8_ + 8; output_surface_info_.bytes_per_pixel = byte_per_pixel_; @@ -956,7 +963,11 @@ void RocVideoDecoder::SaveFrameToFile(std::string output_file_name, void *surf_m } else hst_ptr = static_cast (surf_mem); - + if (hst_ptr == nullptr) { + ROCDEC_ERR("Null surface pointer."); + return; + } + if (current_output_filename.empty()) { current_output_filename = output_file_name; }