Add support for rocDecCreateDecoder API (#28)
* Add support for rocDecCreateDecoder API
* check the decoder config support before initializing the vaapi
* rename RocdecDecoderCreateInfo to RocDecoderCreateInfo
* fix a typo
[ROCm/rocdecode commit: 32f854c159]
This commit is contained in:
@@ -102,7 +102,7 @@ typedef enum rocDecVideoCodec_enum {
|
||||
/*********************************************************************************/
|
||||
//! \enum rocDecVideoSurfaceFormat
|
||||
//! Video surface format enums used for output format of decoded output
|
||||
//! These enums are used in RocdecDecoderCreateInfo structure
|
||||
//! These enums are used in RocDecoderCreateInfo structure
|
||||
/*********************************************************************************/
|
||||
typedef enum rocDecVideoSurfaceFormat_enum {
|
||||
rocDecVideoSurfaceFormat_NV12=0, /**< Semi-Planar YUV [Y plane followed by interleaved UV plane] */
|
||||
@@ -163,10 +163,12 @@ typedef struct _RocdecDecodeCaps {
|
||||
} RocdecDecodeCaps;
|
||||
|
||||
/**************************************************************************************************************/
|
||||
//! \struct RocdecDecoderCreateInfo
|
||||
//! \struct RocDecoderCreateInfo
|
||||
//! This structure is used in rocDecCreateDecoder API
|
||||
/**************************************************************************************************************/
|
||||
typedef struct _RocdecDecoderCreateInfo {
|
||||
typedef struct _RocDecoderCreateInfo {
|
||||
uint8_t deviceid; /**< IN: the device id for which a decoder should be created
|
||||
0 for the first device, 1 for the second device on the system, etc.*/
|
||||
uint32_t ulWidth; /**< IN: Coded sequence width in pixels */
|
||||
uint32_t ulHeight; /**< IN: Coded sequence height in pixels */
|
||||
uint32_t ulNumDecodeSurfaces; /**< IN: Maximum number of internal decode surfaces */
|
||||
@@ -207,7 +209,7 @@ typedef struct _RocdecDecoderCreateInfo {
|
||||
} target_rect;
|
||||
|
||||
uint32_t Reserved2[4]; /**< Reserved for future use - set to zero */
|
||||
} RocdecDecoderCreateInfo;
|
||||
} RocDecoderCreateInfo;
|
||||
|
||||
/*********************************************************************************************************/
|
||||
//! \struct RocdecDecodeStatus
|
||||
@@ -226,8 +228,8 @@ typedef struct _RocdecDecodeStatus {
|
||||
//! This structure is used in rocDecReconfigureDecoder() API
|
||||
/****************************************************/
|
||||
typedef struct _RocdecReconfigureDecoderInfo {
|
||||
uint32_t ulWidth; /**< IN: Coded sequence width in pixels, MUST be < = ulMaxWidth defined at RocdecDecoderCreateInfo */
|
||||
uint32_t ulHeight; /**< IN: Coded sequence height in pixels, MUST be < = ulMaxHeight defined at RocdecDecoderCreateInfo */
|
||||
uint32_t ulWidth; /**< IN: Coded sequence width in pixels, MUST be < = ulMaxWidth defined at RocDecoderCreateInfo */
|
||||
uint32_t ulHeight; /**< IN: Coded sequence height in pixels, MUST be < = ulMaxHeight defined at RocDecoderCreateInfo */
|
||||
uint32_t ulTargetWidth; /**< IN: Post processed output width */
|
||||
uint32_t ulTargetHeight; /**< IN: Post Processed output height */
|
||||
uint32_t ulNumDecodeSurfaces; /**< IN: Maximum number of internal decode surfaces */
|
||||
@@ -701,10 +703,10 @@ typedef struct _RocdecProcParams
|
||||
/***********************************************************************************************************/
|
||||
|
||||
/*****************************************************************************************************/
|
||||
//! \fn rocDecStatus ROCDECAPI rocDecCreateDecoder(rocDecDecoderHandle *phDecoder, RocdecDecoderCreateInfo *pdci)
|
||||
//! \fn rocDecStatus ROCDECAPI rocDecCreateDecoder(rocDecDecoderHandle *phDecoder, RocDecoderCreateInfo *pdci)
|
||||
//! Create the decoder object based on pdci. A handle to the created decoder is returned
|
||||
/*****************************************************************************************************/
|
||||
extern rocDecStatus ROCDECAPI rocDecCreateDecoder(rocDecDecoderHandle *phDecoder, RocdecDecoderCreateInfo *pdci);
|
||||
extern rocDecStatus ROCDECAPI rocDecCreateDecoder(rocDecDecoderHandle *phDecoder, RocDecoderCreateInfo *pdci);
|
||||
|
||||
/*****************************************************************************************************/
|
||||
//! \fn rocDecStatus ROCDECAPI rocDecDestroyDecoder(rocDecDecoderHandle hDecoder)
|
||||
|
||||
@@ -32,7 +32,7 @@ THE SOFTWARE.
|
||||
*/
|
||||
struct DecHandle {
|
||||
|
||||
explicit DecHandle() : roc_decoder(std::make_shared<RocDecoder>()) {}; //constructor
|
||||
explicit DecHandle(RocDecoderCreateInfo& decoder_create_info) : roc_decoder(std::make_shared<RocDecoder>(decoder_create_info)) {}; //constructor
|
||||
~DecHandle() { clear_errors(); }
|
||||
std::shared_ptr<RocDecoder> roc_decoder; // class instantiation
|
||||
bool no_error() { return error.empty(); }
|
||||
|
||||
@@ -23,14 +23,7 @@ THE SOFTWARE.
|
||||
#include "../commons.h"
|
||||
#include "roc_decoder.h"
|
||||
|
||||
RocDecoder::RocDecoder(int device_id):device_id_ {device_id}, num_devices_{0} {
|
||||
// todo::
|
||||
if (ROCDEC_SUCCESS != initHIP(device_id_)) {
|
||||
THROW("Failed to initilize the HIP");
|
||||
}
|
||||
initDRMnodes();
|
||||
|
||||
}
|
||||
RocDecoder::RocDecoder(RocDecoderCreateInfo& decoder_create_info): va_video_decoder_{decoder_create_info}, device_id_{decoder_create_info.deviceid} {}
|
||||
|
||||
RocDecoder::~RocDecoder() {
|
||||
// todo::
|
||||
@@ -43,6 +36,23 @@ RocDecoder::RocDecoder(int device_id):device_id_ {device_id}, num_devices_{0} {
|
||||
}
|
||||
}
|
||||
|
||||
rocDecStatus RocDecoder::InitializeDecoder() {
|
||||
rocDecStatus rocdec_status = ROCDEC_SUCCESS;
|
||||
rocdec_status = InitHIP(device_id_);
|
||||
if (rocdec_status != ROCDEC_SUCCESS) {
|
||||
ERR("ERROR: Failed to initilize the HIP!" + TOSTR(rocdec_status));
|
||||
return rocdec_status;
|
||||
}
|
||||
|
||||
rocdec_status = va_video_decoder_.InitializeDecoder(hip_dev_prop_.gcnArchName);
|
||||
if (rocdec_status != ROCDEC_SUCCESS) {
|
||||
ERR("ERROR: Failed to initilize the VAAPI Video decoder!" + TOSTR(rocdec_status));
|
||||
return rocdec_status;
|
||||
}
|
||||
|
||||
return rocdec_status;
|
||||
}
|
||||
|
||||
rocDecStatus RocDecoder::decodeFrame(RocdecPicParams *pPicParams) {
|
||||
// todo:: return appropriate decStatus if fails
|
||||
// call funsction to do va-api decoding using the picture parameters structure
|
||||
@@ -80,7 +90,7 @@ rocDecStatus RocDecoder::unMapVideoFrame(void *pMappedDevPtr) {
|
||||
}
|
||||
|
||||
|
||||
rocDecStatus RocDecoder::initHIP(int device_id) {
|
||||
rocDecStatus RocDecoder::InitHIP(int device_id) {
|
||||
hipError_t hipStatus = hipSuccess;
|
||||
hipStatus = hipGetDeviceCount(&num_devices_);
|
||||
rocDecStatus decStatus = ROCDEC_SUCCESS;
|
||||
@@ -115,11 +125,3 @@ rocDecStatus RocDecoder::initHIP(int device_id) {
|
||||
}
|
||||
return decStatus;
|
||||
}
|
||||
|
||||
void RocDecoder::initDRMnodes() {
|
||||
// build the DRM render node names
|
||||
for (int i = 0; i < num_devices_; i++) {
|
||||
drm_nodes_.push_back("/dev/dri/renderD" + std::to_string(128 + i));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,11 +32,13 @@ THE SOFTWARE.
|
||||
#include <map>
|
||||
#include "../api/rocdecode.h"
|
||||
#include <hip/hip_runtime.h>
|
||||
#include "vaapi/vaapi_videodecoder.h"
|
||||
|
||||
class RocDecoder {
|
||||
public:
|
||||
RocDecoder(int device_id = 0);
|
||||
RocDecoder(RocDecoderCreateInfo &decoder_create_info);
|
||||
~RocDecoder();
|
||||
rocDecStatus InitializeDecoder();
|
||||
rocDecStatus decodeFrame(RocdecPicParams *pPicParams);
|
||||
rocDecStatus getDecodeStatus(int nPicIdx, RocdecDecodeStatus* pDecodeStatus);
|
||||
rocDecStatus reconfigureDecoder(RocdecReconfigureDecoderInfo *pDecReconfigParams);
|
||||
@@ -44,11 +46,10 @@ public:
|
||||
rocDecStatus unMapVideoFrame(void *pMappedDevPtr);
|
||||
|
||||
private:
|
||||
rocDecStatus initHIP(int device_id);
|
||||
void initDRMnodes();
|
||||
rocDecStatus InitHIP(int device_id);
|
||||
int num_devices_;
|
||||
int device_id_;
|
||||
VaapiVideoDecoder va_video_decoder_;
|
||||
hipDeviceProp_t hip_dev_prop_;
|
||||
hipStream_t hip_stream_;
|
||||
std::vector<std::string> drm_nodes_;
|
||||
};
|
||||
@@ -49,7 +49,7 @@ struct VcnCodecsSpec {
|
||||
// The RocDecVcnCodecSpec singleton class for providing access to the the vcn_spec_table
|
||||
class RocDecVcnCodecSpec {
|
||||
public:
|
||||
static RocDecVcnCodecSpec& GetInastance() {
|
||||
static RocDecVcnCodecSpec& GetInstance() {
|
||||
static RocDecVcnCodecSpec instance;
|
||||
return instance;
|
||||
}
|
||||
@@ -82,6 +82,28 @@ public:
|
||||
return ROCDEC_DEVICE_INVALID;
|
||||
}
|
||||
}
|
||||
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);
|
||||
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(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;
|
||||
|
||||
@@ -26,20 +26,21 @@ THE SOFTWARE.
|
||||
|
||||
|
||||
/*****************************************************************************************************/
|
||||
//! \fn rocDecStatus ROCDECAPI rocDecCreateDecoder(rocDecDecoderHandle *phDecoder, RocdecDecoderCreateInfo *pdci)
|
||||
//! \fn rocDecStatus ROCDECAPI rocDecCreateDecoder(rocDecDecoderHandle *phDecoder, RocDecoderCreateInfo *pdci)
|
||||
//! Create the decoder object based on pdci. A handle to the created decoder is returned
|
||||
/*****************************************************************************************************/
|
||||
rocDecStatus ROCDECAPI
|
||||
rocDecCreateDecoder(rocDecDecoderHandle *phDecoder, RocdecDecoderCreateInfo *pdci) {
|
||||
rocDecCreateDecoder(rocDecDecoderHandle *phDecoder, RocDecoderCreateInfo *pdci) {
|
||||
rocDecDecoderHandle handle = nullptr;
|
||||
try {
|
||||
handle = new DecHandle();
|
||||
handle = new DecHandle(*pdci);
|
||||
}
|
||||
catch(const std::exception& e) {
|
||||
ERR( STR("Failed to init the rocDecode handle, ") + STR(e.what()))
|
||||
return ROCDEC_NOT_INITIALIZED;
|
||||
}
|
||||
*phDecoder = handle;
|
||||
return ROCDEC_SUCCESS;
|
||||
return static_cast<DecHandle *>(handle)->roc_decoder->InitializeDecoder();
|
||||
}
|
||||
|
||||
/*****************************************************************************************************/
|
||||
@@ -87,7 +88,7 @@ rocDecGetDecoderCaps(RocdecDecodeCaps *pdc) {
|
||||
return ROCDEC_DEVICE_INVALID;
|
||||
}
|
||||
|
||||
RocDecVcnCodecSpec& vcn_codec_spec = RocDecVcnCodecSpec::GetInastance();
|
||||
RocDecVcnCodecSpec& vcn_codec_spec = RocDecVcnCodecSpec::GetInstance();
|
||||
return vcn_codec_spec.GetDecoderCaps(hip_dev_prop.gcnArchName, pdc);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,13 +20,77 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string.h>
|
||||
|
||||
#include "../commons.h"
|
||||
#include "vaapi_videodecoder.h"
|
||||
|
||||
VaapiVideoDecoder::VaapiVideoDecoder(RocDecoderCreateInfo &decoder_create_info) : decoder_create_info_{decoder_create_info},
|
||||
drm_fd_{-1}, va_display_{0}, va_config_attrib_{{}}, va_config_id_{0}, va_profile_ {VAProfileNone} {};
|
||||
|
||||
VaapiVideoDecoder::~VaapiVideoDecoder() {
|
||||
if (drm_fd_ != -1) {
|
||||
close(drm_fd_);
|
||||
}
|
||||
if (va_display_) {
|
||||
if (va_config_id_)
|
||||
vaDestroyConfig(va_display_, va_config_id_);
|
||||
vaTerminate(va_display_);
|
||||
}
|
||||
}
|
||||
|
||||
rocDecStatus VaapiVideoDecoder::InitializeDecoder(std::string gcn_arch_name) {
|
||||
rocDecStatus rocdec_status = ROCDEC_SUCCESS;
|
||||
|
||||
//Before initializing the VAAPI, first check to see if the requested codec config is supported
|
||||
RocDecVcnCodecSpec& vcn_codec_spec = RocDecVcnCodecSpec::GetInstance();
|
||||
if (!vcn_codec_spec.IsCodecConfigSupported(gcn_arch_name, decoder_create_info_.CodecType, decoder_create_info_.ChromaFormat,
|
||||
decoder_create_info_.bitDepthMinus8, decoder_create_info_.OutputFormat)) {
|
||||
ERR("ERROR: the codec config combination is not supported!");
|
||||
return ROCDEC_NOT_SUPPORTED;
|
||||
}
|
||||
rocdec_status = InitVAAPI();
|
||||
if (rocdec_status != ROCDEC_SUCCESS) {
|
||||
ERR("ERROR: Failed to initilize the VAAPI!" + TOSTR(rocdec_status));
|
||||
return rocdec_status;
|
||||
}
|
||||
rocdec_status = CreateDecoderConfig();
|
||||
if (rocdec_status != ROCDEC_SUCCESS) {
|
||||
ERR("ERROR: Failed to create a VAAPI decoder configuration" + TOSTR(rocdec_status));
|
||||
return rocdec_status;
|
||||
}
|
||||
return rocdec_status;
|
||||
}
|
||||
|
||||
rocDecStatus VaapiVideoDecoder::InitVAAPI() {
|
||||
std::string drm_node = "/dev/dri/renderD" + std::to_string(128 + decoder_create_info_.deviceid);
|
||||
drm_fd_ = open(drm_node.c_str(), O_RDWR);
|
||||
if (drm_fd_ < 0) {
|
||||
ERR("ERROR: failed to open drm node " + drm_node);
|
||||
return ROCDEC_NOT_INITIALIZED;
|
||||
}
|
||||
va_display_ = vaGetDisplayDRM(drm_fd_);
|
||||
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_.CodecType) {
|
||||
case rocDecVideoCodec_HEVC:
|
||||
if (decoder_create_info_.bitDepthMinus8 == 0) {
|
||||
va_profile_ = VAProfileHEVCMain;
|
||||
} else if (decoder_create_info_.bitDepthMinus8 == 2) {
|
||||
va_profile_ = VAProfileHEVCMain10;
|
||||
}
|
||||
break;
|
||||
case rocDecVideoCodec_H264:
|
||||
va_profile_ = VAProfileH264Main;
|
||||
break;
|
||||
default:
|
||||
ERR("ERROR: 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_));
|
||||
return ROCDEC_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -22,38 +22,39 @@ THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <va/va.h>
|
||||
#include <va/va_drm.h>
|
||||
#include <va/va_drmcommon.h>
|
||||
#include "../roc_decoder_caps.h"
|
||||
#include "../../commons.h"
|
||||
#include "../../../api/rocdecode.h"
|
||||
|
||||
// class implementing highlevel vaapi decoder
|
||||
/***********************************************************************************************************/
|
||||
//! requirement is as follows
|
||||
//!
|
||||
//! In order to minimize decode latencies, there should be always at least enough pictures (min 2) in the decode
|
||||
//! queue at any time, in order to make sure that all VCN decode engines are always busy.
|
||||
//! In addition to the reqular create and destroy: the decoder needs to have a task-Q for submitting decoding jobs from the high level
|
||||
//!
|
||||
//! Overall data flow:
|
||||
//! - GetCaps(...)
|
||||
//! - CreateVideoDecoder(...)
|
||||
//! - For each picture:
|
||||
//! + submitDecodeTask(0) /* submit first frame for decoding */
|
||||
//! + ... /* submit next frame for decoding */
|
||||
//! + submitDecodeTask(N) /* N is determined based on available HW decode engines in the system */
|
||||
//!
|
||||
//! + QueryStatus(N-4) /* Query the decode status of N-4 frame */
|
||||
//! + MapVideoFrame(N-4)
|
||||
//! + do some processing in HIP
|
||||
//! + UnmapVideoFrame(N-4)
|
||||
//! + submitDecodeTask(N+1)
|
||||
//! + MapVideoFrame(N-3)
|
||||
//! + ...
|
||||
//! - DestroyVideoDecoder(...)
|
||||
//!
|
||||
//! NOTE:
|
||||
//! - The decoder has to maintain a Q for decode jobs with associated picture buffers
|
||||
//! - An intenal thread has to pick up the next available job: If none wait for the Q to fill
|
||||
/***********************************************************************************************************/
|
||||
|
||||
class vaapiVideoDecoder {
|
||||
#define CHECK_VAAPI(call) { \
|
||||
VAStatus va_status = (call); \
|
||||
if (va_status != VA_STATUS_SUCCESS) { \
|
||||
std::cout << "VAAPI failure: 'status#" << va_status << "' at " << __FILE__ << ":" << __LINE__ << std::endl;\
|
||||
return ROCDEC_RUNTIME_ERROR; \
|
||||
} \
|
||||
}
|
||||
|
||||
class VaapiVideoDecoder {
|
||||
public:
|
||||
|
||||
VaapiVideoDecoder(RocDecoderCreateInfo &decoder_create_info);
|
||||
~VaapiVideoDecoder();
|
||||
rocDecStatus InitializeDecoder(std::string gcn_arch_name);
|
||||
private:
|
||||
RocDecoderCreateInfo decoder_create_info_;
|
||||
int drm_fd_;
|
||||
VADisplay va_display_;
|
||||
VAConfigAttrib va_config_attrib_;
|
||||
VAConfigID va_config_id_;
|
||||
VAProfile va_profile_;
|
||||
rocDecStatus InitVAAPI();
|
||||
rocDecStatus CreateDecoderConfig();
|
||||
};
|
||||
@@ -257,7 +257,7 @@ int RocVideoDecoder::HandleVideoSequence(RocdecVideoFormat *pVideoFormat) {
|
||||
}
|
||||
video_format_ = *pVideoFormat;
|
||||
|
||||
RocdecDecoderCreateInfo videoDecodeCreateInfo = { 0 };
|
||||
RocDecoderCreateInfo videoDecodeCreateInfo = { 0 };
|
||||
videoDecodeCreateInfo.CodecType = pVideoFormat->codec;
|
||||
videoDecodeCreateInfo.ChromaFormat = pVideoFormat->chroma_format;
|
||||
videoDecodeCreateInfo.OutputFormat = video_surface_format_;
|
||||
|
||||
مرجع در شماره جدید
Block a user