From bf830a2678076dc1ac80eef594df313135e04b39 Mon Sep 17 00:00:00 2001 From: Aryan Salmanpour Date: Tue, 24 Oct 2023 08:40:58 -0400 Subject: [PATCH] Add support for the rocDecGetDecoderCaps API (#21) * Add support for the rocDecGetDecoderCaps API * move the RocDecVcnCodecSpec class to a new header file --- api/rocdecode.h | 2 + src/rocdecode/roc_decoder.h | 4 +- src/rocdecode/roc_decoder_caps.h | 108 +++++++++++++++++++++++++++++++ src/rocdecode/rocdecode_api.cpp | 30 ++++++++- 4 files changed, 140 insertions(+), 4 deletions(-) create mode 100644 src/rocdecode/roc_decoder_caps.h diff --git a/api/rocdecode.h b/api/rocdecode.h index 784d6eaf9a..b562bcf8e2 100644 --- a/api/rocdecode.h +++ b/api/rocdecode.h @@ -145,6 +145,8 @@ typedef enum rocDecodeStatus_enum { //! This structure is used in rocDecGetDecoderCaps API /**************************************************************************************************************/ typedef struct _RocdecDecodeCaps { + uint8_t deviceid; /**< IN: the device id for which query the decode capability + 0 for the first device, 1 for the second device on the system, etc.*/ rocDecVideoCodec eCodecType; /**< IN: rocDecVideoCodec_XXX */ rocDecVideoChromaFormat eChromaFormat; /**< IN: rocDecVideoChromaFormat_XXX */ uint32_t nBitDepthMinus8; /**< IN: The Value "BitDepth minus 8" */ diff --git a/src/rocdecode/roc_decoder.h b/src/rocdecode/roc_decoder.h index 91a2289b93..e2dae0ea53 100644 --- a/src/rocdecode/roc_decoder.h +++ b/src/rocdecode/roc_decoder.h @@ -33,7 +33,6 @@ THE SOFTWARE. #include "../api/rocdecode.h" #include - class RocDecoder { public: RocDecoder(int device_id = 0); @@ -47,10 +46,9 @@ public: private: rocDecStatus initHIP(int device_id); void initDRMnodes(); - int num_devices_; int device_id_; hipDeviceProp_t hip_dev_prop_; hipStream_t hip_stream_; std::vector drm_nodes_; -}; +}; \ No newline at end of file diff --git a/src/rocdecode/roc_decoder_caps.h b/src/rocdecode/roc_decoder_caps.h new file mode 100644 index 0000000000..7ba86280fb --- /dev/null +++ b/src/rocdecode/roc_decoder_caps.h @@ -0,0 +1,108 @@ +/* +Copyright (c) 2023 - 2023 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 +#include +#include +#include +#include "../commons.h" +#include "../../api/rocdecode.h" + + +// The CodecSpec struct contains information for an individual codec (e.g., rocDecVideoCodec_HEVC) +struct CodecSpec { + std::vector chroma_format; + std::vector bitdepth_minus8; + uint16_t output_format_mask; + uint32_t max_width; + uint32_t max_height; + uint16_t min_width; + uint16_t min_height; +}; + +// The VcnCodecsSpec struct contains information for all supported codecs and number of vcn instances per device +struct VcnCodecsSpec { + std::unordered_map codecs_spec; + uint8_t num_decoders; +}; + +// The RocDecVcnCodecSpec singleton class for providing access to the the vcn_spec_table +class RocDecVcnCodecSpec { +public: + static RocDecVcnCodecSpec& GetInastance() { + static RocDecVcnCodecSpec instance; + return instance; + } + rocDecStatus GetDecoderCaps(std::string gcn_arch_name, RocdecDecodeCaps *pdc) { + std::lock_guard lock(mutex); + auto it = vcn_spec_table.find(gcn_arch_name); + if (it != vcn_spec_table.end()) { + const VcnCodecsSpec& vcn_spec = it->second; + auto it1 = vcn_spec.codecs_spec.find(pdc->eCodecType); + if (it1 != vcn_spec.codecs_spec.end()) { + const CodecSpec& codec_spec = it1->second; + auto it_chroma_format = std::find(codec_spec.chroma_format.begin(), codec_spec.chroma_format.end(), pdc->eChromaFormat); + auto it_bitdepth_minus8 = std::find(codec_spec.bitdepth_minus8.begin(), codec_spec.bitdepth_minus8.end(), pdc->nBitDepthMinus8); + if (it_chroma_format != codec_spec.chroma_format.end() && it_bitdepth_minus8 != codec_spec.bitdepth_minus8.end()) { + pdc->bIsSupported = 1; + pdc->nNumDecoders = vcn_spec.num_decoders; + pdc->nOutputFormatMask = codec_spec.output_format_mask; + pdc->nMaxWidth = codec_spec.max_width; + pdc->nMaxHeight = codec_spec.max_height; + pdc->nMinWidth = codec_spec.min_width; + pdc->nMinHeight = codec_spec.min_height; + return ROCDEC_SUCCESS; + } else { + return ROCDEC_NOT_SUPPORTED; + } + } else { + return ROCDEC_NOT_SUPPORTED; + } + } else { + return ROCDEC_DEVICE_INVALID; + } + } +private: + std::unordered_map vcn_spec_table; + std::mutex mutex; + RocDecVcnCodecSpec() { + //vcn lookup table format: + //{"gcn_arch_name1",{{{codec1, {{chroma_format1_for_codec1, chroma_format2_for_codec1, ...}, {bit_depth1_minus8_for_codec1, bit_depth2_minus8_for_codec1, ...}, output_format_mask_for_codec1, max_width_for_codec1, max_height_for_codec1, min_width_for_codec1, min_height_for_codec1}}, + // {codec2, {{chroma_format1_for_codec2, chroma_format2_for_codec2, ...}, {bit_depth1_minus8_for_codec2, bit_depth2_minus8_for_codec2, ...}, output_format_mask_for_codec2, max_width_for_codec2, max_height_for_codec2, min_width_for_codec2, min_height_for_codec2}}} + // , vcn_instances_for_gcn_arch_name1}}, + vcn_spec_table = { + {"gfx803",{}}, + {"gfx900",{}}, + {"gfx906",{}}, + {"gfx908",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 4096, 2176, 64, 64}}, {rocDecVideoCodec_H264, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2160, 64, 64}}}, 2}}, + {"gfx90a",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 4096, 2176, 64, 64}}, {rocDecVideoCodec_H264, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2160, 64, 64}}}, 2}}, + {"gfx940",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_H264, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}}, 3}}, + {"gfx941",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_H264, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}}, 4}}, + {"gfx1030",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_H264, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}}, 2}}, + {"gfx1031",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_H264, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}}, 2}}, + {"gfx1032",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_H264, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}}, 2}},}; + } + RocDecVcnCodecSpec(const RocDecVcnCodecSpec&) = delete; + RocDecVcnCodecSpec& operator = (const RocDecVcnCodecSpec) = delete; + ~RocDecVcnCodecSpec() = default; +}; \ No newline at end of file diff --git a/src/rocdecode/rocdecode_api.cpp b/src/rocdecode/rocdecode_api.cpp index b33269241a..158c07a461 100644 --- a/src/rocdecode/rocdecode_api.cpp +++ b/src/rocdecode/rocdecode_api.cpp @@ -21,8 +21,10 @@ THE SOFTWARE. */ #include "dec_handle.h" #include "rocdecode.h" +#include "roc_decoder_caps.h" #include "../commons.h" + /*****************************************************************************************************/ //! \fn rocDecStatus ROCDECAPI rocDecCreateDecoder(rocDecDecoderHandle *phDecoder, RocdecDecoderCreateInfo *pdci) //! Create the decoder object based on pdci. A handle to the created decoder is returned @@ -60,7 +62,33 @@ rocDecDestroyDecoder(rocDecDecoderHandle hDecoder) { /**********************************************************************************************************************/ rocDecStatus ROCDECAPI rocDecGetDecoderCaps(RocdecDecodeCaps *pdc) { - return ROCDEC_NOT_IMPLEMENTED; + if (pdc == nullptr) { + return ROCDEC_INVALID_PARAMETER; + } + hipError_t hip_status = hipSuccess; + int num_devices = 0; + hipDeviceProp_t hip_dev_prop; + hip_status = hipGetDeviceCount(&num_devices); + if (hip_status != hipSuccess) { + ERR("ERROR: hipGetDeviceCount failed!" + TOSTR(hip_status)); + return ROCDEC_DEVICE_INVALID; + } + if (num_devices < 1) { + ERR("ERROR: didn't find any GPU!"); + return ROCDEC_DEVICE_INVALID; + } + if (pdc->deviceid >= num_devices) { + ERR("ERROR: the requested device_id is not found! "); + return ROCDEC_DEVICE_INVALID; + } + hip_status = hipGetDeviceProperties(&hip_dev_prop, pdc->deviceid); + if (hip_status != hipSuccess) { + ERR("ERROR: hipGetDeviceProperties for device (" +TOSTR(pdc->deviceid) + " ) failed! (" + TOSTR(hip_status) + ")" ); + return ROCDEC_DEVICE_INVALID; + } + + RocDecVcnCodecSpec& vcn_codec_spec = RocDecVcnCodecSpec::GetInastance(); + return vcn_codec_spec.GetDecoderCaps(hip_dev_prop.gcnArchName, pdc); } /*****************************************************************************************************/