Added the new GPU VA context class to handle VA connections to GPU. Removed the hard coded HW decoder capability info. (#415)
* * rocDecode: Removed the hard coded HW decoder capability info. - We now probe HW decoder capabilities through VA-API from the driver. * * rocDecode: Added number of decoder prob and a few missing tear down calls. * * rocDecode/HW cap change: Added a new singleton class, GpuVaContext, to handle HIP and VA initialization and VA attributes probe for both HW capability check and decoder initialization. * * rocDecode/HW caps: Removed GpuVaContext class out of vaapi_videodecoder.h and into a new file. Removed debug logs. Removed roc_decoder_caps.h. * * rocDecode/HW caps: Fixed a crash issue with multi-thread cases. Called to vaInitialize() and vaTerminte() should be paired. * * rocDecode/HW caps: Added multi-GPU support. * * rocDecode/HW cap: Moved GpuVaContext class implementation back to VAAPI layer. * * rocDecode/HW cap: Added changed based on review comments. * * rocDecode/HW cap: Added changes based on review comments. * * rocDecode/HW cap: GPU VA context class name change based on review comment. --------- Co-authored-by: Kiriti Gowda <kiritigowda@gmail.com>
Dieser Commit ist enthalten in:
1 Ursprung
6477cd1100
Commit
ef06f12dfa
7 Dateien geändert
+578
-405
Keine Dateien entsprechen Ihrer Suche
@@ -45,11 +45,6 @@ RocDecoder::RocDecoder(RocDecoderCreateInfo& decoder_create_info): va_video_deco
|
|||||||
|
|
||||||
rocDecStatus RocDecoder::InitializeDecoder() {
|
rocDecStatus RocDecoder::InitializeDecoder() {
|
||||||
rocDecStatus rocdec_status = ROCDEC_SUCCESS;
|
rocDecStatus rocdec_status = ROCDEC_SUCCESS;
|
||||||
rocdec_status = InitHIP(decoder_create_info_.device_id);
|
|
||||||
if (rocdec_status != ROCDEC_SUCCESS) {
|
|
||||||
ERR("Failed to initilize the HIP.");
|
|
||||||
return rocdec_status;
|
|
||||||
}
|
|
||||||
if (decoder_create_info_.num_decode_surfaces < 1) {
|
if (decoder_create_info_.num_decode_surfaces < 1) {
|
||||||
ERR("Invalid number of decode surfaces.");
|
ERR("Invalid number of decode surfaces.");
|
||||||
return ROCDEC_INVALID_PARAMETER;
|
return ROCDEC_INVALID_PARAMETER;
|
||||||
@@ -58,8 +53,7 @@ RocDecoder::RocDecoder(RocDecoderCreateInfo& decoder_create_info): va_video_deco
|
|||||||
for (auto i = 0; i < hip_interop_.size(); i++) {
|
for (auto i = 0; i < hip_interop_.size(); i++) {
|
||||||
memset((void *)&hip_interop_[i], 0, sizeof(hip_interop_[i]));
|
memset((void *)&hip_interop_[i], 0, sizeof(hip_interop_[i]));
|
||||||
}
|
}
|
||||||
std::string gpu_uuid(hip_dev_prop_.uuid.bytes, sizeof(hip_dev_prop_.uuid.bytes));
|
rocdec_status = va_video_decoder_.InitializeDecoder();
|
||||||
rocdec_status = va_video_decoder_.InitializeDecoder(hip_dev_prop_.name, hip_dev_prop_.gcnArchName, gpu_uuid);
|
|
||||||
if (rocdec_status != ROCDEC_SUCCESS) {
|
if (rocdec_status != ROCDEC_SUCCESS) {
|
||||||
ERR("Failed to initilize the VAAPI Video decoder.");
|
ERR("Failed to initilize the VAAPI Video decoder.");
|
||||||
return rocdec_status;
|
return rocdec_status;
|
||||||
@@ -186,16 +180,3 @@ rocDecStatus RocDecoder::FreeVideoFrame(int pic_idx) {
|
|||||||
|
|
||||||
return ROCDEC_SUCCESS;
|
return ROCDEC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
rocDecStatus RocDecoder::InitHIP(int device_id) {
|
|
||||||
CHECK_HIP(hipGetDeviceCount(&num_devices_));
|
|
||||||
if (num_devices_ < 1) {
|
|
||||||
ERR("Didn't find any GPU.");
|
|
||||||
return ROCDEC_DEVICE_INVALID;
|
|
||||||
}
|
|
||||||
CHECK_HIP(hipSetDevice(device_id));
|
|
||||||
CHECK_HIP(hipGetDeviceProperties(&hip_dev_prop_, device_id));
|
|
||||||
|
|
||||||
return ROCDEC_SUCCESS;
|
|
||||||
}
|
|
||||||
@@ -34,14 +34,6 @@ THE SOFTWARE.
|
|||||||
#include <hip/hip_runtime.h>
|
#include <hip/hip_runtime.h>
|
||||||
#include "vaapi/vaapi_videodecoder.h"
|
#include "vaapi/vaapi_videodecoder.h"
|
||||||
|
|
||||||
#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;\
|
|
||||||
return ROCDEC_RUNTIME_ERROR;\
|
|
||||||
}\
|
|
||||||
}
|
|
||||||
|
|
||||||
struct HipInteropDeviceMem {
|
struct HipInteropDeviceMem {
|
||||||
hipExternalMemory_t hip_ext_mem; // Interface to the vaapi-hip interop
|
hipExternalMemory_t hip_ext_mem; // Interface to the vaapi-hip interop
|
||||||
uint8_t* hip_mapped_device_mem; // Mapped device memory for the YUV plane
|
uint8_t* hip_mapped_device_mem; // Mapped device memory for the YUV plane
|
||||||
@@ -63,11 +55,9 @@ public:
|
|||||||
rocDecStatus GetVideoFrame(int pic_idx, void *dev_mem_ptr[3], uint32_t horizontal_pitch[3], RocdecProcParams *vid_postproc_params);
|
rocDecStatus GetVideoFrame(int pic_idx, void *dev_mem_ptr[3], uint32_t horizontal_pitch[3], RocdecProcParams *vid_postproc_params);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
rocDecStatus InitHIP(int device_id);
|
|
||||||
rocDecStatus FreeVideoFrame(int pic_idx);
|
rocDecStatus FreeVideoFrame(int pic_idx);
|
||||||
int num_devices_;
|
int num_devices_;
|
||||||
RocDecoderCreateInfo decoder_create_info_;
|
RocDecoderCreateInfo decoder_create_info_;
|
||||||
VaapiVideoDecoder va_video_decoder_;
|
VaapiVideoDecoder va_video_decoder_;
|
||||||
hipDeviceProp_t hip_dev_prop_;
|
|
||||||
std::vector<HipInteropDeviceMem> hip_interop_;
|
std::vector<HipInteropDeviceMem> hip_interop_;
|
||||||
};
|
};
|
||||||
@@ -1,141 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright (c) 2023 - 2025 Advanced Micro Devices, Inc. All rights reserved.
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <mutex>
|
|
||||||
#include <algorithm>
|
|
||||||
#include "../commons.h"
|
|
||||||
#include "../../api/rocdecode.h"
|
|
||||||
|
|
||||||
|
|
||||||
// The CodecSpec struct contains information for an individual codec (e.g., rocDecVideoCodec_HEVC)
|
|
||||||
struct CodecSpec {
|
|
||||||
std::vector<rocDecVideoChromaFormat> chroma_format;
|
|
||||||
std::vector<int> 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<rocDecVideoCodec, CodecSpec> codecs_spec;
|
|
||||||
uint8_t num_decoders;
|
|
||||||
};
|
|
||||||
|
|
||||||
// The RocDecVcnCodecSpec singleton class for providing access to the the vcn_spec_table
|
|
||||||
class RocDecVcnCodecSpec {
|
|
||||||
public:
|
|
||||||
static RocDecVcnCodecSpec& GetInstance() {
|
|
||||||
static RocDecVcnCodecSpec instance;
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
rocDecStatus GetDecoderCaps(std::string gcn_arch_name, RocdecDecodeCaps *pdc) {
|
|
||||||
std::lock_guard<std::mutex> lock(mutex);
|
|
||||||
std::size_t pos = gcn_arch_name.find_first_of(":");
|
|
||||||
std::string gcn_arch_name_base = (pos != std::string::npos) ? gcn_arch_name.substr(0, pos) : gcn_arch_name;
|
|
||||||
auto it = vcn_spec_table.find(gcn_arch_name_base);
|
|
||||||
if (it != vcn_spec_table.end()) {
|
|
||||||
const VcnCodecsSpec& vcn_spec = it->second;
|
|
||||||
auto it1 = vcn_spec.codecs_spec.find(pdc->codec_type);
|
|
||||||
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->chroma_format);
|
|
||||||
auto it_bitdepth_minus8 = std::find(codec_spec.bitdepth_minus8.begin(), codec_spec.bitdepth_minus8.end(), pdc->bit_depth_minus_8);
|
|
||||||
if (it_chroma_format != codec_spec.chroma_format.end() && it_bitdepth_minus8 != codec_spec.bitdepth_minus8.end()) {
|
|
||||||
pdc->is_supported = 1;
|
|
||||||
pdc->num_decoders = vcn_spec.num_decoders;
|
|
||||||
pdc->output_format_mask = codec_spec.output_format_mask;
|
|
||||||
pdc->max_width = codec_spec.max_width;
|
|
||||||
pdc->max_height = codec_spec.max_height;
|
|
||||||
pdc->min_width = codec_spec.min_width;
|
|
||||||
pdc->min_height = codec_spec.min_height;
|
|
||||||
return ROCDEC_SUCCESS;
|
|
||||||
} else {
|
|
||||||
return ROCDEC_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return ROCDEC_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ERR("Didn't find the decoder capability for " + gcn_arch_name + " GPU!");
|
|
||||||
return ROCDEC_NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool IsCodecConfigSupported(std::string gcn_arch_name, rocDecVideoCodec codec_type, rocDecVideoChromaFormat chroma_format, uint32_t bit_depth_minus8, rocDecVideoSurfaceFormat output_format) {
|
|
||||||
std::lock_guard<std::mutex> lock(mutex);
|
|
||||||
std::size_t pos = gcn_arch_name.find_first_of(":");
|
|
||||||
std::string gcn_arch_name_base = (pos != std::string::npos) ? gcn_arch_name.substr(0, pos) : gcn_arch_name;
|
|
||||||
auto it = vcn_spec_table.find(gcn_arch_name_base);
|
|
||||||
if (it != vcn_spec_table.end()) {
|
|
||||||
const VcnCodecsSpec& vcn_spec = it->second;
|
|
||||||
auto it1 = vcn_spec.codecs_spec.find(codec_type);
|
|
||||||
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(), chroma_format);
|
|
||||||
auto it_bitdepth_minus8 = std::find(codec_spec.bitdepth_minus8.begin(), codec_spec.bitdepth_minus8.end(), bit_depth_minus8);
|
|
||||||
if (it_chroma_format != codec_spec.chroma_format.end() && it_bitdepth_minus8 != codec_spec.bitdepth_minus8.end()) {
|
|
||||||
return (codec_spec.output_format_mask & (static_cast<int>(output_format) + 1));
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
std::unordered_map<std::string, VcnCodecsSpec> 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}},
|
|
||||||
// av1 is available only on VCN3.0 and above
|
|
||||||
vcn_spec_table = {
|
|
||||||
{"gfx908",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2160, 64, 64}}, {rocDecVideoCodec_VP9, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}}, 2}},
|
|
||||||
{"gfx90a",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2160, 64, 64}}, {rocDecVideoCodec_VP9, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}}, 2}},
|
|
||||||
{"gfx940",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}, {rocDecVideoCodec_VP9, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AV1, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}}, 3}},
|
|
||||||
{"gfx941",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}, {rocDecVideoCodec_VP9, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AV1, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}}, 4}},
|
|
||||||
{"gfx942",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}, {rocDecVideoCodec_VP9, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AV1, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}}, 3}},
|
|
||||||
{"gfx1030",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}, {rocDecVideoCodec_VP9, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AV1, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}}, 2}},
|
|
||||||
{"gfx1031",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}, {rocDecVideoCodec_VP9, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AV1, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}}, 2}},
|
|
||||||
{"gfx1032",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}, {rocDecVideoCodec_VP9, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AV1, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}}, 2}},
|
|
||||||
{"gfx1100",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}, {rocDecVideoCodec_VP9, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AV1, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}}, 2}},
|
|
||||||
{"gfx1101",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}, {rocDecVideoCodec_VP9, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AV1, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}}, 1}},
|
|
||||||
{"gfx1102",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}, {rocDecVideoCodec_VP9, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AV1, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}}, 2}},
|
|
||||||
{"gfx1200",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}, {rocDecVideoCodec_VP9, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}, {rocDecVideoCodec_AV1, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}}, 2}},
|
|
||||||
{"gfx1201",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}, {rocDecVideoCodec_VP9, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}, {rocDecVideoCodec_AV1, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}}, 2}},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
RocDecVcnCodecSpec(const RocDecVcnCodecSpec&) = delete;
|
|
||||||
RocDecVcnCodecSpec& operator = (const RocDecVcnCodecSpec) = delete;
|
|
||||||
~RocDecVcnCodecSpec() = default;
|
|
||||||
};
|
|
||||||
@@ -21,7 +21,7 @@ THE SOFTWARE.
|
|||||||
*/
|
*/
|
||||||
#include "dec_handle.h"
|
#include "dec_handle.h"
|
||||||
#include "rocdecode.h"
|
#include "rocdecode.h"
|
||||||
#include "roc_decoder_caps.h"
|
#include "vaapi_videodecoder.h"
|
||||||
#include "../commons.h"
|
#include "../commons.h"
|
||||||
|
|
||||||
namespace rocdecode {
|
namespace rocdecode {
|
||||||
@@ -72,30 +72,14 @@ rocDecGetDecoderCaps(RocdecDecodeCaps *pdc) {
|
|||||||
if (pdc == nullptr) {
|
if (pdc == nullptr) {
|
||||||
return ROCDEC_INVALID_PARAMETER;
|
return ROCDEC_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
hipError_t hip_status = hipSuccess;
|
VaContext& va_ctx = VaContext::GetInstance();
|
||||||
int num_devices = 0;
|
rocDecStatus ret = ROCDEC_SUCCESS;
|
||||||
hipDeviceProp_t hip_dev_prop;
|
if ((ret = va_ctx.CheckDecCapForCodecType(pdc)) != ROCDEC_SUCCESS) {
|
||||||
hip_status = hipGetDeviceCount(&num_devices);
|
ERR("Failed to obtain decoder capabilities from driver.");
|
||||||
if (hip_status != hipSuccess) {
|
return ret;
|
||||||
ERR("ERROR: hipGetDeviceCount failed!" + TOSTR(hip_status));
|
} else {
|
||||||
return ROCDEC_DEVICE_INVALID;
|
return ROCDEC_SUCCESS;
|
||||||
}
|
}
|
||||||
if (num_devices < 1) {
|
|
||||||
ERR("ERROR: didn't find any GPU!");
|
|
||||||
return ROCDEC_DEVICE_INVALID;
|
|
||||||
}
|
|
||||||
if (pdc->device_id >= num_devices) {
|
|
||||||
ERR("ERROR: the requested device_id is not found! ");
|
|
||||||
return ROCDEC_DEVICE_INVALID;
|
|
||||||
}
|
|
||||||
hip_status = hipGetDeviceProperties(&hip_dev_prop, pdc->device_id);
|
|
||||||
if (hip_status != hipSuccess) {
|
|
||||||
ERR("ERROR: hipGetDeviceProperties for device (" +TOSTR(pdc->device_id) + " ) failed! (" + TOSTR(hip_status) + ")" );
|
|
||||||
return ROCDEC_DEVICE_INVALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
RocDecVcnCodecSpec& vcn_codec_spec = RocDecVcnCodecSpec::GetInstance();
|
|
||||||
return vcn_codec_spec.GetDecoderCaps(hip_dev_prop.gcnArchName, pdc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************************************/
|
/*****************************************************************************************************/
|
||||||
|
|||||||
@@ -52,46 +52,27 @@ VaapiVideoDecoder::~VaapiVideoDecoder() {
|
|||||||
if (va_status != VA_STATUS_SUCCESS) {
|
if (va_status != VA_STATUS_SUCCESS) {
|
||||||
ERR("vaDestroyConfig failed");
|
ERR("vaDestroyConfig failed");
|
||||||
}
|
}
|
||||||
va_status = vaTerminate(va_display_);
|
|
||||||
if (va_status != VA_STATUS_SUCCESS) {
|
|
||||||
ERR("vaTerminate failed");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rocDecStatus VaapiVideoDecoder::InitializeDecoder(std::string device_name, std::string gcn_arch_name, std::string& gpu_uuid) {
|
rocDecStatus VaapiVideoDecoder::InitializeDecoder() {
|
||||||
rocDecStatus rocdec_status = ROCDEC_SUCCESS;
|
rocDecStatus rocdec_status = ROCDEC_SUCCESS;
|
||||||
|
|
||||||
//Before initializing the VAAPI, first check to see if the requested codec config is supported
|
// Before initializing the VAAPI, first check to see if the requested codec config is supported
|
||||||
RocDecVcnCodecSpec& vcn_codec_spec = RocDecVcnCodecSpec::GetInstance();
|
if (!IsCodecConfigSupported(decoder_create_info_.device_id, decoder_create_info_.codec_type, decoder_create_info_.chroma_format,
|
||||||
if (!vcn_codec_spec.IsCodecConfigSupported(gcn_arch_name, decoder_create_info_.codec_type, decoder_create_info_.chroma_format,
|
|
||||||
decoder_create_info_.bit_depth_minus_8, decoder_create_info_.output_format)) {
|
decoder_create_info_.bit_depth_minus_8, decoder_create_info_.output_format)) {
|
||||||
ERR("The codec config combination is not supported.");
|
ERR("The codec config combination is not supported.");
|
||||||
return ROCDEC_NOT_SUPPORTED;
|
return ROCDEC_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t pos = gcn_arch_name.find_first_of(":");
|
VaContext& va_ctx = VaContext::GetInstance();
|
||||||
std::string gcn_arch_name_base = (pos != std::string::npos) ? gcn_arch_name.substr(0, pos) : gcn_arch_name;
|
uint32_t va_ctx_id;
|
||||||
|
if ((rocdec_status = va_ctx.GetVaContext(decoder_create_info_.device_id, &va_ctx_id)) != ROCDEC_SUCCESS) {
|
||||||
std::vector<int> visible_devices;
|
ERR("Failed to get VA context.");
|
||||||
GetVisibleDevices(visible_devices);
|
return rocdec_status;
|
||||||
GetGpuUuids();
|
}
|
||||||
int offset = 0;
|
if ((rocdec_status = va_ctx.GetVaDisplay(va_ctx_id, &va_display_)) != ROCDEC_SUCCESS) {
|
||||||
if (gcn_arch_name_base.compare("gfx942") == 0) {
|
ERR("Failed to get VA display.");
|
||||||
std::vector<ComputePartition> current_compute_partitions;
|
|
||||||
GetCurrentComputePartition(current_compute_partitions);
|
|
||||||
if (!current_compute_partitions.empty()) {
|
|
||||||
GetDrmNodeOffset(device_name, decoder_create_info_.device_id, visible_devices, current_compute_partitions, offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string drm_node = "/dev/dri/renderD";
|
|
||||||
int render_node_id = (gpu_uuids_to_render_nodes_map_.find(gpu_uuid) != gpu_uuids_to_render_nodes_map_.end()) ? gpu_uuids_to_render_nodes_map_[gpu_uuid] : 128;
|
|
||||||
drm_node += std::to_string(render_node_id + offset);
|
|
||||||
|
|
||||||
rocdec_status = InitVAAPI(drm_node);
|
|
||||||
if (rocdec_status != ROCDEC_SUCCESS) {
|
|
||||||
ERR("Failed to initilize the VAAPI.");
|
|
||||||
return rocdec_status;
|
return rocdec_status;
|
||||||
}
|
}
|
||||||
rocdec_status = CreateDecoderConfig();
|
rocdec_status = CreateDecoderConfig();
|
||||||
@@ -112,157 +93,6 @@ rocDecStatus VaapiVideoDecoder::InitializeDecoder(std::string device_name, std::
|
|||||||
return rocdec_status;
|
return rocdec_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
rocDecStatus VaapiVideoDecoder::InitVAAPI(std::string drm_node) {
|
|
||||||
drm_fd_ = open(drm_node.c_str(), O_RDWR);
|
|
||||||
if (drm_fd_ < 0) {
|
|
||||||
ERR("Failed to open drm node." + drm_node);
|
|
||||||
return ROCDEC_NOT_INITIALIZED;
|
|
||||||
}
|
|
||||||
va_display_ = vaGetDisplayDRM(drm_fd_);
|
|
||||||
if (!va_display_) {
|
|
||||||
ERR("Failed to create va_display.");
|
|
||||||
return ROCDEC_NOT_INITIALIZED;
|
|
||||||
}
|
|
||||||
vaSetInfoCallback(va_display_, NULL, NULL);
|
|
||||||
int major_version = 0, minor_version = 0;
|
|
||||||
CHECK_VAAPI(vaInitialize(va_display_, &major_version, &minor_version));
|
|
||||||
return ROCDEC_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
rocDecStatus VaapiVideoDecoder::CreateDecoderConfig() {
|
|
||||||
switch (decoder_create_info_.codec_type) {
|
|
||||||
case rocDecVideoCodec_HEVC:
|
|
||||||
if (decoder_create_info_.bit_depth_minus_8 == 0) {
|
|
||||||
va_profile_ = VAProfileHEVCMain;
|
|
||||||
} else if (decoder_create_info_.bit_depth_minus_8 == 2) {
|
|
||||||
va_profile_ = VAProfileHEVCMain10;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case rocDecVideoCodec_AVC:
|
|
||||||
va_profile_ = VAProfileH264Main;
|
|
||||||
break;
|
|
||||||
case rocDecVideoCodec_VP9:
|
|
||||||
if (decoder_create_info_.bit_depth_minus_8 == 0) {
|
|
||||||
va_profile_ = VAProfileVP9Profile0;
|
|
||||||
} else if (decoder_create_info_.bit_depth_minus_8 == 2) {
|
|
||||||
va_profile_ = VAProfileVP9Profile2;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case rocDecVideoCodec_AV1:
|
|
||||||
#if VA_CHECK_VERSION(1,6,0)
|
|
||||||
va_profile_ = VAProfileAV1Profile0;
|
|
||||||
#else
|
|
||||||
va_profile_ = static_cast<VAProfile>(32); // VAProfileAV1Profile0;
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ERR("The codec type is not supported.");
|
|
||||||
return ROCDEC_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
va_config_attrib_.type = VAConfigAttribRTFormat;
|
|
||||||
CHECK_VAAPI(vaGetConfigAttributes(va_display_, va_profile_, VAEntrypointVLD, &va_config_attrib_, 1));
|
|
||||||
CHECK_VAAPI(vaCreateConfig(va_display_, va_profile_, VAEntrypointVLD, &va_config_attrib_, 1, &va_config_id_));
|
|
||||||
unsigned int num_attribs = 0;
|
|
||||||
CHECK_VAAPI(vaQuerySurfaceAttributes(va_display_, va_config_id_, nullptr, &num_attribs));
|
|
||||||
std::vector<VASurfaceAttrib> attribs(num_attribs);
|
|
||||||
CHECK_VAAPI(vaQuerySurfaceAttributes(va_display_, va_config_id_, attribs.data(), &num_attribs));
|
|
||||||
for (auto attrib : attribs) {
|
|
||||||
if (attrib.type == VASurfaceAttribDRMFormatModifiers) {
|
|
||||||
supports_modifiers_ = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ROCDEC_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
rocDecStatus VaapiVideoDecoder::CreateSurfaces() {
|
|
||||||
if (decoder_create_info_.num_decode_surfaces < 1) {
|
|
||||||
ERR("Invalid number of decode surfaces.");
|
|
||||||
return ROCDEC_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
va_surface_ids_.resize(decoder_create_info_.num_decode_surfaces);
|
|
||||||
std::vector<VASurfaceAttrib> surf_attribs;
|
|
||||||
VASurfaceAttrib surf_attrib;
|
|
||||||
surf_attrib.type = VASurfaceAttribPixelFormat;
|
|
||||||
surf_attrib.flags = VA_SURFACE_ATTRIB_SETTABLE;
|
|
||||||
surf_attrib.value.type = VAGenericValueTypeInteger;
|
|
||||||
uint32_t surface_format;
|
|
||||||
switch (decoder_create_info_.chroma_format) {
|
|
||||||
case rocDecVideoChromaFormat_Monochrome:
|
|
||||||
surface_format = VA_RT_FORMAT_YUV400;
|
|
||||||
surf_attrib.value.value.i = VA_FOURCC_Y800;
|
|
||||||
break;
|
|
||||||
case rocDecVideoChromaFormat_420:
|
|
||||||
if (decoder_create_info_.bit_depth_minus_8 == 2) {
|
|
||||||
surface_format = VA_RT_FORMAT_YUV420_10;
|
|
||||||
surf_attrib.value.value.i = VA_FOURCC_P010;
|
|
||||||
} else if (decoder_create_info_.bit_depth_minus_8 == 4) {
|
|
||||||
surface_format = VA_RT_FORMAT_YUV420_12;
|
|
||||||
#if VA_CHECK_VERSION(1,8,0)
|
|
||||||
surf_attrib.value.value.i = VA_FOURCC_P012;
|
|
||||||
#else
|
|
||||||
surf_attrib.value.value.i = 0x32313050; // VA_FOURCC_P012
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
surface_format = VA_RT_FORMAT_YUV420;
|
|
||||||
surf_attrib.value.value.i = VA_FOURCC_NV12;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case rocDecVideoChromaFormat_422:
|
|
||||||
surface_format = VA_RT_FORMAT_YUV422;
|
|
||||||
break;
|
|
||||||
case rocDecVideoChromaFormat_444:
|
|
||||||
surface_format = VA_RT_FORMAT_YUV444;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ERR("The surface type is not supported");
|
|
||||||
return ROCDEC_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
surf_attribs.push_back(surf_attrib);
|
|
||||||
uint64_t mod_linear = 0;
|
|
||||||
VADRMFormatModifierList modifier_list = {
|
|
||||||
.num_modifiers = 1,
|
|
||||||
.modifiers = &mod_linear,
|
|
||||||
};
|
|
||||||
if (supports_modifiers_) {
|
|
||||||
surf_attrib.type = VASurfaceAttribDRMFormatModifiers;
|
|
||||||
surf_attrib.value.type = VAGenericValueTypePointer;
|
|
||||||
surf_attrib.value.value.p = &modifier_list;
|
|
||||||
surf_attribs.push_back(surf_attrib);
|
|
||||||
}
|
|
||||||
CHECK_VAAPI(vaCreateSurfaces(va_display_, surface_format, decoder_create_info_.width,
|
|
||||||
decoder_create_info_.height, va_surface_ids_.data(), va_surface_ids_.size(), surf_attribs.data(), surf_attribs.size()));
|
|
||||||
return ROCDEC_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
rocDecStatus VaapiVideoDecoder::CreateContext() {
|
|
||||||
CHECK_VAAPI(vaCreateContext(va_display_, va_config_id_, decoder_create_info_.width, decoder_create_info_.height,
|
|
||||||
VA_PROGRESSIVE, va_surface_ids_.data(), va_surface_ids_.size(), &va_context_id_));
|
|
||||||
return ROCDEC_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
rocDecStatus VaapiVideoDecoder::DestroyDataBuffers() {
|
|
||||||
if (pic_params_buf_id_) {
|
|
||||||
CHECK_VAAPI(vaDestroyBuffer(va_display_, pic_params_buf_id_));
|
|
||||||
pic_params_buf_id_ = 0;
|
|
||||||
}
|
|
||||||
if (iq_matrix_buf_id_) {
|
|
||||||
CHECK_VAAPI(vaDestroyBuffer(va_display_, iq_matrix_buf_id_));
|
|
||||||
iq_matrix_buf_id_ = 0;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < num_slices_; i++) {
|
|
||||||
if (slice_params_buf_id_[i]) {
|
|
||||||
CHECK_VAAPI(vaDestroyBuffer(va_display_, slice_params_buf_id_[i]));
|
|
||||||
slice_params_buf_id_[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (slice_data_buf_id_) {
|
|
||||||
CHECK_VAAPI(vaDestroyBuffer(va_display_, slice_data_buf_id_));
|
|
||||||
slice_data_buf_id_ = 0;
|
|
||||||
}
|
|
||||||
return ROCDEC_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
rocDecStatus VaapiVideoDecoder::SubmitDecode(RocdecPicParams *pPicParams) {
|
rocDecStatus VaapiVideoDecoder::SubmitDecode(RocdecPicParams *pPicParams) {
|
||||||
void *pic_params_ptr, *iq_matrix_ptr, *slice_params_ptr;
|
void *pic_params_ptr, *iq_matrix_ptr, *slice_params_ptr;
|
||||||
uint32_t pic_params_size, iq_matrix_size, slice_params_size;
|
uint32_t pic_params_size, iq_matrix_size, slice_params_size;
|
||||||
@@ -483,6 +313,18 @@ rocDecStatus VaapiVideoDecoder::ExportSurface(int pic_idx, VADRMPRIMESurfaceDesc
|
|||||||
return ROCDEC_SUCCESS;
|
return ROCDEC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rocDecStatus VaapiVideoDecoder::SyncSurface(int pic_idx) {
|
||||||
|
if (pic_idx >= va_surface_ids_.size()) {
|
||||||
|
return ROCDEC_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
VASurfaceStatus surface_status;
|
||||||
|
CHECK_VAAPI(vaQuerySurfaceStatus(va_display_, va_surface_ids_[pic_idx], &surface_status));
|
||||||
|
if (surface_status != VASurfaceReady) {
|
||||||
|
CHECK_VAAPI(vaSyncSurface(va_display_, va_surface_ids_[pic_idx]));
|
||||||
|
}
|
||||||
|
return ROCDEC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
rocDecStatus VaapiVideoDecoder::ReconfigureDecoder(RocdecReconfigureDecoderInfo *reconfig_params) {
|
rocDecStatus VaapiVideoDecoder::ReconfigureDecoder(RocdecReconfigureDecoderInfo *reconfig_params) {
|
||||||
if (reconfig_params == nullptr) {
|
if (reconfig_params == nullptr) {
|
||||||
return ROCDEC_INVALID_PARAMETER;
|
return ROCDEC_INVALID_PARAMETER;
|
||||||
@@ -514,19 +356,480 @@ rocDecStatus VaapiVideoDecoder::ReconfigureDecoder(RocdecReconfigureDecoderInfo
|
|||||||
return rocdec_status;
|
return rocdec_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
rocDecStatus VaapiVideoDecoder::SyncSurface(int pic_idx) {
|
bool VaapiVideoDecoder::IsCodecConfigSupported(int device_id, rocDecVideoCodec codec_type, rocDecVideoChromaFormat chroma_format, uint32_t bit_depth_minus8, rocDecVideoSurfaceFormat output_format) {
|
||||||
if (pic_idx >= va_surface_ids_.size()) {
|
RocdecDecodeCaps decode_caps;
|
||||||
return ROCDEC_INVALID_PARAMETER;
|
decode_caps.device_id = device_id;
|
||||||
|
decode_caps.codec_type = codec_type;
|
||||||
|
decode_caps.chroma_format = chroma_format;
|
||||||
|
decode_caps.bit_depth_minus_8 = bit_depth_minus8;
|
||||||
|
if((rocDecGetDecoderCaps(&decode_caps) != ROCDEC_SUCCESS) || (decode_caps.is_supported == false) || ((decode_caps.output_format_mask & (1 << output_format)) == 0)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
VASurfaceStatus surface_status;
|
}
|
||||||
CHECK_VAAPI(vaQuerySurfaceStatus(va_display_, va_surface_ids_[pic_idx], &surface_status));
|
|
||||||
if (surface_status != VASurfaceReady) {
|
rocDecStatus VaapiVideoDecoder::CreateDecoderConfig() {
|
||||||
CHECK_VAAPI(vaSyncSurface(va_display_, va_surface_ids_[pic_idx]));
|
switch (decoder_create_info_.codec_type) {
|
||||||
|
case rocDecVideoCodec_HEVC:
|
||||||
|
if (decoder_create_info_.bit_depth_minus_8 == 0) {
|
||||||
|
va_profile_ = VAProfileHEVCMain;
|
||||||
|
} else if (decoder_create_info_.bit_depth_minus_8 == 2) {
|
||||||
|
va_profile_ = VAProfileHEVCMain10;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case rocDecVideoCodec_AVC:
|
||||||
|
va_profile_ = VAProfileH264Main;
|
||||||
|
break;
|
||||||
|
case rocDecVideoCodec_VP9:
|
||||||
|
if (decoder_create_info_.bit_depth_minus_8 == 0) {
|
||||||
|
va_profile_ = VAProfileVP9Profile0;
|
||||||
|
} else if (decoder_create_info_.bit_depth_minus_8 == 2) {
|
||||||
|
va_profile_ = VAProfileVP9Profile2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case rocDecVideoCodec_AV1:
|
||||||
|
#if VA_CHECK_VERSION(1,6,0)
|
||||||
|
va_profile_ = VAProfileAV1Profile0;
|
||||||
|
#else
|
||||||
|
va_profile_ = static_cast<VAProfile>(32); // VAProfileAV1Profile0;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ERR("The codec type is not supported.");
|
||||||
|
return ROCDEC_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
va_config_attrib_.type = VAConfigAttribRTFormat;
|
||||||
|
CHECK_VAAPI(vaGetConfigAttributes(va_display_, va_profile_, VAEntrypointVLD, &va_config_attrib_, 1));
|
||||||
|
CHECK_VAAPI(vaCreateConfig(va_display_, va_profile_, VAEntrypointVLD, &va_config_attrib_, 1, &va_config_id_));
|
||||||
|
unsigned int num_attribs = 0;
|
||||||
|
CHECK_VAAPI(vaQuerySurfaceAttributes(va_display_, va_config_id_, nullptr, &num_attribs));
|
||||||
|
std::vector<VASurfaceAttrib> attribs(num_attribs);
|
||||||
|
CHECK_VAAPI(vaQuerySurfaceAttributes(va_display_, va_config_id_, attribs.data(), &num_attribs));
|
||||||
|
for (auto attrib : attribs) {
|
||||||
|
if (attrib.type == VASurfaceAttribDRMFormatModifiers) {
|
||||||
|
supports_modifiers_ = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ROCDEC_SUCCESS;
|
return ROCDEC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VaapiVideoDecoder::GetVisibleDevices(std::vector<int>& visible_devices_vetor) {
|
rocDecStatus VaapiVideoDecoder::CreateSurfaces() {
|
||||||
|
if (decoder_create_info_.num_decode_surfaces < 1) {
|
||||||
|
ERR("Invalid number of decode surfaces.");
|
||||||
|
return ROCDEC_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
va_surface_ids_.resize(decoder_create_info_.num_decode_surfaces);
|
||||||
|
std::vector<VASurfaceAttrib> surf_attribs;
|
||||||
|
VASurfaceAttrib surf_attrib;
|
||||||
|
surf_attrib.type = VASurfaceAttribPixelFormat;
|
||||||
|
surf_attrib.flags = VA_SURFACE_ATTRIB_SETTABLE;
|
||||||
|
surf_attrib.value.type = VAGenericValueTypeInteger;
|
||||||
|
uint32_t surface_format;
|
||||||
|
switch (decoder_create_info_.chroma_format) {
|
||||||
|
case rocDecVideoChromaFormat_Monochrome:
|
||||||
|
surface_format = VA_RT_FORMAT_YUV400;
|
||||||
|
surf_attrib.value.value.i = VA_FOURCC_Y800;
|
||||||
|
break;
|
||||||
|
case rocDecVideoChromaFormat_420:
|
||||||
|
if (decoder_create_info_.bit_depth_minus_8 == 2) {
|
||||||
|
surface_format = VA_RT_FORMAT_YUV420_10;
|
||||||
|
surf_attrib.value.value.i = VA_FOURCC_P010;
|
||||||
|
} else if (decoder_create_info_.bit_depth_minus_8 == 4) {
|
||||||
|
surface_format = VA_RT_FORMAT_YUV420_12;
|
||||||
|
#if VA_CHECK_VERSION(1,8,0)
|
||||||
|
surf_attrib.value.value.i = VA_FOURCC_P012;
|
||||||
|
#else
|
||||||
|
surf_attrib.value.value.i = 0x32313050; // VA_FOURCC_P012
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
surface_format = VA_RT_FORMAT_YUV420;
|
||||||
|
surf_attrib.value.value.i = VA_FOURCC_NV12;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case rocDecVideoChromaFormat_422:
|
||||||
|
surface_format = VA_RT_FORMAT_YUV422;
|
||||||
|
break;
|
||||||
|
case rocDecVideoChromaFormat_444:
|
||||||
|
surface_format = VA_RT_FORMAT_YUV444;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ERR("The surface type is not supported");
|
||||||
|
return ROCDEC_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
surf_attribs.push_back(surf_attrib);
|
||||||
|
uint64_t mod_linear = 0;
|
||||||
|
VADRMFormatModifierList modifier_list = {
|
||||||
|
.num_modifiers = 1,
|
||||||
|
.modifiers = &mod_linear,
|
||||||
|
};
|
||||||
|
if (supports_modifiers_) {
|
||||||
|
surf_attrib.type = VASurfaceAttribDRMFormatModifiers;
|
||||||
|
surf_attrib.value.type = VAGenericValueTypePointer;
|
||||||
|
surf_attrib.value.value.p = &modifier_list;
|
||||||
|
surf_attribs.push_back(surf_attrib);
|
||||||
|
}
|
||||||
|
CHECK_VAAPI(vaCreateSurfaces(va_display_, surface_format, decoder_create_info_.width,
|
||||||
|
decoder_create_info_.height, va_surface_ids_.data(), va_surface_ids_.size(), surf_attribs.data(), surf_attribs.size()));
|
||||||
|
return ROCDEC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
rocDecStatus VaapiVideoDecoder::CreateContext() {
|
||||||
|
CHECK_VAAPI(vaCreateContext(va_display_, va_config_id_, decoder_create_info_.width, decoder_create_info_.height,
|
||||||
|
VA_PROGRESSIVE, va_surface_ids_.data(), va_surface_ids_.size(), &va_context_id_));
|
||||||
|
return ROCDEC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
rocDecStatus VaapiVideoDecoder::DestroyDataBuffers() {
|
||||||
|
if (pic_params_buf_id_) {
|
||||||
|
CHECK_VAAPI(vaDestroyBuffer(va_display_, pic_params_buf_id_));
|
||||||
|
pic_params_buf_id_ = 0;
|
||||||
|
}
|
||||||
|
if (iq_matrix_buf_id_) {
|
||||||
|
CHECK_VAAPI(vaDestroyBuffer(va_display_, iq_matrix_buf_id_));
|
||||||
|
iq_matrix_buf_id_ = 0;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < num_slices_; i++) {
|
||||||
|
if (slice_params_buf_id_[i]) {
|
||||||
|
CHECK_VAAPI(vaDestroyBuffer(va_display_, slice_params_buf_id_[i]));
|
||||||
|
slice_params_buf_id_[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (slice_data_buf_id_) {
|
||||||
|
CHECK_VAAPI(vaDestroyBuffer(va_display_, slice_data_buf_id_));
|
||||||
|
slice_data_buf_id_ = 0;
|
||||||
|
}
|
||||||
|
return ROCDEC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
VaContext::VaContext() {
|
||||||
|
GetGpuUuids();
|
||||||
|
}
|
||||||
|
|
||||||
|
VaContext::~VaContext() {
|
||||||
|
for (int i = 0; i < va_contexts_.size(); i++) {
|
||||||
|
if (va_contexts_[i].va_display) {
|
||||||
|
if (vaTerminate(va_contexts_[i].va_display) != VA_STATUS_SUCCESS) {
|
||||||
|
ERR("Failed to termiate VA");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
rocDecStatus VaContext::GetVaContext(int device_id, uint32_t *va_ctx_id) {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
bool found_existing = false;
|
||||||
|
uint32_t va_ctx_idx = 0;
|
||||||
|
hipDeviceProp_t hip_dev_prop;
|
||||||
|
rocDecStatus rocdec_status = ROCDEC_SUCCESS;
|
||||||
|
rocdec_status = InitHIP(device_id, hip_dev_prop);
|
||||||
|
if (rocdec_status != ROCDEC_SUCCESS) {
|
||||||
|
ERR("Failed to initilize the HIP.");
|
||||||
|
return rocdec_status;
|
||||||
|
}
|
||||||
|
std::string gpu_uuid(hip_dev_prop.uuid.bytes, sizeof(hip_dev_prop.uuid.bytes));
|
||||||
|
|
||||||
|
if (!va_contexts_.empty()) {
|
||||||
|
for (va_ctx_idx = 0; va_ctx_idx < va_contexts_.size(); va_ctx_idx++) {
|
||||||
|
if (gpu_uuid.compare(va_contexts_[va_ctx_idx].gpu_uuid) == 0) {
|
||||||
|
found_existing = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (found_existing) {
|
||||||
|
*va_ctx_id = va_ctx_idx;
|
||||||
|
return ROCDEC_SUCCESS;
|
||||||
|
} else {
|
||||||
|
va_contexts_.resize(va_contexts_.size() + 1);
|
||||||
|
va_ctx_idx = va_contexts_.size() - 1;
|
||||||
|
|
||||||
|
va_contexts_[va_ctx_idx].device_id = device_id;
|
||||||
|
va_contexts_[va_ctx_idx].gpu_uuid.assign(gpu_uuid);
|
||||||
|
va_contexts_[va_ctx_idx].hip_dev_prop = hip_dev_prop;
|
||||||
|
va_contexts_[va_ctx_idx].drm_fd = -1;
|
||||||
|
va_contexts_[va_ctx_idx].va_display = 0;
|
||||||
|
va_contexts_[va_ctx_idx].num_dec_engines = 1;
|
||||||
|
va_contexts_[va_ctx_idx].va_profile = VAProfileNone;
|
||||||
|
va_contexts_[va_ctx_idx].config_attributes_probed = false;
|
||||||
|
|
||||||
|
std::string gcn_arch_name = va_contexts_[va_ctx_idx].hip_dev_prop.gcnArchName;
|
||||||
|
std::size_t pos = gcn_arch_name.find_first_of(":");
|
||||||
|
std::string gcn_arch_name_base = (pos != std::string::npos) ? gcn_arch_name.substr(0, pos) : gcn_arch_name;
|
||||||
|
std::vector<int> visible_devices;
|
||||||
|
GetVisibleDevices(visible_devices);
|
||||||
|
|
||||||
|
int offset = 0;
|
||||||
|
if (gcn_arch_name_base.compare("gfx942") == 0) {
|
||||||
|
std::vector<ComputePartition> current_compute_partitions;
|
||||||
|
GetCurrentComputePartition(current_compute_partitions);
|
||||||
|
if (!current_compute_partitions.empty()) {
|
||||||
|
GetDrmNodeOffset(va_contexts_[va_ctx_idx].hip_dev_prop.name, va_contexts_[va_ctx_idx].device_id, visible_devices, current_compute_partitions, offset);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string drm_node = "/dev/dri/renderD";
|
||||||
|
int render_node_id = (gpu_uuids_to_render_nodes_map_.find(gpu_uuid) != gpu_uuids_to_render_nodes_map_.end()) ? gpu_uuids_to_render_nodes_map_[gpu_uuid] : 128;
|
||||||
|
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.");
|
||||||
|
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);
|
||||||
|
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.");
|
||||||
|
}
|
||||||
|
amdgpu_device_deinitialize(dev_handle);
|
||||||
|
|
||||||
|
// Prob VA profiles
|
||||||
|
va_contexts_[va_ctx_idx].num_va_profiles = vaMaxNumProfiles(va_contexts_[va_ctx_idx].va_display);
|
||||||
|
va_contexts_[va_ctx_idx].va_profile_list.resize(va_contexts_[va_ctx_idx].num_va_profiles);
|
||||||
|
CHECK_VAAPI(vaQueryConfigProfiles(va_contexts_[va_ctx_idx].va_display, va_contexts_[va_ctx_idx].va_profile_list.data(), &va_contexts_[va_ctx_idx].num_va_profiles));
|
||||||
|
|
||||||
|
*va_ctx_id = va_ctx_idx;
|
||||||
|
return ROCDEC_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rocDecStatus VaContext::GetVaDisplay(uint32_t va_ctx_id, VADisplay *va_display) {
|
||||||
|
if (va_ctx_id >= va_contexts_.size()) {
|
||||||
|
ERR("Invalid VA context Id.");
|
||||||
|
*va_display = 0;
|
||||||
|
return ROCDEC_INVALID_PARAMETER;
|
||||||
|
} else {
|
||||||
|
*va_display = va_contexts_[va_ctx_id].va_display;
|
||||||
|
return ROCDEC_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rocDecStatus VaContext::CheckDecCapForCodecType(RocdecDecodeCaps *dec_cap) {
|
||||||
|
if (dec_cap == nullptr) {
|
||||||
|
ERR("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.");
|
||||||
|
return rocdec_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
dec_cap->is_supported = 1; // init value
|
||||||
|
VAProfile va_profile = VAProfileNone;
|
||||||
|
switch (dec_cap->codec_type) {
|
||||||
|
case rocDecVideoCodec_HEVC: {
|
||||||
|
if (dec_cap->bit_depth_minus_8 == 0) {
|
||||||
|
va_profile = VAProfileHEVCMain;
|
||||||
|
} else if (dec_cap->bit_depth_minus_8 == 2) {
|
||||||
|
va_profile = VAProfileHEVCMain10;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case rocDecVideoCodec_AVC: {
|
||||||
|
va_profile = VAProfileH264Main;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case rocDecVideoCodec_VP9: {
|
||||||
|
if (dec_cap->bit_depth_minus_8 == 0) {
|
||||||
|
va_profile = VAProfileVP9Profile0;
|
||||||
|
} else if (dec_cap->bit_depth_minus_8 == 2) {
|
||||||
|
va_profile = VAProfileVP9Profile2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case rocDecVideoCodec_AV1: {
|
||||||
|
#if VA_CHECK_VERSION(1,6,0)
|
||||||
|
va_profile = VAProfileAV1Profile0;
|
||||||
|
#else
|
||||||
|
va_profile = static_cast<VAProfile>(32); // VAProfileAV1Profile0;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
dec_cap->is_supported = 0;
|
||||||
|
return ROCDEC_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < va_contexts_[va_ctx_id].num_va_profiles; i++) {
|
||||||
|
if (va_contexts_[va_ctx_id].va_profile_list[i] == va_profile) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == va_contexts_[va_ctx_id].num_va_profiles) {
|
||||||
|
dec_cap->is_supported = 0;
|
||||||
|
return ROCDEC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the config attributes of the profile have been probed before
|
||||||
|
if (va_profile != va_contexts_[va_ctx_id].va_profile || va_contexts_[va_ctx_id].config_attributes_probed == false) {
|
||||||
|
va_contexts_[va_ctx_id].va_profile = va_profile;
|
||||||
|
|
||||||
|
VAConfigAttrib va_config_attrib;
|
||||||
|
unsigned int attr_count;
|
||||||
|
std::vector<VASurfaceAttrib> attr_list;
|
||||||
|
va_config_attrib.type = VAConfigAttribRTFormat;
|
||||||
|
CHECK_VAAPI(vaGetConfigAttributes(va_contexts_[va_ctx_id].va_display, va_contexts_[va_ctx_id].va_profile, VAEntrypointVLD, &va_config_attrib, 1));
|
||||||
|
va_contexts_[va_ctx_id].rt_format_attrib = va_config_attrib.value;
|
||||||
|
|
||||||
|
CHECK_VAAPI(vaCreateConfig(va_contexts_[va_ctx_id].va_display, va_contexts_[va_ctx_id].va_profile, VAEntrypointVLD, &va_config_attrib, 1, &va_contexts_[va_ctx_id].va_config_id));
|
||||||
|
CHECK_VAAPI(vaQuerySurfaceAttributes(va_contexts_[va_ctx_id].va_display, va_contexts_[va_ctx_id].va_config_id, 0, &attr_count));
|
||||||
|
attr_list.resize(attr_count);
|
||||||
|
CHECK_VAAPI(vaQuerySurfaceAttributes(va_contexts_[va_ctx_id].va_display, va_contexts_[va_ctx_id].va_config_id, attr_list.data(), &attr_count));
|
||||||
|
va_contexts_[va_ctx_id].output_format_mask = 0;
|
||||||
|
CHECK_VAAPI(vaDestroyConfig(va_contexts_[va_ctx_id].va_display, va_contexts_[va_ctx_id].va_config_id));
|
||||||
|
for (int k = 0; k < attr_count; k++) {
|
||||||
|
switch (attr_list[k].type) {
|
||||||
|
case VASurfaceAttribPixelFormat: {
|
||||||
|
switch (attr_list[k].value.value.i) {
|
||||||
|
case VA_FOURCC_NV12:
|
||||||
|
va_contexts_[va_ctx_id].output_format_mask |= 1 << rocDecVideoSurfaceFormat_NV12;
|
||||||
|
break;
|
||||||
|
case VA_FOURCC_P016:
|
||||||
|
va_contexts_[va_ctx_id].output_format_mask |= 1 << rocDecVideoSurfaceFormat_P016;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case VASurfaceAttribMinWidth:
|
||||||
|
va_contexts_[va_ctx_id].min_width = attr_list[k].value.value.i;
|
||||||
|
break;
|
||||||
|
case VASurfaceAttribMinHeight:
|
||||||
|
va_contexts_[va_ctx_id].min_height = attr_list[k].value.value.i;
|
||||||
|
break;
|
||||||
|
case VASurfaceAttribMaxWidth:
|
||||||
|
va_contexts_[va_ctx_id].max_width = attr_list[k].value.value.i;
|
||||||
|
break;
|
||||||
|
case VASurfaceAttribMaxHeight:
|
||||||
|
va_contexts_[va_ctx_id].max_height = attr_list[k].value.value.i;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
va_contexts_[va_ctx_id].config_attributes_probed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check chroma format
|
||||||
|
switch (dec_cap->chroma_format) {
|
||||||
|
case rocDecVideoChromaFormat_Monochrome: {
|
||||||
|
if ((va_contexts_[va_ctx_id].rt_format_attrib & VA_RT_FORMAT_YUV400) == 0) {
|
||||||
|
dec_cap->is_supported = 0;
|
||||||
|
return ROCDEC_SUCCESS;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case rocDecVideoChromaFormat_420: {
|
||||||
|
if ((va_contexts_[va_ctx_id].rt_format_attrib & (VA_RT_FORMAT_YUV420 | VA_RT_FORMAT_YUV420_10 | VA_RT_FORMAT_YUV420_12)) == 0) {
|
||||||
|
dec_cap->is_supported = 0;
|
||||||
|
return ROCDEC_SUCCESS;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case rocDecVideoChromaFormat_422: {
|
||||||
|
if ((va_contexts_[va_ctx_id].rt_format_attrib & (VA_RT_FORMAT_YUV422 | VA_RT_FORMAT_YUV422_10 | VA_RT_FORMAT_YUV422_12)) == 0) {
|
||||||
|
dec_cap->is_supported = 0;
|
||||||
|
return ROCDEC_SUCCESS;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case rocDecVideoChromaFormat_444: {
|
||||||
|
if ((va_contexts_[va_ctx_id].rt_format_attrib & (VA_RT_FORMAT_YUV444 | VA_RT_FORMAT_YUV444_10 | VA_RT_FORMAT_YUV444_12)) == 0) {
|
||||||
|
dec_cap->is_supported = 0;
|
||||||
|
return ROCDEC_SUCCESS;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
dec_cap->is_supported = 0;
|
||||||
|
return ROCDEC_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check bit depth
|
||||||
|
switch (dec_cap->bit_depth_minus_8) {
|
||||||
|
case 0: {
|
||||||
|
if ((va_contexts_[va_ctx_id].rt_format_attrib & (VA_RT_FORMAT_YUV420 | VA_RT_FORMAT_YUV422 | VA_RT_FORMAT_YUV444 | VA_RT_FORMAT_YUV400)) == 0) {
|
||||||
|
dec_cap->is_supported = 0;
|
||||||
|
return ROCDEC_SUCCESS;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
if ((va_contexts_[va_ctx_id].rt_format_attrib & (VA_RT_FORMAT_YUV420_10 | VA_RT_FORMAT_YUV422_10 | VA_RT_FORMAT_YUV444_10)) == 0) {
|
||||||
|
dec_cap->is_supported = 0;
|
||||||
|
return ROCDEC_SUCCESS;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4: {
|
||||||
|
if ((va_contexts_[va_ctx_id].rt_format_attrib & (VA_RT_FORMAT_YUV420_12 | VA_RT_FORMAT_YUV422_12 | VA_RT_FORMAT_YUV444_12)) == 0) {
|
||||||
|
dec_cap->is_supported = 0;
|
||||||
|
return ROCDEC_SUCCESS;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
dec_cap->is_supported = 0;
|
||||||
|
return ROCDEC_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dec_cap->num_decoders = va_contexts_[va_ctx_id].num_dec_engines;
|
||||||
|
dec_cap->output_format_mask = va_contexts_[va_ctx_id].output_format_mask;
|
||||||
|
dec_cap->max_width = va_contexts_[va_ctx_id].max_width;
|
||||||
|
dec_cap->max_height = va_contexts_[va_ctx_id].max_height;
|
||||||
|
dec_cap->min_width = va_contexts_[va_ctx_id].min_width;
|
||||||
|
dec_cap->min_height = va_contexts_[va_ctx_id].min_height;
|
||||||
|
return ROCDEC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
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.");
|
||||||
|
return ROCDEC_DEVICE_INVALID;
|
||||||
|
}
|
||||||
|
if (device_id >= num_devices_) {
|
||||||
|
ERR("ERROR: the requested device_id is not found! ");
|
||||||
|
return ROCDEC_DEVICE_INVALID;
|
||||||
|
}
|
||||||
|
CHECK_HIP(hipSetDevice(device_id));
|
||||||
|
CHECK_HIP(hipGetDeviceProperties(&hip_dev_prop, device_id));
|
||||||
|
return ROCDEC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
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.");
|
||||||
|
return ROCDEC_NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
vaSetInfoCallback(va_contexts_[va_ctx_idx].va_display, NULL, NULL);
|
||||||
|
int major_version = 0, minor_version = 0;
|
||||||
|
CHECK_VAAPI(vaInitialize(va_contexts_[va_ctx_idx].va_display, &major_version, &minor_version));
|
||||||
|
return ROCDEC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VaContext::GetVisibleDevices(std::vector<int>& visible_devices_vetor) {
|
||||||
// First, check if the ROCR_VISIBLE_DEVICES environment variable is present
|
// First, check if the ROCR_VISIBLE_DEVICES environment variable is present
|
||||||
char *visible_devices = std::getenv("ROCR_VISIBLE_DEVICES");
|
char *visible_devices = std::getenv("ROCR_VISIBLE_DEVICES");
|
||||||
// If ROCR_VISIBLE_DEVICES is not present, check if HIP_VISIBLE_DEVICES is present
|
// If ROCR_VISIBLE_DEVICES is not present, check if HIP_VISIBLE_DEVICES is present
|
||||||
@@ -539,11 +842,11 @@ void VaapiVideoDecoder::GetVisibleDevices(std::vector<int>& visible_devices_veto
|
|||||||
visible_devices_vetor.push_back(std::atoi(token));
|
visible_devices_vetor.push_back(std::atoi(token));
|
||||||
token = std::strtok(nullptr,",");
|
token = std::strtok(nullptr,",");
|
||||||
}
|
}
|
||||||
std::sort(visible_devices_vetor.begin(), visible_devices_vetor.end());
|
std::sort(visible_devices_vetor.begin(), visible_devices_vetor.end());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VaapiVideoDecoder::GetCurrentComputePartition(std::vector<ComputePartition> ¤t_compute_partitions) {
|
void VaContext::GetCurrentComputePartition(std::vector<ComputePartition> ¤t_compute_partitions) {
|
||||||
std::string search_path = "/sys/devices/";
|
std::string search_path = "/sys/devices/";
|
||||||
std::string partition_file = "current_compute_partition";
|
std::string partition_file = "current_compute_partition";
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
@@ -577,9 +880,7 @@ void VaapiVideoDecoder::GetCurrentComputePartition(std::vector<ComputePartition>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VaapiVideoDecoder::GetDrmNodeOffset(std::string device_name, uint8_t device_id, std::vector<int>& visible_devices,
|
void VaContext::GetDrmNodeOffset(std::string device_name, uint8_t device_id, std::vector<int>& visible_devices, std::vector<ComputePartition> ¤t_compute_partitions, int &offset) {
|
||||||
std::vector<ComputePartition> ¤t_compute_partitions, int &offset) {
|
|
||||||
|
|
||||||
if (!current_compute_partitions.empty()) {
|
if (!current_compute_partitions.empty()) {
|
||||||
switch (current_compute_partitions[0]) {
|
switch (current_compute_partitions[0]) {
|
||||||
case kSpx:
|
case kSpx:
|
||||||
@@ -638,7 +939,7 @@ void VaapiVideoDecoder::GetDrmNodeOffset(std::string device_name, uint8_t device
|
|||||||
* UUID from the corresponding sysfs path. It maps each unique GPU UUID to its
|
* UUID from the corresponding sysfs path. It maps each unique GPU UUID to its
|
||||||
* corresponding render node ID and stores this mapping in the gpu_uuids_to_render_nodes_map_.
|
* corresponding render node ID and stores this mapping in the gpu_uuids_to_render_nodes_map_.
|
||||||
*/
|
*/
|
||||||
void VaapiVideoDecoder::GetGpuUuids() {
|
void VaContext::GetGpuUuids() {
|
||||||
std::string dri_path = "/dev/dri";
|
std::string dri_path = "/dev/dri";
|
||||||
// Iterate through all render nodes
|
// Iterate through all render nodes
|
||||||
for (const auto& entry : fs::directory_iterator(dri_path, fs::directory_options::skip_permission_denied)) {
|
for (const auto& entry : fs::directory_iterator(dri_path, fs::directory_options::skip_permission_denied)) {
|
||||||
|
|||||||
@@ -29,6 +29,9 @@ THE SOFTWARE.
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <mutex>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <unordered_map>
|
||||||
#if __cplusplus >= 201703L && __has_include(<filesystem>)
|
#if __cplusplus >= 201703L && __has_include(<filesystem>)
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
@@ -36,13 +39,22 @@ THE SOFTWARE.
|
|||||||
#include <experimental/filesystem>
|
#include <experimental/filesystem>
|
||||||
namespace fs = std::experimental::filesystem;
|
namespace fs = std::experimental::filesystem;
|
||||||
#endif
|
#endif
|
||||||
|
#include <libdrm/amdgpu_drm.h>
|
||||||
|
#include <libdrm/amdgpu.h>
|
||||||
#include <va/va.h>
|
#include <va/va.h>
|
||||||
#include <va/va_drm.h>
|
#include <va/va_drm.h>
|
||||||
#include <va/va_drmcommon.h>
|
#include <va/va_drmcommon.h>
|
||||||
#include "../roc_decoder_caps.h"
|
|
||||||
#include "../../commons.h"
|
#include "../../commons.h"
|
||||||
#include "../../../api/rocdecode.h"
|
#include "../../../api/rocdecode.h"
|
||||||
|
|
||||||
|
#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;\
|
||||||
|
return ROCDEC_RUNTIME_ERROR;\
|
||||||
|
}\
|
||||||
|
}
|
||||||
|
|
||||||
#define CHECK_VAAPI(call) {\
|
#define CHECK_VAAPI(call) {\
|
||||||
VAStatus va_status = call;\
|
VAStatus va_status = call;\
|
||||||
if (va_status != VA_STATUS_SUCCESS) {\
|
if (va_status != VA_STATUS_SUCCESS) {\
|
||||||
@@ -61,23 +73,44 @@ typedef enum {
|
|||||||
kCpx = 4, // Core Partition Accelerator
|
kCpx = 4, // Core Partition Accelerator
|
||||||
} ComputePartition;
|
} ComputePartition;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int device_id;
|
||||||
|
std::string gpu_uuid;
|
||||||
|
int drm_fd;
|
||||||
|
VADisplay va_display;
|
||||||
|
hipDeviceProp_t hip_dev_prop;
|
||||||
|
uint32_t num_dec_engines;
|
||||||
|
int num_va_profiles;
|
||||||
|
std::vector<VAProfile> va_profile_list; // supported profiles by the current GPU
|
||||||
|
VAProfile va_profile; // current profile used
|
||||||
|
VAConfigID va_config_id;
|
||||||
|
bool config_attributes_probed;
|
||||||
|
uint32_t rt_format_attrib;
|
||||||
|
uint32_t output_format_mask;
|
||||||
|
uint32_t max_width;
|
||||||
|
uint32_t max_height;
|
||||||
|
uint32_t min_width;
|
||||||
|
uint32_t min_height;
|
||||||
|
} VaContextInfo;
|
||||||
|
|
||||||
class VaapiVideoDecoder {
|
class VaapiVideoDecoder {
|
||||||
public:
|
public:
|
||||||
VaapiVideoDecoder(RocDecoderCreateInfo &decoder_create_info);
|
VaapiVideoDecoder(RocDecoderCreateInfo &decoder_create_info);
|
||||||
~VaapiVideoDecoder();
|
~VaapiVideoDecoder();
|
||||||
rocDecStatus InitializeDecoder(std::string device_name, std::string gcn_arch_name, std::string& gpu_uuid);
|
rocDecStatus InitializeDecoder();
|
||||||
rocDecStatus SubmitDecode(RocdecPicParams *pPicParams);
|
rocDecStatus SubmitDecode(RocdecPicParams *pPicParams);
|
||||||
rocDecStatus GetDecodeStatus(int pic_idx, RocdecDecodeStatus* decode_status);
|
rocDecStatus GetDecodeStatus(int pic_idx, RocdecDecodeStatus* decode_status);
|
||||||
rocDecStatus ExportSurface(int pic_idx, VADRMPRIMESurfaceDescriptor &va_drm_prime_surface_desc);
|
rocDecStatus ExportSurface(int pic_idx, VADRMPRIMESurfaceDescriptor &va_drm_prime_surface_desc);
|
||||||
rocDecStatus SyncSurface(int pic_idx);
|
rocDecStatus SyncSurface(int pic_idx);
|
||||||
rocDecStatus ReconfigureDecoder(RocdecReconfigureDecoderInfo *reconfig_params);
|
rocDecStatus ReconfigureDecoder(RocdecReconfigureDecoderInfo *reconfig_params);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RocDecoderCreateInfo decoder_create_info_;
|
RocDecoderCreateInfo decoder_create_info_;
|
||||||
int drm_fd_;
|
int drm_fd_;
|
||||||
VADisplay va_display_;
|
VADisplay va_display_;
|
||||||
|
VAProfile va_profile_;
|
||||||
VAConfigAttrib va_config_attrib_;
|
VAConfigAttrib va_config_attrib_;
|
||||||
VAConfigID va_config_id_;
|
VAConfigID va_config_id_;
|
||||||
VAProfile va_profile_;
|
|
||||||
VAContextID va_context_id_;
|
VAContextID va_context_id_;
|
||||||
std::vector<VASurfaceID> va_surface_ids_;
|
std::vector<VASurfaceID> va_surface_ids_;
|
||||||
bool supports_modifiers_;
|
bool supports_modifiers_;
|
||||||
@@ -88,6 +121,30 @@ private:
|
|||||||
uint32_t num_slices_;
|
uint32_t num_slices_;
|
||||||
VABufferID slice_data_buf_id_;
|
VABufferID slice_data_buf_id_;
|
||||||
uint32_t slice_data_buf_size_;
|
uint32_t slice_data_buf_size_;
|
||||||
|
|
||||||
|
bool IsCodecConfigSupported(int device_id, rocDecVideoCodec codec_type, rocDecVideoChromaFormat chroma_format, uint32_t bit_depth_minus8, rocDecVideoSurfaceFormat output_format);
|
||||||
|
rocDecStatus CreateDecoderConfig();
|
||||||
|
rocDecStatus CreateSurfaces();
|
||||||
|
rocDecStatus CreateContext();
|
||||||
|
rocDecStatus DestroyDataBuffers();
|
||||||
|
};
|
||||||
|
|
||||||
|
// The VaContext singleton class providing access to the the GPU VA services
|
||||||
|
class VaContext {
|
||||||
|
public:
|
||||||
|
int num_devices_;
|
||||||
|
std::vector<VaContextInfo> va_contexts_;
|
||||||
|
|
||||||
|
static VaContext& GetInstance() {
|
||||||
|
static VaContext instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
rocDecStatus GetVaContext(int device_id, uint32_t *va_ctx_id);
|
||||||
|
rocDecStatus GetVaDisplay(uint32_t va_ctx_id, VADisplay *va_display);
|
||||||
|
rocDecStatus CheckDecCapForCodecType(RocdecDecodeCaps *dec_cap);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::mutex mutex;
|
||||||
/**
|
/**
|
||||||
* @brief A map that associates GPU UUIDs with their corresponding render node indices.
|
* @brief A map that associates GPU UUIDs with their corresponding render node indices.
|
||||||
*
|
*
|
||||||
@@ -97,14 +154,15 @@ private:
|
|||||||
*/
|
*/
|
||||||
std::unordered_map<std::string, int> gpu_uuids_to_render_nodes_map_;
|
std::unordered_map<std::string, int> gpu_uuids_to_render_nodes_map_;
|
||||||
|
|
||||||
rocDecStatus InitVAAPI(std::string drm_node);
|
VaContext();
|
||||||
rocDecStatus CreateDecoderConfig();
|
VaContext(const VaContext&) = delete;
|
||||||
rocDecStatus CreateSurfaces();
|
VaContext& operator = (const VaContext) = delete;
|
||||||
rocDecStatus CreateContext();
|
~VaContext();
|
||||||
rocDecStatus DestroyDataBuffers();
|
|
||||||
|
rocDecStatus InitHIP(int device_id, hipDeviceProp_t& hip_dev_prop);
|
||||||
|
rocDecStatus InitVAAPI(int va_ctx_idx, std::string drm_node);
|
||||||
|
void GetVisibleDevices(std::vector<int>& visible_devices_vetor);
|
||||||
|
void GetCurrentComputePartition(std::vector<ComputePartition> ¤t_compute_partitions);
|
||||||
|
void GetDrmNodeOffset(std::string device_name, uint8_t device_id, std::vector<int>& visible_devices, std::vector<ComputePartition> ¤t_compute_partitions, int &offset);
|
||||||
void GetGpuUuids();
|
void GetGpuUuids();
|
||||||
void GetVisibleDevices(std::vector<int>& visible_devices);
|
|
||||||
void GetCurrentComputePartition(std::vector<ComputePartition> &currnet_compute_partitions);
|
|
||||||
void GetDrmNodeOffset(std::string device_name, uint8_t device_id, std::vector<int>& visible_devices,
|
|
||||||
std::vector<ComputePartition> ¤t_compute_partitions, int &offset);
|
|
||||||
};
|
};
|
||||||
@@ -26,7 +26,6 @@ RocVideoDecoder::RocVideoDecoder(int device_id, OutputSurfaceMemoryType out_mem_
|
|||||||
const Rect *p_crop_rect, bool extract_user_sei_Message, uint32_t disp_delay, int max_width, int max_height, uint32_t clk_rate) :
|
const Rect *p_crop_rect, bool extract_user_sei_Message, uint32_t disp_delay, int max_width, int max_height, uint32_t clk_rate) :
|
||||||
device_id_{device_id}, out_mem_type_(out_mem_type), codec_id_(codec), b_force_zero_latency_(force_zero_latency),
|
device_id_{device_id}, out_mem_type_(out_mem_type), codec_id_(codec), b_force_zero_latency_(force_zero_latency),
|
||||||
b_extract_sei_message_(extract_user_sei_Message), disp_delay_(disp_delay), max_width_ (max_width), max_height_(max_height) {
|
b_extract_sei_message_(extract_user_sei_Message), disp_delay_(disp_delay), max_width_ (max_width), max_height_(max_height) {
|
||||||
|
|
||||||
if (!InitHIP(device_id_)) {
|
if (!InitHIP(device_id_)) {
|
||||||
THROW("Failed to initilize the HIP");
|
THROW("Failed to initilize the HIP");
|
||||||
}
|
}
|
||||||
@@ -1059,10 +1058,11 @@ bool RocVideoDecoder::CodecSupported(int device_id, rocDecVideoCodec codec_id, u
|
|||||||
decode_caps.codec_type = codec_id;
|
decode_caps.codec_type = codec_id;
|
||||||
decode_caps.chroma_format = rocDecVideoChromaFormat_420;
|
decode_caps.chroma_format = rocDecVideoChromaFormat_420;
|
||||||
decode_caps.bit_depth_minus_8 = bit_depth - 8;
|
decode_caps.bit_depth_minus_8 = bit_depth - 8;
|
||||||
if(rocDecGetDecoderCaps(&decode_caps) != ROCDEC_SUCCESS) {
|
if((rocDecGetDecoderCaps(&decode_caps) != ROCDEC_SUCCESS) || !decode_caps.is_supported) {
|
||||||
return false;
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RocVideoDecoder::WaitForDecodeCompletion() {
|
void RocVideoDecoder::WaitForDecodeCompletion() {
|
||||||
|
|||||||
In neuem Issue referenzieren
Einen Benutzer sperren