From 7a90c0c05404d224fc9e0833a0abbbecf77a3e30 Mon Sep 17 00:00:00 2001 From: Aryan Salmanpour Date: Fri, 10 Nov 2023 17:02:57 -0500 Subject: [PATCH] Add support for rocDecMapVideoFrame API (#53) --- src/rocdecode/roc_decoder.cpp | 47 ++++++++++++++++++---- src/rocdecode/roc_decoder.h | 13 +++++- src/rocdecode/vaapi/vaapi_videodecoder.cpp | 14 +++++++ src/rocdecode/vaapi/vaapi_videodecoder.h | 2 + 4 files changed, 66 insertions(+), 10 deletions(-) diff --git a/src/rocdecode/roc_decoder.cpp b/src/rocdecode/roc_decoder.cpp index 78ba95e220..8791ccc0c1 100644 --- a/src/rocdecode/roc_decoder.cpp +++ b/src/rocdecode/roc_decoder.cpp @@ -23,7 +23,7 @@ THE SOFTWARE. #include "../commons.h" #include "roc_decoder.h" -RocDecoder::RocDecoder(RocDecoderCreateInfo& decoder_create_info): va_video_decoder_{decoder_create_info}, device_id_{decoder_create_info.deviceid} {} +RocDecoder::RocDecoder(RocDecoderCreateInfo& decoder_create_info): va_video_decoder_{decoder_create_info}, decoder_create_info_{decoder_create_info} {} RocDecoder::~RocDecoder() { // todo:: @@ -38,11 +38,16 @@ RocDecoder::RocDecoder(RocDecoderCreateInfo& decoder_create_info): va_video_deco rocDecStatus RocDecoder::InitializeDecoder() { rocDecStatus rocdec_status = ROCDEC_SUCCESS; - rocdec_status = InitHIP(device_id_); + rocdec_status = InitHIP(decoder_create_info_.deviceid); if (rocdec_status != ROCDEC_SUCCESS) { ERR("ERROR: Failed to initilize the HIP!" + TOSTR(rocdec_status)); return rocdec_status; } + if (decoder_create_info_.ulNumDecodeSurfaces < 1) { + ERR("ERROR: invalid number of decode surfaces "); + return ROCDEC_INVALID_PARAMETER; + } + hip_ext_mem_.resize(decoder_create_info_.ulNumDecodeSurfaces); rocdec_status = va_video_decoder_.InitializeDecoder(hip_dev_prop_.gcnArchName); if (rocdec_status != ROCDEC_SUCCESS) { @@ -80,12 +85,38 @@ rocDecStatus RocDecoder::reconfigureDecoder(RocdecReconfigureDecoderInfo *pDecRe return ROCDEC_NOT_IMPLEMENTED; } -rocDecStatus RocDecoder::mapVideoFrame(int nPicIdx, void *pDevMemPtr[3], - unsigned int pHorizontalPitch[3], RocdecProcParams *pVidPostprocParams) { - // todo:: return appropriate decStatus - // Post-process and map video frame corresponding to nPicIdx for use in HIP. Returns HIP device pointer and associated - // pitch(horizontal stride) of the video frame. Returns device memory pointers for each plane (Y, U and V) seperately - return ROCDEC_NOT_IMPLEMENTED; +rocDecStatus RocDecoder::mapVideoFrame(int pic_idx, void *dev_mem_ptr[3], + unsigned int horizontal_pitch[3], RocdecProcParams *vid_postproc_params) { + if (pic_idx >= hip_ext_mem_.size() || &dev_mem_ptr[0] == nullptr || vid_postproc_params == nullptr) { + return ROCDEC_INVALID_PARAMETER; + } + rocDecStatus rocdec_status = ROCDEC_SUCCESS; + hipExternalMemoryHandleDesc external_mem_handle_desc_ = {}; + hipExternalMemoryBufferDesc external_mem_buffer_desc_ = {}; + VADRMPRIMESurfaceDescriptor va_drm_prime_surface_desc = {}; + + rocdec_status = va_video_decoder_.ExportSurface(pic_idx, va_drm_prime_surface_desc); + if (rocdec_status != ROCDEC_SUCCESS) { + ERR("ERROR: Failed to export surface for picture id" + TOSTR(pic_idx) + TOSTR(rocdec_status)); + } + + external_mem_handle_desc_.type = hipExternalMemoryHandleTypeOpaqueFd; + external_mem_handle_desc_.handle.fd = va_drm_prime_surface_desc.objects[0].fd; + external_mem_handle_desc_.size = va_drm_prime_surface_desc.objects[0].size; + CHECK_HIP(hipImportExternalMemory(&hip_ext_mem_[pic_idx], &external_mem_handle_desc_)); + + external_mem_buffer_desc_.size = va_drm_prime_surface_desc.objects[0].size; + CHECK_HIP(hipExternalMemoryGetMappedBuffer(&*&dev_mem_ptr[0], hip_ext_mem_[pic_idx], &external_mem_buffer_desc_)); + horizontal_pitch[0] = va_drm_prime_surface_desc.layers[0].pitch[0]; + if (va_drm_prime_surface_desc.num_layers == 2) { + *&dev_mem_ptr[1] = static_cast(*&dev_mem_ptr[0]) + va_drm_prime_surface_desc.layers[1].offset[0]; + horizontal_pitch[1] = va_drm_prime_surface_desc.layers[1].pitch[0]; + } else if (va_drm_prime_surface_desc.num_layers == 3) { + *&dev_mem_ptr[2] = static_cast(*&dev_mem_ptr[0]) + va_drm_prime_surface_desc.layers[2].offset[0]; + horizontal_pitch[2] = va_drm_prime_surface_desc.layers[2].pitch[0]; + } + + return rocdec_status; } rocDecStatus RocDecoder::unMapVideoFrame(void *pMappedDevPtr) { diff --git a/src/rocdecode/roc_decoder.h b/src/rocdecode/roc_decoder.h index 6c756ef290..6066cf8bd2 100644 --- a/src/rocdecode/roc_decoder.h +++ b/src/rocdecode/roc_decoder.h @@ -34,6 +34,14 @@ THE SOFTWARE. #include #include "vaapi/vaapi_videodecoder.h" +#define CHECK_HIP(call) { \ + hipError_t hip_status = call; \ + if (hip_status != hipSuccess) { \ + std::cout << "HIP failure: 'status#" << hip_status << "' at " << __FILE__ << ":" << __LINE__ << std::endl;\ + return ROCDEC_RUNTIME_ERROR; \ + } \ +} + class RocDecoder { public: RocDecoder(RocDecoderCreateInfo &decoder_create_info); @@ -42,14 +50,15 @@ public: rocDecStatus decodeFrame(RocdecPicParams *pPicParams); rocDecStatus getDecodeStatus(int nPicIdx, RocdecDecodeStatus* pDecodeStatus); rocDecStatus reconfigureDecoder(RocdecReconfigureDecoderInfo *pDecReconfigParams); - rocDecStatus mapVideoFrame(int nPicIdx, void *pDevMemPtr[3], unsigned int pHorizontalPitch[3], RocdecProcParams *pVidPostprocParams); + rocDecStatus mapVideoFrame(int pic_idx, void *dev_mem_ptr[3], unsigned int horizontal_pitch[3], RocdecProcParams *vid_postproc_params); rocDecStatus unMapVideoFrame(void *pMappedDevPtr); private: rocDecStatus InitHIP(int device_id); int num_devices_; - int device_id_; + RocDecoderCreateInfo decoder_create_info_; VaapiVideoDecoder va_video_decoder_; hipDeviceProp_t hip_dev_prop_; hipStream_t hip_stream_; + std::vector hip_ext_mem_; }; \ No newline at end of file diff --git a/src/rocdecode/vaapi/vaapi_videodecoder.cpp b/src/rocdecode/vaapi/vaapi_videodecoder.cpp index 7f1c56290b..9d4d038873 100644 --- a/src/rocdecode/vaapi/vaapi_videodecoder.cpp +++ b/src/rocdecode/vaapi/vaapi_videodecoder.cpp @@ -174,3 +174,17 @@ rocDecStatus VaapiVideoDecoder::GetDecodeStatus(int pic_idx, RocdecDecodeStatus } return ROCDEC_SUCCESS; } + +rocDecStatus VaapiVideoDecoder::ExportSurface(int pic_idx, VADRMPRIMESurfaceDescriptor &va_drm_prime_surface_desc) { + if (pic_idx >= va_surface_ids_.size()) { + return ROCDEC_INVALID_PARAMETER; + } + CHECK_VAAPI(vaSyncSurface(va_display_, va_surface_ids_[pic_idx])); + CHECK_VAAPI(vaExportSurfaceHandle(va_display_, va_surface_ids_[pic_idx], + VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2, + VA_EXPORT_SURFACE_READ_ONLY | + VA_EXPORT_SURFACE_SEPARATE_LAYERS, + &va_drm_prime_surface_desc)); + + return ROCDEC_SUCCESS; +} diff --git a/src/rocdecode/vaapi/vaapi_videodecoder.h b/src/rocdecode/vaapi/vaapi_videodecoder.h index 25f06bf9e5..e8da580bb3 100644 --- a/src/rocdecode/vaapi/vaapi_videodecoder.h +++ b/src/rocdecode/vaapi/vaapi_videodecoder.h @@ -50,6 +50,8 @@ public: rocDecStatus InitializeDecoder(std::string gcn_arch_name); rocDecStatus SubmitDecode(RocdecPicParams *pPicParams); rocDecStatus GetDecodeStatus(int pic_idx, RocdecDecodeStatus* decode_status); + rocDecStatus ExportSurface(int pic_idx, VADRMPRIMESurfaceDescriptor &va_drm_prime_surface_desc); + private: RocDecoderCreateInfo decoder_create_info_; int drm_fd_;