diff --git a/projects/rocdecode/CMakeLists.txt b/projects/rocdecode/CMakeLists.txt index 750cd5c52e..1819e8b093 100644 --- a/projects/rocdecode/CMakeLists.txt +++ b/projects/rocdecode/CMakeLists.txt @@ -100,9 +100,18 @@ else() endif() message("-- ${BoldBlue}rocDecode Build Type -- ${CMAKE_BUILD_TYPE}${ColourReset}") +# Add an option for enabling the rocprofiler-register +option(ROCDECODE_ENABLE_ROCPROFILER_REGISTER "Enable rocprofiler-register support" OFF) + find_package(HIP QUIET) find_package(Libva QUIET) +if(ROCDECODE_ENABLE_ROCPROFILER_REGISTER) + find_package(rocprofiler-register QUIET + HINTS $ENV{rocprofiler_register_ROOT} $ENV{ROCPROFILER_REGISTER_ROOT} ${CMAKE_INSTALL_PREFIX} + PATHS ${ROCM_PATH}) +endif() + if(HIP_FOUND AND Libva_FOUND) # HIP @@ -117,6 +126,11 @@ if(HIP_FOUND AND Libva_FOUND) set(LINK_LIBRARY_LIST ${LINK_LIBRARY_LIST} stdc++fs) endif() + # rocprofiler + if (rocprofiler-register_FOUND) + set(LINK_LIBRARY_LIST ${LINK_LIBRARY_LIST} rocprofiler-register::rocprofiler-register) + endif() + # local include files include_directories(api src/rocdecode src/parser src/rocdecode/vaapi) # source files @@ -131,6 +145,18 @@ if(HIP_FOUND AND Libva_FOUND) set_target_properties(${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE CXX) set_target_properties(${PROJECT_NAME} PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR}) + # rocprofiler + if (rocprofiler-register_FOUND) + string(REPLACE "." ";" VERSION_LIST ${VERSION}) + list(GET VERSION_LIST 0 VERSION_MAJOR) + list(GET VERSION_LIST 1 VERSION_MINOR) + list(GET VERSION_LIST 2 VERSION_PATCH) + target_compile_definitions(${PROJECT_NAME} PRIVATE ROCDECODE_ROCPROFILER_REGISTER=1 + ROCDECODE_ROCP_REG_VERSION_MAJOR=${VERSION_MAJOR} + ROCDECODE_ROCP_REG_VERSION_MINOR=${VERSION_MINOR} + ROCDECODE_ROCP_REG_VERSION_PATCH=${VERSION_PATCH}) + endif() + # install rocDecode libs -- {ROCM_PATH}/lib install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT runtime NAMELINK_SKIP) install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT dev NAMELINK_ONLY) @@ -138,6 +164,10 @@ if(HIP_FOUND AND Libva_FOUND) # install rocDecode include files -- {ROCM_PATH}/include/rocdecode install(FILES api/rocdecode.h api/rocparser.h api/rocdecode_version.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} COMPONENT dev) + # install rocDecode api trace include file -- {ROCM_PATH}/include/rocdecode/amd_detail + install(FILES api/amd_detail/rocdecode_api_trace.h + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/amd_detail COMPONENT dev) + # 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) @@ -205,6 +235,12 @@ if(HIP_FOUND AND Libva_FOUND) set(ROCDECODE_DEBIAN_RUNTIME_PACKAGE_LIST "rocm-hip-runtime, libva2-amdgpu, libva-amdgpu-drm2, libva-amdgpu-wayland2, libva-amdgpu-x11-2, mesa-amdgpu-va-drivers") # Unfortunately RPM has a mix of versions; RHEL has "libva", SLE has "libva2" set(ROCDECODE_RPM_RUNTIME_PACKAGE_LIST "rocm-hip-runtime, (libva >= 2.16.0 or libva2 >= 2.16.0 or libva-amdgpu), mesa-amdgpu-va-drivers") + # Add rocprofiler-register dependencies + if(ROCDECODE_ENABLE_ROCPROFILER_REGISTER) + set(ROCDECODE_DEBIAN_RUNTIME_PACKAGE_LIST "${ROCDECODE_DEBIAN_RUNTIME_PACKAGE_LIST}, rocprofiler-register") + set(ROCDECODE_RPM_RUNTIME_PACKAGE_LIST "${ROCDECODE_RPM_RUNTIME_PACKAGE_LIST}, rocprofiler-register") + endif() + # Set the dev dependent packages set(ROCDECODE_DEBIAN_DEV_PACKAGE_LIST "rocm-hip-runtime-dev, libva-amdgpu-dev, pkg-config, ffmpeg, libavcodec-dev, libavformat-dev, libavutil-dev") if(UBUNTU_22_FOUND) diff --git a/projects/rocdecode/api/amd_detail/rocdecode_api_trace.h b/projects/rocdecode/api/amd_detail/rocdecode_api_trace.h new file mode 100644 index 0000000000..fbb18b8662 --- /dev/null +++ b/projects/rocdecode/api/amd_detail/rocdecode_api_trace.h @@ -0,0 +1,93 @@ +/* +Copyright (c) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +#pragma once + +#include "rocdecode.h" +#include "rocparser.h" + +// Define version macros for the rocDecode API dispatch table, specifying the MAJOR and STEP versions. +// +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! IMPORTANT !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// +// 1. When adding new functions to the rocDecode API dispatch table, always append the new function pointer +// to the end of the table and increment the dispatch table's version number. Never rearrange the order of +// the member variables in the dispatch table, as doing so will break the Application Binary Interface (ABI). +// 2. In critical situations where the type of an existing member variable in a dispatch table has been changed +// or removed due to a data type modification, it is important to increment the major version number of the +// rocDecode API dispatch table. If the function pointer type can no longer be declared, do not remove it. +// Instead, change the function pointer type to `void*` and ensure it is always initialized to `nullptr`. +// +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// + +// The major version number should ideally remain unchanged. Increment the ROCDECODE_RUNTIME_API_TABLE_MAJOR_VERSION only +// for fundamental changes to the rocDecodeDispatchTable struct, such as altering the type or name of an existing member variable. +// Please DO NOT REMOVE it. +#define ROCDECODE_RUNTIME_API_TABLE_MAJOR_VERSION 0 + +// Increment the ROCDECODE_RUNTIME_API_TABLE_STEP_VERSION when new runtime API functions are added. +// If the corresponding ROCDECODE_RUNTIME_API_TABLE_MAJOR_VERSION increases reset the ROCDECODE_RUNTIME_API_TABLE_STEP_VERSION to zero. +#define ROCDECODE_RUNTIME_API_TABLE_STEP_VERSION 0 + +// rocDecode API interface +typedef rocDecStatus (ROCDECAPI *PfnRocDecCreateVideoParser)(RocdecVideoParser *parser_handle, RocdecParserParams *params); +typedef rocDecStatus (ROCDECAPI *PfnRocDecParseVideoData)(RocdecVideoParser parser_handle, RocdecSourceDataPacket *packet); +typedef rocDecStatus (ROCDECAPI *PfnRocDecDestroyVideoParser)(RocdecVideoParser parser_handle); +typedef rocDecStatus (ROCDECAPI *PfnRocDecCreateDecoder)(rocDecDecoderHandle *decoder_handle, RocDecoderCreateInfo *decoder_create_info); +typedef rocDecStatus (ROCDECAPI *PfnRocDecDestroyDecoder)(rocDecDecoderHandle decoder_handle); +typedef rocDecStatus (ROCDECAPI *PfnRocDecGetDecoderCaps)(RocdecDecodeCaps *decode_caps); +typedef rocDecStatus (ROCDECAPI *PfnRocDecDecodeFrame)(rocDecDecoderHandle decoder_handle, RocdecPicParams *pic_params); +typedef rocDecStatus (ROCDECAPI *PfnRocDecGetDecodeStatus)(rocDecDecoderHandle decoder_handle, int pic_idx, RocdecDecodeStatus *decode_status); +typedef rocDecStatus (ROCDECAPI *PfnRocDecReconfigureDecoder)(rocDecDecoderHandle decoder_handle, RocdecReconfigureDecoderInfo *reconfig_params); +typedef rocDecStatus (ROCDECAPI *PfnRocDecGetVideoFrame)(rocDecDecoderHandle decoder_handle, int pic_idx, void *dev_mem_ptr[3], uint32_t (&horizontal_pitch)[3], RocdecProcParams *vid_postproc_params); +typedef const char* (ROCDECAPI *PfnRocDecGetErrorName)(rocDecStatus rocdec_status); + +// rocDecode API dispatch table +struct RocDecodeDispatchTable { + // ROCDECODE_RUNTIME_API_TABLE_STEP_VERSION == 0 + size_t size; + PfnRocDecCreateVideoParser pfn_rocdec_create_video_parser; + PfnRocDecParseVideoData pfn_rocdec_parse_video_data; + PfnRocDecDestroyVideoParser pfn_rocdec_destroy_video_parser; + PfnRocDecCreateDecoder pfn_rocdec_create_decoder; + PfnRocDecDestroyDecoder pfn_rocdec_destroy_decoder; + PfnRocDecGetDecoderCaps pfn_rocdec_get_gecoder_caps; + PfnRocDecDecodeFrame pfn_rocdec_decode_frame; + PfnRocDecGetDecodeStatus pfn_rocdec_get_decode_status; + PfnRocDecReconfigureDecoder pfn_rocdec_reconfigure_decoder; + PfnRocDecGetVideoFrame pfn_rocdec_get_video_frame; + PfnRocDecGetErrorName pfn_rocdec_get_error_name; + // PLEASE DO NOT EDIT ABOVE! + // ROCDECODE_RUNTIME_API_TABLE_STEP_VERSION == 1 + + // ******************************************************************************************* // + // READ BELOW + // ******************************************************************************************* // + // Please keep this text at the end of the structure: + + // 1. Do not reorder any existing members. + // 2. Increase the step version definition before adding new members. + // 3. Insert new members under the appropriate step version comment. + // 4. Generate a comment for the next step version. + // 5. Add a "PLEASE DO NOT EDIT ABOVE!" comment. + // ******************************************************************************************* // +}; \ No newline at end of file diff --git a/projects/rocdecode/src/amd_detail/rocdecode_api_dispatch_interface.cpp b/projects/rocdecode/src/amd_detail/rocdecode_api_dispatch_interface.cpp new file mode 100644 index 0000000000..0ad24888a8 --- /dev/null +++ b/projects/rocdecode/src/amd_detail/rocdecode_api_dispatch_interface.cpp @@ -0,0 +1,60 @@ +/* +Copyright (c) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +#include "../../api/amd_detail/rocdecode_api_trace.h" + +namespace rocdecode { +const RocDecodeDispatchTable* GetRocDecodeDispatchTable(); +} //namespace rocdecode + +rocDecStatus ROCDECAPI rocDecCreateVideoParser(RocdecVideoParser *parser_handle, RocdecParserParams *params) { + return rocdecode::GetRocDecodeDispatchTable()->pfn_rocdec_create_video_parser(parser_handle, params); +} +rocDecStatus ROCDECAPI rocDecParseVideoData(RocdecVideoParser parser_handle, RocdecSourceDataPacket *packet) { + return rocdecode::GetRocDecodeDispatchTable()->pfn_rocdec_parse_video_data(parser_handle, packet); +} +rocDecStatus ROCDECAPI rocDecDestroyVideoParser(RocdecVideoParser parser_handle) { + return rocdecode::GetRocDecodeDispatchTable()->pfn_rocdec_destroy_video_parser(parser_handle); +} +rocDecStatus ROCDECAPI rocDecCreateDecoder(rocDecDecoderHandle *decoder_handle, RocDecoderCreateInfo *decoder_create_info) { + return rocdecode::GetRocDecodeDispatchTable()->pfn_rocdec_create_decoder(decoder_handle, decoder_create_info); +} +rocDecStatus ROCDECAPI rocDecDestroyDecoder(rocDecDecoderHandle decoder_handle) { + return rocdecode::GetRocDecodeDispatchTable()->pfn_rocdec_destroy_decoder(decoder_handle); +} +rocDecStatus ROCDECAPI rocDecGetDecoderCaps(RocdecDecodeCaps *decode_caps) { + return rocdecode::GetRocDecodeDispatchTable()->pfn_rocdec_get_gecoder_caps(decode_caps); +} +rocDecStatus ROCDECAPI rocDecDecodeFrame(rocDecDecoderHandle decoder_handle, RocdecPicParams *pic_params) { + return rocdecode::GetRocDecodeDispatchTable()->pfn_rocdec_decode_frame(decoder_handle, pic_params); +} +rocDecStatus ROCDECAPI rocDecGetDecodeStatus(rocDecDecoderHandle decoder_handle, int pic_idx, RocdecDecodeStatus *decode_status) { + return rocdecode::GetRocDecodeDispatchTable()->pfn_rocdec_get_decode_status(decoder_handle, pic_idx, decode_status); +} +rocDecStatus ROCDECAPI rocDecReconfigureDecoder(rocDecDecoderHandle decoder_handle, RocdecReconfigureDecoderInfo *reconfig_params) { + return rocdecode::GetRocDecodeDispatchTable()->pfn_rocdec_reconfigure_decoder(decoder_handle, reconfig_params); +} +rocDecStatus ROCDECAPI rocDecGetVideoFrame(rocDecDecoderHandle decoder_handle, int pic_idx, void *dev_mem_ptr[3], uint32_t (&horizontal_pitch)[3], RocdecProcParams *vid_postproc_params) { + return rocdecode::GetRocDecodeDispatchTable()->pfn_rocdec_get_video_frame(decoder_handle, pic_idx, dev_mem_ptr, horizontal_pitch, vid_postproc_params); +} +const char *ROCDECAPI rocDecGetErrorName(rocDecStatus rocdec_status) { + return rocdecode::GetRocDecodeDispatchTable()->pfn_rocdec_get_error_name(rocdec_status); +} \ No newline at end of file diff --git a/projects/rocdecode/src/amd_detail/rocdecode_api_trace.cpp b/projects/rocdecode/src/amd_detail/rocdecode_api_trace.cpp new file mode 100644 index 0000000000..12aa68bcb2 --- /dev/null +++ b/projects/rocdecode/src/amd_detail/rocdecode_api_trace.cpp @@ -0,0 +1,168 @@ +/* +Copyright (c) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +#include "../../api/amd_detail/rocdecode_api_trace.h" + +#if defined(ROCDECODE_ROCPROFILER_REGISTER) && ROCDECODE_ROCPROFILER_REGISTER > 0 +#include + +#define ROCDECODE_ROCP_REG_VERSION \ + ROCPROFILER_REGISTER_COMPUTE_VERSION_3(ROCDECODE_ROCP_REG_VERSION_MAJOR, ROCDECODE_ROCP_REG_VERSION_MINOR, \ + ROCDECODE_ROCP_REG_VERSION_PATCH) + +ROCPROFILER_REGISTER_DEFINE_IMPORT(rocdecode, ROCDECODE_ROCP_REG_VERSION) +#elif !defined(ROCDECODE_ROCPROFILER_REGISTER) +#define ROCDECODE_ROCPROFILER_REGISTER 0 +#endif + +namespace rocdecode { +rocDecStatus ROCDECAPI rocDecCreateVideoParser(RocdecVideoParser *parser_handle, RocdecParserParams *params); +rocDecStatus ROCDECAPI rocDecParseVideoData(RocdecVideoParser parser_handle, RocdecSourceDataPacket *packet); +rocDecStatus ROCDECAPI rocDecDestroyVideoParser(RocdecVideoParser parser_handle); +rocDecStatus ROCDECAPI rocDecCreateDecoder(rocDecDecoderHandle *decoder_handle, RocDecoderCreateInfo *decoder_create_info); +rocDecStatus ROCDECAPI rocDecDestroyDecoder(rocDecDecoderHandle decoder_handle); +rocDecStatus ROCDECAPI rocDecGetDecoderCaps(RocdecDecodeCaps *decode_caps); +rocDecStatus ROCDECAPI rocDecDecodeFrame(rocDecDecoderHandle decoder_handle, RocdecPicParams *pic_params); +rocDecStatus ROCDECAPI rocDecGetDecodeStatus(rocDecDecoderHandle decoder_handle, int pic_idx, RocdecDecodeStatus *decode_status); +rocDecStatus ROCDECAPI rocDecReconfigureDecoder(rocDecDecoderHandle decoder_handle, RocdecReconfigureDecoderInfo *reconfig_params); +rocDecStatus ROCDECAPI rocDecGetVideoFrame(rocDecDecoderHandle decoder_handle, int pic_idx, void *dev_mem_ptr[3], uint32_t (&horizontal_pitch)[3], RocdecProcParams *vid_postproc_params); +const char *ROCDECAPI rocDecGetErrorName(rocDecStatus rocdec_status); +} + +namespace rocdecode { +namespace { +void UpdateDispatchTable(RocDecodeDispatchTable* ptr_dispatch_table) { + ptr_dispatch_table->size = sizeof(RocDecodeDispatchTable); + ptr_dispatch_table->pfn_rocdec_create_video_parser = rocdecode::rocDecCreateVideoParser; + ptr_dispatch_table->pfn_rocdec_parse_video_data = rocdecode::rocDecParseVideoData; + ptr_dispatch_table->pfn_rocdec_destroy_video_parser = rocdecode::rocDecDestroyVideoParser; + ptr_dispatch_table->pfn_rocdec_create_decoder = rocdecode::rocDecCreateDecoder; + ptr_dispatch_table->pfn_rocdec_destroy_decoder = rocdecode::rocDecDestroyDecoder; + ptr_dispatch_table->pfn_rocdec_get_gecoder_caps = rocdecode::rocDecGetDecoderCaps; + ptr_dispatch_table->pfn_rocdec_decode_frame = rocdecode::rocDecDecodeFrame; + ptr_dispatch_table->pfn_rocdec_get_decode_status = rocdecode::rocDecGetDecodeStatus; + ptr_dispatch_table->pfn_rocdec_reconfigure_decoder = rocdecode::rocDecReconfigureDecoder; + ptr_dispatch_table->pfn_rocdec_get_video_frame = rocdecode::rocDecGetVideoFrame; + ptr_dispatch_table->pfn_rocdec_get_error_name = rocdecode::rocDecGetErrorName; +} + +#if ROCDECODE_ROCPROFILER_REGISTER > 0 +template struct dispatch_table_info; + +#define ROCDECODE_DEFINE_DISPATCH_TABLE_INFO(TYPE, NAME) \ +template <> struct dispatch_table_info { \ + static constexpr auto name = #NAME; \ + static constexpr auto version = ROCDECODE_ROCP_REG_VERSION; \ + static constexpr auto import_func = &ROCPROFILER_REGISTER_IMPORT_FUNC(NAME); \ +}; + +constexpr auto ComputeTableSize(size_t num_funcs) { + return (num_funcs * sizeof(void*)) + sizeof(uint64_t); +} + +ROCDECODE_DEFINE_DISPATCH_TABLE_INFO(RocDecodeDispatchTable, rocdecode) +#endif + +template void ToolInit(Tp* table) { +#if ROCDECODE_ROCPROFILER_REGISTER > 0 + auto table_array = std::array{static_cast(table)}; + auto lib_id = rocprofiler_register_library_indentifier_t{}; + auto rocp_reg_status = rocprofiler_register_library_api_table( + dispatch_table_info::name, dispatch_table_info::import_func, + dispatch_table_info::version, table_array.data(), table_array.size(), &lib_id); + + bool report_register_errors = false; + if (report_register_errors && rocp_reg_status != ROCP_REG_SUCCESS) + fprintf(stderr, "rocprofiler-register failed for %s with error code %i: %s\n", + dispatch_table_info::name, rocp_reg_status, rocprofiler_register_error_string(rocp_reg_status)); +#else + (void)table; +#endif +} + +template Tp& GetDispatchTableImpl() { + static auto dispatch_table = Tp{}; + // Update all function pointers to reference the runtime implementation functions of rocDecode. + UpdateDispatchTable(&dispatch_table); + // The profiler registration process may encapsulate the function pointers. + ToolInit(&dispatch_table); + return dispatch_table; +} +} //namespace + +const RocDecodeDispatchTable* GetRocDecodeDispatchTable() { + static auto* rocdecode_dispatch_table = &GetDispatchTableImpl(); + return rocdecode_dispatch_table; +} +} //namespace rocdecode + +#if !defined(_WIN32) +constexpr auto ComputeTableOffset(size_t num_funcs) { + return (num_funcs * sizeof(void*)) + sizeof(size_t); +} + +// The `ROCDECODE_ENFORCE_ABI_VERSIONING` macro will trigger a compiler error if the size of the rocDecode dispatch API table changes, +// which is most likely due to the addition of a new dispatch table entry. This serves as a reminder for developers to update the table +// versioning value before changing the value in `ROCDECODE_ENFORCE_ABI_VERSIONING`, ensuring that this static assertion passes. +// +// The `ROCDECODE_ENFORCE_ABI` macro will also trigger a compiler error if the order of the members in the rocDecode dispatch API table +// is altered. Therefore, it is essential to avoid reordering member variables. +// +// Please be aware that `rocprofiler` performs strict compile-time checks to ensure that these versioning values are correctly updated. +// Commenting out this check or merely updating the size field in `ROCDECODE_ENFORCE_ABI_VERSIONING` will cause the `rocprofiler` to fail +// during the build process. +#define ROCDECODE_ENFORCE_ABI_VERSIONING(TABLE, NUM) \ + static_assert( \ + sizeof(TABLE) == ComputeTableOffset(NUM), \ + "The size of the API table structure has been updated. Please modify the " \ + "STEP_VERSION number (or, in rare cases, the MAJOR_VERSION number) " \ + "in for the failing API " \ + "structure before changing the SIZE field passed to ROCDECODE_DEFINE_DISPATCH_TABLE_INFO."); + +#define ROCDECODE_ENFORCE_ABI(TABLE, ENTRY, NUM) \ + static_assert(offsetof(TABLE, ENTRY) == ComputeTableOffset(NUM), \ + "ABI broke for " #TABLE "." #ENTRY \ + ", only add new function pointers at the end of the struct and do not rearrange them."); + +// These ensure that function pointers are not re-ordered +// ROCDECODE_RUNTIME_API_TABLE_STEP_VERSION == 0 +ROCDECODE_ENFORCE_ABI(RocDecodeDispatchTable, pfn_rocdec_create_video_parser, 0) +ROCDECODE_ENFORCE_ABI(RocDecodeDispatchTable, pfn_rocdec_parse_video_data, 1) +ROCDECODE_ENFORCE_ABI(RocDecodeDispatchTable, pfn_rocdec_destroy_video_parser, 2) +ROCDECODE_ENFORCE_ABI(RocDecodeDispatchTable, pfn_rocdec_create_decoder, 3) +ROCDECODE_ENFORCE_ABI(RocDecodeDispatchTable, pfn_rocdec_destroy_decoder, 4) +ROCDECODE_ENFORCE_ABI(RocDecodeDispatchTable, pfn_rocdec_get_gecoder_caps, 5) +ROCDECODE_ENFORCE_ABI(RocDecodeDispatchTable, pfn_rocdec_decode_frame, 6) +ROCDECODE_ENFORCE_ABI(RocDecodeDispatchTable, pfn_rocdec_get_decode_status, 7) +ROCDECODE_ENFORCE_ABI(RocDecodeDispatchTable, pfn_rocdec_reconfigure_decoder, 8) +ROCDECODE_ENFORCE_ABI(RocDecodeDispatchTable, pfn_rocdec_get_video_frame, 9) +ROCDECODE_ENFORCE_ABI(RocDecodeDispatchTable, pfn_rocdec_get_error_name, 10) + +// If ROCDECODE_ENFORCE_ABI entries are added for each new function pointer in the table, +// the number below will be one greater than the number in the last ROCDECODE_ENFORCE_ABI line. For example: +// ROCDECODE_ENFORCE_ABI(, , 10) +// ROCDECODE_ENFORCE_ABI_VERSIONING(
, 11) <- 10 + 1 = 11 +ROCDECODE_ENFORCE_ABI_VERSIONING(RocDecodeDispatchTable, 11) + +static_assert(ROCDECODE_RUNTIME_API_TABLE_MAJOR_VERSION == 0 && ROCDECODE_RUNTIME_API_TABLE_STEP_VERSION == 0, + "If you encounter this error, add the new ROCDECODE_ENFORCE_ABI(...) code for the updated function pointers, " + "and then modify this check to ensure it evaluates to true."); +#endif \ No newline at end of file diff --git a/projects/rocdecode/src/parser/rocparser_api.cpp b/projects/rocdecode/src/parser/rocparser_api.cpp index c0bd9c9dec..316db5302a 100644 --- a/projects/rocdecode/src/parser/rocparser_api.cpp +++ b/projects/rocdecode/src/parser/rocparser_api.cpp @@ -22,7 +22,7 @@ THE SOFTWARE. #include "parser_handle.h" #include "../commons.h" - +namespace rocdecode { /************************************************************************************************/ //! \ingroup FUNCTS //! \fn rocParserStatus ROCDECAPI rocDecCreateVideoParser(RocdecVideoParser *parser_handle, RocdecParserParams *parser_params) @@ -130,3 +130,4 @@ rocDecDestroyVideoParser(RocdecVideoParser parser_handle) { delete roc_parser_handle; return ret; } +} //namespace rocdecode \ No newline at end of file diff --git a/projects/rocdecode/src/rocdecode/rocdecode_api.cpp b/projects/rocdecode/src/rocdecode/rocdecode_api.cpp index 5a18b4e469..ac68241e92 100644 --- a/projects/rocdecode/src/rocdecode/rocdecode_api.cpp +++ b/projects/rocdecode/src/rocdecode/rocdecode_api.cpp @@ -24,7 +24,7 @@ THE SOFTWARE. #include "roc_decoder_caps.h" #include "../commons.h" - +namespace rocdecode { /*****************************************************************************************************/ //! \fn rocDecStatus ROCDECAPI rocDecCreateDecoder(rocDecDecoderHandle *decoder_handle, RocDecoderCreateInfo *decoder_create_info) //! Create the decoder object based on decoder_create_info. A handle to the created decoder is returned @@ -219,4 +219,5 @@ const char* ROCDECAPI rocDecGetErrorName(rocDecStatus rocdec_status) { default: return "UNKNOWN_ERROR"; } -} \ No newline at end of file +} +} //namespace rocdecode \ No newline at end of file