diff --git a/samples/jpegDecode/jpegdecode.cpp b/samples/jpegDecode/jpegdecode.cpp index 236ff684b9..f527e982d1 100644 --- a/samples/jpegDecode/jpegdecode.cpp +++ b/samples/jpegDecode/jpegdecode.cpp @@ -302,6 +302,7 @@ int main(int argc, char **argv) { uint32_t widths[ROCJPEG_MAX_COMPONENT] = {}; uint32_t heights[ROCJPEG_MAX_COMPONENT] = {}; uint32_t channel_sizes[ROCJPEG_MAX_COMPONENT] = {}; + uint32_t prior_channel_sizes[ROCJPEG_MAX_COMPONENT] = {}; uint32_t num_channels = 0; int total_images = 0; double time_per_image_all = 0; @@ -459,9 +460,16 @@ int main(int argc, char **argv) { std::cout << "Unknown output format!" << std::endl; return EXIT_FAILURE; } - // allocate memory for each channel + + // allocate memory for each channel and reuse them if the sizes remain unchanged for a new image. for (int i = 0; i < num_channels; i++) { - CHECK_HIP(hipMalloc(&output_image.channel[i], channel_sizes[i])); + if (prior_channel_sizes[i] != channel_sizes[i]) { + if (output_image.channel[i] != nullptr) { + CHECK_HIP(hipFree((void *)output_image.channel[i])); + output_image.channel[i] = nullptr; + } + CHECK_HIP(hipMalloc(&output_image.channel[i], channel_sizes[i])); + } } std::cout << "info: decoding started, please wait! ... " << std::endl; @@ -503,14 +511,6 @@ int main(int argc, char **argv) { SaveImage(image_save_path, &output_image, widths[0], heights[0], subsampling, output_format); } - for (int i = 0; i < num_channels; i++) { - if (output_image.channel[i] != nullptr) { - CHECK_HIP(hipFree((void*)output_image.channel[i])); - output_image.channel[i] = nullptr; - output_image.pitch[i] = 0; - } - } - std::cout << "info: average processing time per image (ms): " << time_per_image_in_milli_sec << std::endl; std::cout << "info: average images per sec: " << 1000 / time_per_image_in_milli_sec << std::endl; @@ -521,6 +521,16 @@ int main(int argc, char **argv) { mpixels_all += image_size_in_mpixels; } counter++; + for (int i = 0; i < ROCJPEG_MAX_COMPONENT; i++) { + prior_channel_sizes[i] = channel_sizes[i]; + } + } + + for (int i = 0; i < num_channels; i++) { + if (output_image.channel[i] != nullptr) { + CHECK_HIP(hipFree((void *)output_image.channel[i])); + output_image.channel[i] = nullptr; + } } if (is_dir) { @@ -530,8 +540,8 @@ int main(int argc, char **argv) { std::cout << "info: total decoded images: " << total_images << std::endl; if (total_images) { std::cout << "info: average processing time per image (ms): " << time_per_image_all << std::endl; - std::cout << "info: average decoded images per sec: " << images_per_sec << std::endl; - std::cout << "info: average decoded image_size_in_mpixels per sec: " << mpixels_per_sec << std::endl; + std::cout << "info: average decoded images per sec (Images/Sec): " << images_per_sec << std::endl; + std::cout << "info: average decoded images size (Mpixels/Sec): " << mpixels_per_sec << std::endl; } std::cout << std::endl; } diff --git a/src/rocjpeg_decoder.cpp b/src/rocjpeg_decoder.cpp index 629021d8d5..a4fef891a5 100644 --- a/src/rocjpeg_decoder.cpp +++ b/src/rocjpeg_decoder.cpp @@ -23,7 +23,7 @@ THE SOFTWARE. #include "rocjpeg_decoder.h" ROCJpegDecoder::ROCJpegDecoder(RocJpegBackend backend, int device_id) : - num_devices_{0}, device_id_ {device_id}, hip_stream_ {0}, backend_{backend}, hip_interop_{} {} + num_devices_{0}, device_id_ {device_id}, hip_stream_ {0}, backend_{backend} {} ROCJpegDecoder::~ROCJpegDecoder() { if (hip_stream_) { @@ -81,43 +81,42 @@ RocJpegStatus ROCJpegDecoder::Decode(const uint8_t *data, size_t length, RocJpeg CHECK_ROCJPEG(jpeg_vaapi_decoder_.SubmitDecode(jpeg_stream_params, current_surface_id, output_format)); if (destination != nullptr) { - VADRMPRIMESurfaceDescriptor va_drm_prime_surface_desc = {}; + HipInteropDeviceMem hip_interop_dev_mem = {}; CHECK_ROCJPEG(jpeg_vaapi_decoder_.SyncSurface(current_surface_id)); - CHECK_ROCJPEG(jpeg_vaapi_decoder_.ExportSurface(current_surface_id, va_drm_prime_surface_desc)); - CHECK_ROCJPEG(GetHipInteropMem(va_drm_prime_surface_desc)); + CHECK_ROCJPEG(jpeg_vaapi_decoder_.GetHipInteropMem(current_surface_id, hip_interop_dev_mem)); uint16_t chroma_height = 0; switch (output_format) { case ROCJPEG_OUTPUT_NATIVE: // Copy the native decoded output buffers from interop memory directly to the destination buffers - CHECK_ROCJPEG(GetChromaHeight(jpeg_stream_params->picture_parameter_buffer.picture_height, chroma_height)); + CHECK_ROCJPEG(GetChromaHeight(hip_interop_dev_mem.surface_format, jpeg_stream_params->picture_parameter_buffer.picture_height, chroma_height)); // Copy Luma (first channel) for any surface format - CHECK_ROCJPEG(CopyChannel(destination, jpeg_stream_params->picture_parameter_buffer.picture_height, 0)); - if (hip_interop_.surface_format == VA_FOURCC_NV12) { + CHECK_ROCJPEG(CopyChannel(hip_interop_dev_mem, jpeg_stream_params->picture_parameter_buffer.picture_height, 0, destination)); + if (hip_interop_dev_mem.surface_format == VA_FOURCC_NV12) { // Copy the second channel (UV interleaved) for NV12 - CHECK_ROCJPEG(CopyChannel(destination, chroma_height, 1)); - } else if (hip_interop_.surface_format == VA_FOURCC_444P) { + CHECK_ROCJPEG(CopyChannel(hip_interop_dev_mem, chroma_height, 1, destination)); + } else if (hip_interop_dev_mem.surface_format == VA_FOURCC_444P) { // Copy the second and third channels for YUV444 - CHECK_ROCJPEG(CopyChannel(destination, chroma_height, 1)); - CHECK_ROCJPEG(CopyChannel(destination, chroma_height, 2)); + CHECK_ROCJPEG(CopyChannel(hip_interop_dev_mem, chroma_height, 1, destination)); + CHECK_ROCJPEG(CopyChannel(hip_interop_dev_mem, chroma_height, 2, destination)); } break; case ROCJPEG_OUTPUT_YUV_PLANAR: - CHECK_ROCJPEG(GetChromaHeight(jpeg_stream_params->picture_parameter_buffer.picture_height, chroma_height)); - CHECK_ROCJPEG(GetPlanarYUVOutputFormat(jpeg_stream_params->picture_parameter_buffer.picture_width, + CHECK_ROCJPEG(GetChromaHeight(hip_interop_dev_mem.surface_format, jpeg_stream_params->picture_parameter_buffer.picture_height, chroma_height)); + CHECK_ROCJPEG(GetPlanarYUVOutputFormat(hip_interop_dev_mem, jpeg_stream_params->picture_parameter_buffer.picture_width, jpeg_stream_params->picture_parameter_buffer.picture_height, chroma_height, destination)); break; case ROCJPEG_OUTPUT_Y: - CHECK_ROCJPEG(GetYOutputFormat(jpeg_stream_params->picture_parameter_buffer.picture_width, + CHECK_ROCJPEG(GetYOutputFormat(hip_interop_dev_mem, jpeg_stream_params->picture_parameter_buffer.picture_width, jpeg_stream_params->picture_parameter_buffer.picture_height, destination)); break; case ROCJPEG_OUTPUT_RGB: - CHECK_ROCJPEG(ColorConvertToRGB(jpeg_stream_params->picture_parameter_buffer.picture_width, + CHECK_ROCJPEG(ColorConvertToRGB(hip_interop_dev_mem, jpeg_stream_params->picture_parameter_buffer.picture_width, jpeg_stream_params->picture_parameter_buffer.picture_height, destination)); break; case ROCJPEG_OUTPUT_RGB_PLANAR: - CHECK_ROCJPEG(ColorConvertToRGBPlanar(jpeg_stream_params->picture_parameter_buffer.picture_width, + CHECK_ROCJPEG(ColorConvertToRGBPlanar(hip_interop_dev_mem, jpeg_stream_params->picture_parameter_buffer.picture_width, jpeg_stream_params->picture_parameter_buffer.picture_height, destination)); break; default: @@ -125,8 +124,6 @@ RocJpegStatus ROCJpegDecoder::Decode(const uint8_t *data, size_t length, RocJpeg } CHECK_HIP(hipStreamSynchronize(hip_stream_)); - - CHECK_ROCJPEG(ReleaseHipInteropMem(current_surface_id)); } return ROCJPEG_STATUS_SUCCESS; @@ -188,63 +185,21 @@ RocJpegStatus ROCJpegDecoder::GetImageInfo(const uint8_t *data, size_t length, u return ROCJPEG_STATUS_SUCCESS; } -RocJpegStatus ROCJpegDecoder::GetHipInteropMem(VADRMPRIMESurfaceDescriptor &va_drm_prime_surface_desc) { - hipExternalMemoryHandleDesc external_mem_handle_desc = {}; - hipExternalMemoryBufferDesc external_mem_buffer_desc = {}; - 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_interop_.hip_ext_mem, &external_mem_handle_desc)); - external_mem_buffer_desc.size = va_drm_prime_surface_desc.objects[0].size; - CHECK_HIP(hipExternalMemoryGetMappedBuffer((void**)&hip_interop_.hip_mapped_device_mem, hip_interop_.hip_ext_mem, &external_mem_buffer_desc)); - - hip_interop_.surface_format = va_drm_prime_surface_desc.fourcc; - hip_interop_.width = va_drm_prime_surface_desc.width; - hip_interop_.height = va_drm_prime_surface_desc.height; - hip_interop_.offset[0] = va_drm_prime_surface_desc.layers[0].offset[0]; - hip_interop_.offset[1] = va_drm_prime_surface_desc.layers[1].offset[0]; - hip_interop_.offset[2] = va_drm_prime_surface_desc.layers[2].offset[0]; - hip_interop_.pitch[0] = va_drm_prime_surface_desc.layers[0].pitch[0]; - hip_interop_.pitch[1] = va_drm_prime_surface_desc.layers[1].pitch[0]; - hip_interop_.pitch[2] = va_drm_prime_surface_desc.layers[2].pitch[0]; - hip_interop_.num_layers = va_drm_prime_surface_desc.num_layers; - - for (uint32_t i = 0; i < va_drm_prime_surface_desc.num_objects; ++i) { - close(va_drm_prime_surface_desc.objects[i].fd); - } - return ROCJPEG_STATUS_SUCCESS; -} - -RocJpegStatus ROCJpegDecoder::ReleaseHipInteropMem(VASurfaceID current_surface_id) { - if (hip_interop_.hip_mapped_device_mem != nullptr) { - CHECK_HIP(hipFree(hip_interop_.hip_mapped_device_mem)); - } - if (hip_interop_.hip_ext_mem != nullptr) { - CHECK_HIP(hipDestroyExternalMemory(hip_interop_.hip_ext_mem)); - } - memset((void*)&hip_interop_, 0, sizeof(hip_interop_)); - - CHECK_ROCJPEG(jpeg_vaapi_decoder_.ReleaseSurface(current_surface_id)); - - return ROCJPEG_STATUS_SUCCESS; -} - -RocJpegStatus ROCJpegDecoder::CopyChannel(RocJpegImage *destination, uint16_t channel_height, uint8_t channel_index) { - if (hip_interop_.pitch[channel_index] != 0 && destination->pitch[channel_index] != 0 && destination->channel[channel_index] != nullptr) { - if (destination->pitch[channel_index] == hip_interop_.pitch[channel_index]) { +RocJpegStatus ROCJpegDecoder::CopyChannel(HipInteropDeviceMem& hip_interop_dev_mem, uint16_t channel_height, uint8_t channel_index, RocJpegImage *destination) { + if (hip_interop_dev_mem.pitch[channel_index] != 0 && destination->pitch[channel_index] != 0 && destination->channel[channel_index] != nullptr) { + if (destination->pitch[channel_index] == hip_interop_dev_mem.pitch[channel_index]) { uint32_t channel_size = destination->pitch[channel_index] * channel_height; - CHECK_HIP(hipMemcpyDtoDAsync(destination->channel[channel_index], hip_interop_.hip_mapped_device_mem + hip_interop_.offset[channel_index], channel_size, hip_stream_)); + CHECK_HIP(hipMemcpyDtoDAsync(destination->channel[channel_index], hip_interop_dev_mem.hip_mapped_device_mem + hip_interop_dev_mem.offset[channel_index], channel_size, hip_stream_)); } else { - CHECK_HIP(hipMemcpy2DAsync(destination->channel[channel_index], destination->pitch[channel_index], hip_interop_.hip_mapped_device_mem + hip_interop_.offset[channel_index], hip_interop_.pitch[channel_index], + CHECK_HIP(hipMemcpy2DAsync(destination->channel[channel_index], destination->pitch[channel_index], hip_interop_dev_mem.hip_mapped_device_mem + hip_interop_dev_mem.offset[channel_index], hip_interop_dev_mem.pitch[channel_index], destination->pitch[channel_index], channel_height, hipMemcpyDeviceToDevice, hip_stream_)); } } return ROCJPEG_STATUS_SUCCESS; } -RocJpegStatus ROCJpegDecoder::GetChromaHeight(uint16_t picture_height, uint16_t &chroma_height) { - switch (hip_interop_.surface_format) { +RocJpegStatus ROCJpegDecoder::GetChromaHeight(uint32_t surface_format, uint16_t picture_height, uint16_t &chroma_height) { + switch (surface_format) { case VA_FOURCC_NV12: /*NV12: two-plane 8-bit YUV 4:2:0*/ chroma_height = picture_height >> 1; break; @@ -263,28 +218,28 @@ RocJpegStatus ROCJpegDecoder::GetChromaHeight(uint16_t picture_height, uint16_t return ROCJPEG_STATUS_SUCCESS; } -RocJpegStatus ROCJpegDecoder::ColorConvertToRGB(uint32_t picture_width, uint32_t picture_height, RocJpegImage *destination) { - switch (hip_interop_.surface_format) { +RocJpegStatus ROCJpegDecoder::ColorConvertToRGB(HipInteropDeviceMem& hip_interop_dev_mem, uint32_t picture_width, uint32_t picture_height, RocJpegImage *destination) { + switch (hip_interop_dev_mem.surface_format) { case VA_FOURCC_444P: ColorConvertYUV444ToRGB(hip_stream_, picture_width, picture_height, destination->channel[0], destination->pitch[0], - hip_interop_.hip_mapped_device_mem, hip_interop_.pitch[0], hip_interop_.offset[1]); + hip_interop_dev_mem.hip_mapped_device_mem, hip_interop_dev_mem.pitch[0], hip_interop_dev_mem.offset[1]); break; case ROCJPEG_FOURCC_YUYV: ColorConvertYUYVToRGB(hip_stream_, picture_width, picture_height, destination->channel[0], destination->pitch[0], - hip_interop_.hip_mapped_device_mem, hip_interop_.pitch[0]); + hip_interop_dev_mem.hip_mapped_device_mem, hip_interop_dev_mem.pitch[0]); break; case VA_FOURCC_NV12: ColorConvertNV12ToRGB(hip_stream_, picture_width, picture_height, destination->channel[0], destination->pitch[0], - hip_interop_.hip_mapped_device_mem, hip_interop_.pitch[0], - hip_interop_.hip_mapped_device_mem + hip_interop_.offset[1], hip_interop_.pitch[1]); + hip_interop_dev_mem.hip_mapped_device_mem, hip_interop_dev_mem.pitch[0], + hip_interop_dev_mem.hip_mapped_device_mem + hip_interop_dev_mem.offset[1], hip_interop_dev_mem.pitch[1]); break; case VA_FOURCC_Y800: ColorConvertYUV400ToRGB(hip_stream_, picture_width, picture_height, destination->channel[0], destination->pitch[0], - hip_interop_.hip_mapped_device_mem, hip_interop_.pitch[0]); + hip_interop_dev_mem.hip_mapped_device_mem, hip_interop_dev_mem.pitch[0]); break; case VA_FOURCC_RGBA: ColorConvertRGBAToRGB(hip_stream_, picture_width, picture_height, destination->channel[0], destination->pitch[0], - hip_interop_.hip_mapped_device_mem, hip_interop_.pitch[0]); + hip_interop_dev_mem.hip_mapped_device_mem, hip_interop_dev_mem.pitch[0]); break; default: ERR("ERROR! surface format is not supported!"); @@ -293,29 +248,29 @@ RocJpegStatus ROCJpegDecoder::ColorConvertToRGB(uint32_t picture_width, uint32_t return ROCJPEG_STATUS_SUCCESS; } -RocJpegStatus ROCJpegDecoder::ColorConvertToRGBPlanar(uint32_t picture_width, uint32_t picture_height, RocJpegImage *destination) { - switch (hip_interop_.surface_format) { +RocJpegStatus ROCJpegDecoder::ColorConvertToRGBPlanar(HipInteropDeviceMem& hip_interop_dev_mem, uint32_t picture_width, uint32_t picture_height, RocJpegImage *destination) { + switch (hip_interop_dev_mem.surface_format) { case VA_FOURCC_444P: ColorConvertYUV444ToRGBPlanar(hip_stream_, picture_width, picture_height, destination->channel[0], destination->channel[1], destination->channel[2], destination->pitch[0], - hip_interop_.hip_mapped_device_mem, hip_interop_.pitch[0], hip_interop_.offset[1]); + hip_interop_dev_mem.hip_mapped_device_mem, hip_interop_dev_mem.pitch[0], hip_interop_dev_mem.offset[1]); break; case ROCJPEG_FOURCC_YUYV: ColorConvertYUYVToRGBPlanar(hip_stream_, picture_width, picture_height, destination->channel[0], destination->channel[1], destination->channel[2], destination->pitch[0], - hip_interop_.hip_mapped_device_mem, hip_interop_.pitch[0]); + hip_interop_dev_mem.hip_mapped_device_mem, hip_interop_dev_mem.pitch[0]); break; case VA_FOURCC_NV12: ColorConvertNV12ToRGBPlanar(hip_stream_, picture_width, picture_height, destination->channel[0], destination->channel[1], destination->channel[2], destination->pitch[0], - hip_interop_.hip_mapped_device_mem, hip_interop_.pitch[0], - hip_interop_.hip_mapped_device_mem + hip_interop_.offset[1], hip_interop_.pitch[1]); + hip_interop_dev_mem.hip_mapped_device_mem, hip_interop_dev_mem.pitch[0], + hip_interop_dev_mem.hip_mapped_device_mem + hip_interop_dev_mem.offset[1], hip_interop_dev_mem.pitch[1]); break; case VA_FOURCC_Y800: ColorConvertYUV400ToRGBPlanar(hip_stream_, picture_width, picture_height, destination->channel[0], destination->channel[1], destination->channel[2], destination->pitch[0], - hip_interop_.hip_mapped_device_mem, hip_interop_.pitch[0]); + hip_interop_dev_mem.hip_mapped_device_mem, hip_interop_dev_mem.pitch[0]); break; case VA_FOURCC_RGBP: // Copy red, green, and blue channels from the interop memory into the destination for (uint8_t channel_index = 0; channel_index < 3; channel_index++) { - CHECK_ROCJPEG(CopyChannel(destination, picture_height, channel_index)); + CHECK_ROCJPEG(CopyChannel(hip_interop_dev_mem, picture_height, channel_index, destination)); } break; default: @@ -325,33 +280,33 @@ RocJpegStatus ROCJpegDecoder::ColorConvertToRGBPlanar(uint32_t picture_width, ui return ROCJPEG_STATUS_SUCCESS; } -RocJpegStatus ROCJpegDecoder::GetPlanarYUVOutputFormat(uint32_t picture_width, uint32_t picture_height, uint16_t chroma_height, RocJpegImage *destination) { - if (hip_interop_.surface_format == ROCJPEG_FOURCC_YUYV) { +RocJpegStatus ROCJpegDecoder::GetPlanarYUVOutputFormat(HipInteropDeviceMem& hip_interop_dev_mem, uint32_t picture_width, uint32_t picture_height, uint16_t chroma_height, RocJpegImage *destination) { + if (hip_interop_dev_mem.surface_format == ROCJPEG_FOURCC_YUYV) { // Extract the packed YUYV and copy them into the first, second, and thrid channels of the destination. ConvertPackedYUYVToPlanarYUV(hip_stream_, picture_width, picture_height, destination->channel[0], destination->channel[1], destination->channel[2], - destination->pitch[0], destination->pitch[1], hip_interop_.hip_mapped_device_mem, hip_interop_.pitch[0]); + destination->pitch[0], destination->pitch[1], hip_interop_dev_mem.hip_mapped_device_mem, hip_interop_dev_mem.pitch[0]); } else { // Copy Luma - CHECK_ROCJPEG(CopyChannel(destination, picture_height, 0)); - if (hip_interop_.surface_format == VA_FOURCC_NV12) { + CHECK_ROCJPEG(CopyChannel(hip_interop_dev_mem, picture_height, 0, destination)); + if (hip_interop_dev_mem.surface_format == VA_FOURCC_NV12) { // Extract the interleaved UV channels and copy them into the second and thrid channels of the destination. ConvertInterleavedUVToPlanarUV(hip_stream_, picture_width >> 1, picture_height >> 1, destination->channel[1], destination->channel[2], - destination->pitch[1], hip_interop_.hip_mapped_device_mem + hip_interop_.offset[1] , hip_interop_.pitch[1]); - } else if (hip_interop_.surface_format == VA_FOURCC_444P) { - CHECK_ROCJPEG(CopyChannel(destination, chroma_height, 1)); - CHECK_ROCJPEG(CopyChannel(destination, chroma_height, 2)); + destination->pitch[1], hip_interop_dev_mem.hip_mapped_device_mem + hip_interop_dev_mem.offset[1] , hip_interop_dev_mem.pitch[1]); + } else if (hip_interop_dev_mem.surface_format == VA_FOURCC_444P) { + CHECK_ROCJPEG(CopyChannel(hip_interop_dev_mem, chroma_height, 1, destination)); + CHECK_ROCJPEG(CopyChannel(hip_interop_dev_mem, chroma_height, 2, destination)); } } return ROCJPEG_STATUS_SUCCESS; } -RocJpegStatus ROCJpegDecoder::GetYOutputFormat(uint32_t picture_width, uint32_t picture_height, RocJpegImage *destination) { - if (hip_interop_.surface_format == ROCJPEG_FOURCC_YUYV) { +RocJpegStatus ROCJpegDecoder::GetYOutputFormat(HipInteropDeviceMem& hip_interop_dev_mem, uint32_t picture_width, uint32_t picture_height, RocJpegImage *destination) { + if (hip_interop_dev_mem.surface_format == ROCJPEG_FOURCC_YUYV) { ExtractYFromPackedYUYV(hip_stream_, picture_width, picture_height, destination->channel[0], destination->pitch[0], - hip_interop_.hip_mapped_device_mem, hip_interop_.pitch[0]); + hip_interop_dev_mem.hip_mapped_device_mem, hip_interop_dev_mem.pitch[0]); } else { // Copy Luma - CHECK_ROCJPEG(CopyChannel(destination, picture_height, 0)); + CHECK_ROCJPEG(CopyChannel(hip_interop_dev_mem, picture_height, 0, destination)); } return ROCJPEG_STATUS_SUCCESS; } \ No newline at end of file diff --git a/src/rocjpeg_decoder.h b/src/rocjpeg_decoder.h index ba6e751219..a811701661 100644 --- a/src/rocjpeg_decoder.h +++ b/src/rocjpeg_decoder.h @@ -25,7 +25,6 @@ THE SOFTWARE. #include #include -#include #include #include #include "../api/rocjpeg.h" @@ -34,17 +33,6 @@ THE SOFTWARE. #include "rocjpeg_vaapi_decoder.h" #include "rocjpeg_hip_kernels.h" -struct HipInteropDeviceMem { - hipExternalMemory_t hip_ext_mem; // Interface to the vaapi-hip interop - uint8_t* hip_mapped_device_mem; // Mapped device memory for the YUV plane - uint32_t surface_format; // Pixel format fourcc of the whole surface - uint32_t width; // Width of the surface in pixels. - uint32_t height; // Height of the surface in pixels. - uint32_t offset[3]; // Offset of each plane - uint32_t pitch[3]; // Pitch of each plane - uint32_t num_layers; // Number of layers making up the surface -}; - class ROCJpegDecoder { public: ROCJpegDecoder(RocJpegBackend backend = ROCJPEG_BACKEND_HARDWARE, int device_id = 0); @@ -54,14 +42,12 @@ class ROCJpegDecoder { RocJpegStatus Decode(const uint8_t *data, size_t length, RocJpegOutputFormat output_format, RocJpegImage *destination); private: RocJpegStatus InitHIP(int device_id); - RocJpegStatus GetHipInteropMem(VADRMPRIMESurfaceDescriptor &va_drm_prime_surface_desc); - RocJpegStatus ReleaseHipInteropMem(VASurfaceID current_surface_id); - RocJpegStatus GetChromaHeight(uint16_t picture_height, uint16_t &chroma_height); - RocJpegStatus CopyChannel(RocJpegImage *destination, uint16_t channel_height, uint8_t channel_index); - RocJpegStatus ColorConvertToRGB(uint32_t picture_width, uint32_t picture_height, RocJpegImage *destination); - RocJpegStatus ColorConvertToRGBPlanar(uint32_t picture_width, uint32_t picture_height, RocJpegImage *destination); - RocJpegStatus GetPlanarYUVOutputFormat(uint32_t picture_width, uint32_t picture_height, uint16_t chroma_height, RocJpegImage *destination); - RocJpegStatus GetYOutputFormat(uint32_t picture_width, uint32_t picture_height, RocJpegImage *destination); + RocJpegStatus GetChromaHeight(uint32_t surface_format, uint16_t picture_height, uint16_t &chroma_height); + RocJpegStatus CopyChannel(HipInteropDeviceMem& hip_interop, uint16_t channel_height, uint8_t channel_index, RocJpegImage *destination); + RocJpegStatus ColorConvertToRGB(HipInteropDeviceMem& hip_interop, uint32_t picture_width, uint32_t picture_height, RocJpegImage *destination); + RocJpegStatus ColorConvertToRGBPlanar(HipInteropDeviceMem& hip_interop, uint32_t picture_width, uint32_t picture_height, RocJpegImage *destination); + RocJpegStatus GetPlanarYUVOutputFormat(HipInteropDeviceMem& hip_interop, uint32_t picture_width, uint32_t picture_height, uint16_t chroma_height, RocJpegImage *destination); + RocJpegStatus GetYOutputFormat(HipInteropDeviceMem& hip_interop, uint32_t picture_width, uint32_t picture_height, RocJpegImage *destination); int num_devices_; int device_id_; hipDeviceProp_t hip_dev_prop_; @@ -70,7 +56,6 @@ class ROCJpegDecoder { JpegParser jpeg_parser_; RocJpegBackend backend_; RocJpegVappiDecoder jpeg_vaapi_decoder_; - HipInteropDeviceMem hip_interop_; }; #endif //ROC_JPEG_DECODER_H_ \ No newline at end of file diff --git a/src/rocjpeg_vaapi_decoder.cpp b/src/rocjpeg_vaapi_decoder.cpp index 507f1df0bc..f5e1b14759 100644 --- a/src/rocjpeg_vaapi_decoder.cpp +++ b/src/rocjpeg_vaapi_decoder.cpp @@ -22,10 +22,182 @@ THE SOFTWARE. #include "rocjpeg_vaapi_decoder.h" +RocJpegVappiMemoryPool::RocJpegVappiMemoryPool() { +std::vector surface_formats = {VA_RT_FORMAT_RGB32, VA_RT_FORMAT_RGBP, VA_RT_FORMAT_YUV444, + VA_RT_FORMAT_YUV422, VA_RT_FORMAT_YUV420, VA_RT_FORMAT_YUV400}; + for (auto surface_format : surface_formats) { + mem_pool_[surface_format] = std::vector(); + } +} + +void RocJpegVappiMemoryPool::ReleaseResources() { + VAStatus va_status; + hipError_t hip_status; + for (auto& pair : mem_pool_) { + for (auto& entry : pair.second) { + if (entry.va_context_id != 0) { + va_status = vaDestroyContext(va_display_, entry.va_context_id); + if (va_status != VA_STATUS_SUCCESS) { + ERR("ERROR: vaDestroyContext failed!"); + } + } + if (entry.va_surface_id != 0) { + va_status = vaDestroySurfaces(va_display_, &entry.va_surface_id, 1); + if (va_status != VA_STATUS_SUCCESS) { + ERR("ERROR: vaDestroySurfaces failed!"); + } + } + if (entry.hip_interop.hip_mapped_device_mem != nullptr) { + hip_status = hipFree(entry.hip_interop.hip_mapped_device_mem); + if (hip_status != hipSuccess) { + ERR("ERROR: hipFree failed!"); + } + } + if (entry.hip_interop.hip_ext_mem != nullptr) { + hip_status = hipDestroyExternalMemory(entry.hip_interop.hip_ext_mem); + if (hip_status != hipSuccess) { + ERR("ERROR: hipDestroyExternalMemory failed!"); + } + } + memset((void*)&entry.hip_interop, 0, sizeof(entry.hip_interop)); + } + } +} + +void RocJpegVappiMemoryPool::SetPoolSize(int32_t max_pool_size) { + for (auto& pair : mem_pool_) { + pair.second.reserve(max_pool_size); + } +} + +void RocJpegVappiMemoryPool::SetVaapiDisplay(const VADisplay& va_display) { + va_display_ = va_display; +} + +RocJpegStatus RocJpegVappiMemoryPool::AddPoolEntry(uint32_t surface_format, const RocJpegVappiMemPoolEntry& pool_entry) { + auto& entires = mem_pool_[surface_format]; + if (entires.size() < entires.capacity()) { + entires.push_back(pool_entry); + } else { + if (entires.front().va_context_id != 0) { + CHECK_VAAPI(vaDestroyContext(va_display_, entires.front().va_context_id)); + entires.front().va_context_id = 0; + } + if (entires.front().va_surface_id != 0) { + CHECK_VAAPI(vaDestroySurfaces(va_display_, &entires.front().va_surface_id, 1)); + entires.front().va_surface_id = 0; + } + if (entires.front().hip_interop.hip_mapped_device_mem != nullptr) { + CHECK_HIP(hipFree(entires.front().hip_interop.hip_mapped_device_mem)); + } + if (entires.front().hip_interop.hip_ext_mem != nullptr) { + CHECK_HIP(hipDestroyExternalMemory(entires.front().hip_interop.hip_ext_mem)); + } + memset((void*)&entires.front().hip_interop, 0, sizeof(entires.front().hip_interop)); + entires.erase(entires.begin()); + entires.push_back(pool_entry); + } + return ROCJPEG_STATUS_SUCCESS; +} + +RocJpegVappiMemPoolEntry RocJpegVappiMemoryPool::GetEntry(uint32_t surface_format, uint32_t image_width, uint32_t image_height) { + for (const auto& entry : mem_pool_[surface_format]) { + if (entry.image_width == image_width && entry.image_height == image_height) { + return entry; + } + } + return {0, 0, 0 , 0, {0}}; +} + +bool RocJpegVappiMemoryPool::FindSurfaceId(VASurfaceID surface_id) { + for (auto& pair : mem_pool_) { + for (auto& entry : pair.second) { + if (entry.va_surface_id == surface_id) { + return true; + } + } + } + return false; +} + +RocJpegStatus RocJpegVappiMemoryPool::DeleteSurfaceId(VASurfaceID surface_id) { + for (auto& pair : mem_pool_) { + auto& entries = pair.second; + auto it = std::find_if(entries.begin(), entries.end(), + [surface_id](const RocJpegVappiMemPoolEntry& entry) {return entry.va_surface_id == surface_id;}); + if (it != entries.end()) { + if (it->va_context_id != 0) { + CHECK_VAAPI(vaDestroyContext(va_display_, it->va_context_id)); + it->va_context_id = 0; + } + if (it->va_surface_id != 0) { + CHECK_VAAPI(vaDestroySurfaces(va_display_, &it->va_surface_id, 1)); + it->va_surface_id = 0; + } + if (it->hip_interop.hip_mapped_device_mem != nullptr) { + CHECK_HIP(hipFree(it->hip_interop.hip_mapped_device_mem)); + } + if (it->hip_interop.hip_ext_mem != nullptr) { + CHECK_HIP(hipDestroyExternalMemory(it->hip_interop.hip_ext_mem)); + } + memset((void*)&it->hip_interop, 0, sizeof(it->hip_interop)); + + entries.erase(it); + break; + } + } + return ROCJPEG_STATUS_SUCCESS; +} + +RocJpegStatus RocJpegVappiMemoryPool::GetHipInteropMem(VASurfaceID surface_id, HipInteropDeviceMem& hip_interop) { + for (auto& pair : mem_pool_) { + auto& entries = pair.second; + auto it = std::find_if(entries.begin(), entries.end(), + [surface_id](const RocJpegVappiMemPoolEntry& entry) {return entry.va_surface_id == surface_id;}); + if (it != entries.end()) { + if (it->hip_interop.hip_mapped_device_mem == nullptr) { + VADRMPRIMESurfaceDescriptor va_drm_prime_surface_desc = {}; + CHECK_VAAPI(vaExportSurfaceHandle(va_display_, surface_id, VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2, + VA_EXPORT_SURFACE_READ_ONLY | VA_EXPORT_SURFACE_SEPARATE_LAYERS, + &va_drm_prime_surface_desc)); + + hipExternalMemoryHandleDesc external_mem_handle_desc = {}; + hipExternalMemoryBufferDesc external_mem_buffer_desc = {}; + 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(&it->hip_interop.hip_ext_mem, &external_mem_handle_desc)); + external_mem_buffer_desc.size = va_drm_prime_surface_desc.objects[0].size; + CHECK_HIP(hipExternalMemoryGetMappedBuffer((void**)&it->hip_interop.hip_mapped_device_mem, it->hip_interop.hip_ext_mem, &external_mem_buffer_desc)); + + it->hip_interop.surface_format = va_drm_prime_surface_desc.fourcc; + it->hip_interop.width = va_drm_prime_surface_desc.width; + it->hip_interop.height = va_drm_prime_surface_desc.height; + it->hip_interop.offset[0] = va_drm_prime_surface_desc.layers[0].offset[0]; + it->hip_interop.offset[1] = va_drm_prime_surface_desc.layers[1].offset[0]; + it->hip_interop.offset[2] = va_drm_prime_surface_desc.layers[2].offset[0]; + it->hip_interop.pitch[0] = va_drm_prime_surface_desc.layers[0].pitch[0]; + it->hip_interop.pitch[1] = va_drm_prime_surface_desc.layers[1].pitch[0]; + it->hip_interop.pitch[2] = va_drm_prime_surface_desc.layers[2].pitch[0]; + it->hip_interop.num_layers = va_drm_prime_surface_desc.num_layers; + + for (uint32_t i = 0; i < va_drm_prime_surface_desc.num_objects; ++i) { + close(va_drm_prime_surface_desc.objects[i].fd); + } + } + hip_interop = it->hip_interop; + return ROCJPEG_STATUS_SUCCESS; + } + } + // it shouldn't reach here unless the requested surface_id is not in the memory pool. + ERR("the surface_id: " + TOSTR(surface_id) + " was not found in the memory pool!"); + return ROCJPEG_STATUS_INVALID_PARAMETER; +} RocJpegVappiDecoder::RocJpegVappiDecoder(int device_id) : device_id_{device_id}, drm_fd_{-1}, min_picture_width_{64}, min_picture_height_{64}, max_picture_width_{4096}, max_picture_height_{4096}, va_display_{0}, va_config_attrib_{{}}, va_config_id_{0}, va_profile_{VAProfileJPEGBaseline}, - va_context_id_{0}, va_surface_ids_{}, va_picture_parameter_buf_id_{0}, va_quantization_matrix_buf_id_{0}, va_huffmantable_buf_id_{0}, - va_slice_param_buf_id_{0}, va_slice_data_buf_id_{0}, current_vcn_jpeg_spec_{0} { + vaapi_mem_pool_(std::make_unique()), current_vcn_jpeg_spec_{0}, va_picture_parameter_buf_id_{0}, va_quantization_matrix_buf_id_{0}, va_huffmantable_buf_id_{0}, + va_slice_param_buf_id_{0}, va_slice_data_buf_id_{0} { vcn_jpeg_spec_ = {{"gfx908", {2, false, false}}, {"gfx90a", {2, false, false}}, {"gfx940", {24, true, true}}, @@ -44,23 +216,12 @@ RocJpegVappiDecoder::~RocJpegVappiDecoder() { close(drm_fd_); } if (va_display_) { + vaapi_mem_pool_->ReleaseResources(); RocJpegStatus rocjpeg_status = DestroyDataBuffers(); if (rocjpeg_status != ROCJPEG_STATUS_SUCCESS) { ERR("Error: Failed to destroy VAAPI buffer"); } VAStatus va_status; - if (va_surface_ids_.size() > 0) { - va_status = vaDestroySurfaces(va_display_, va_surface_ids_.data(), va_surface_ids_.size()); - if (va_status != VA_STATUS_SUCCESS) { - ERR("ERROR: vaDestroySurfaces failed!"); - } - } - if (va_context_id_) { - va_status = vaDestroyContext(va_display_, va_context_id_); - if (va_status != VA_STATUS_SUCCESS) { - ERR("ERROR: vaDestroyContext failed!"); - } - } if (va_config_id_) { va_status = vaDestroyConfig(va_display_, va_config_id_); if (va_status != VA_STATUS_SUCCESS) { @@ -114,6 +275,9 @@ RocJpegStatus RocJpegVappiDecoder::InitializeDecoder(std::string device_name, st CHECK_ROCJPEG(InitVAAPI(drm_node)); CHECK_ROCJPEG(CreateDecoderConfig()); + vaapi_mem_pool_->SetVaapiDisplay(va_display_); + vaapi_mem_pool_->SetPoolSize(current_vcn_jpeg_spec_.num_jpeg_cores * 2); + return ROCJPEG_STATUS_SUCCESS; } @@ -257,71 +421,44 @@ RocJpegStatus RocJpegVappiDecoder::SubmitDecode(const JpegStreamParameters *jpeg } } - VASurfaceID va_surface_id; - CHECK_VAAPI(vaCreateSurfaces(va_display_, surface_format, jpeg_stream_params->picture_parameter_buffer.picture_width, jpeg_stream_params->picture_parameter_buffer.picture_height, &va_surface_id, 1, &surface_attrib, 1)); - va_surface_ids_.push_back(va_surface_id); - surface_id = va_surface_id; - - if (va_context_id_) { - vaDestroyContext(va_display_, va_context_id_); - va_context_id_ = 0; + RocJpegVappiMemPoolEntry mem_pool_entry = vaapi_mem_pool_->GetEntry(surface_format, jpeg_stream_params->picture_parameter_buffer.picture_width, jpeg_stream_params->picture_parameter_buffer.picture_height); + VAContextID va_context_id; + if (mem_pool_entry.va_context_id == 0 && mem_pool_entry.va_surface_id == 0) { + CHECK_VAAPI(vaCreateSurfaces(va_display_, surface_format, jpeg_stream_params->picture_parameter_buffer.picture_width, jpeg_stream_params->picture_parameter_buffer.picture_height, &surface_id, 1, &surface_attrib, 1)); + CHECK_VAAPI(vaCreateContext(va_display_, va_config_id_, jpeg_stream_params->picture_parameter_buffer.picture_width, jpeg_stream_params->picture_parameter_buffer.picture_height, VA_PROGRESSIVE, &surface_id, 1, &va_context_id)); + mem_pool_entry.image_width = jpeg_stream_params->picture_parameter_buffer.picture_width; + mem_pool_entry.image_height = jpeg_stream_params->picture_parameter_buffer.picture_height; + mem_pool_entry.va_surface_id = surface_id; + mem_pool_entry.va_context_id = va_context_id; + mem_pool_entry.hip_interop = {}; + CHECK_ROCJPEG(vaapi_mem_pool_->AddPoolEntry(surface_format, mem_pool_entry)); + } else { + surface_id = mem_pool_entry.va_surface_id; + va_context_id = mem_pool_entry.va_context_id; } - CHECK_VAAPI(vaCreateContext(va_display_, va_config_id_, jpeg_stream_params->picture_parameter_buffer.picture_width, jpeg_stream_params->picture_parameter_buffer.picture_height, VA_PROGRESSIVE, &va_surface_id, 1, &va_context_id_)); CHECK_ROCJPEG(DestroyDataBuffers()); - CHECK_VAAPI(vaCreateBuffer(va_display_, va_context_id_, VAPictureParameterBufferType, sizeof(VAPictureParameterBufferJPEGBaseline), 1, (void *)&jpeg_stream_params->picture_parameter_buffer, &va_picture_parameter_buf_id_)); - CHECK_VAAPI(vaCreateBuffer(va_display_, va_context_id_, VAIQMatrixBufferType, sizeof(VAIQMatrixBufferJPEGBaseline), 1, (void *)&jpeg_stream_params->quantization_matrix_buffer, &va_quantization_matrix_buf_id_)); - CHECK_VAAPI(vaCreateBuffer(va_display_, va_context_id_, VAHuffmanTableBufferType, sizeof(VAHuffmanTableBufferJPEGBaseline), 1, (void *)&jpeg_stream_params->huffman_table_buffer, &va_huffmantable_buf_id_)); - CHECK_VAAPI(vaCreateBuffer(va_display_, va_context_id_, VASliceParameterBufferType, sizeof(VASliceParameterBufferJPEGBaseline), 1, (void *)&jpeg_stream_params->slice_parameter_buffer, &va_slice_param_buf_id_)); - CHECK_VAAPI(vaCreateBuffer(va_display_, va_context_id_, VASliceDataBufferType, jpeg_stream_params->slice_parameter_buffer.slice_data_size, 1, (void *)jpeg_stream_params->slice_data_buffer, &va_slice_data_buf_id_)); + CHECK_VAAPI(vaCreateBuffer(va_display_, va_context_id, VAPictureParameterBufferType, sizeof(VAPictureParameterBufferJPEGBaseline), 1, (void *)&jpeg_stream_params->picture_parameter_buffer, &va_picture_parameter_buf_id_)); + CHECK_VAAPI(vaCreateBuffer(va_display_, va_context_id, VAIQMatrixBufferType, sizeof(VAIQMatrixBufferJPEGBaseline), 1, (void *)&jpeg_stream_params->quantization_matrix_buffer, &va_quantization_matrix_buf_id_)); + CHECK_VAAPI(vaCreateBuffer(va_display_, va_context_id, VAHuffmanTableBufferType, sizeof(VAHuffmanTableBufferJPEGBaseline), 1, (void *)&jpeg_stream_params->huffman_table_buffer, &va_huffmantable_buf_id_)); + CHECK_VAAPI(vaCreateBuffer(va_display_, va_context_id, VASliceParameterBufferType, sizeof(VASliceParameterBufferJPEGBaseline), 1, (void *)&jpeg_stream_params->slice_parameter_buffer, &va_slice_param_buf_id_)); + CHECK_VAAPI(vaCreateBuffer(va_display_, va_context_id, VASliceDataBufferType, jpeg_stream_params->slice_parameter_buffer.slice_data_size, 1, (void *)jpeg_stream_params->slice_data_buffer, &va_slice_data_buf_id_)); - CHECK_VAAPI(vaBeginPicture(va_display_, va_context_id_, va_surface_id)); - CHECK_VAAPI(vaRenderPicture(va_display_, va_context_id_, &va_picture_parameter_buf_id_, 1)); - CHECK_VAAPI(vaRenderPicture(va_display_, va_context_id_, &va_quantization_matrix_buf_id_, 1)); - CHECK_VAAPI(vaRenderPicture(va_display_, va_context_id_, &va_huffmantable_buf_id_, 1)); - CHECK_VAAPI(vaRenderPicture(va_display_, va_context_id_, &va_slice_param_buf_id_, 1)); - CHECK_VAAPI(vaRenderPicture(va_display_, va_context_id_, &va_slice_data_buf_id_, 1)); - CHECK_VAAPI(vaEndPicture(va_display_, va_context_id_)); - - return ROCJPEG_STATUS_SUCCESS; -} - -RocJpegStatus RocJpegVappiDecoder::ExportSurface(VASurfaceID surface_id, VADRMPRIMESurfaceDescriptor &va_drm_prime_surface_desc) { - - bool is_surface_id_found = false; - int idx = 0; - for (idx = 0; idx < va_surface_ids_.size(); idx++) { - if (va_surface_ids_[idx] == surface_id) { - is_surface_id_found = true; - break; - } - } - if (!is_surface_id_found) { - return ROCJPEG_STATUS_INVALID_PARAMETER; - } - CHECK_VAAPI(vaExportSurfaceHandle(va_display_, surface_id, - VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2, - VA_EXPORT_SURFACE_READ_ONLY | - VA_EXPORT_SURFACE_SEPARATE_LAYERS, - &va_drm_prime_surface_desc)); + CHECK_VAAPI(vaBeginPicture(va_display_, va_context_id, surface_id)); + CHECK_VAAPI(vaRenderPicture(va_display_, va_context_id, &va_picture_parameter_buf_id_, 1)); + CHECK_VAAPI(vaRenderPicture(va_display_, va_context_id, &va_quantization_matrix_buf_id_, 1)); + CHECK_VAAPI(vaRenderPicture(va_display_, va_context_id, &va_huffmantable_buf_id_, 1)); + CHECK_VAAPI(vaRenderPicture(va_display_, va_context_id, &va_slice_param_buf_id_, 1)); + CHECK_VAAPI(vaRenderPicture(va_display_, va_context_id, &va_slice_data_buf_id_, 1)); + CHECK_VAAPI(vaEndPicture(va_display_, va_context_id)); return ROCJPEG_STATUS_SUCCESS; } RocJpegStatus RocJpegVappiDecoder::SyncSurface(VASurfaceID surface_id) { VASurfaceStatus surface_status; - bool is_surface_id_found = false; - int idx = 0; - - for (idx = 0; idx < va_surface_ids_.size(); idx++) { - if (va_surface_ids_[idx] == surface_id) { - is_surface_id_found = true; - break; - } - } - - if (!is_surface_id_found) { + if (!vaapi_mem_pool_->FindSurfaceId(surface_id)) { return ROCJPEG_STATUS_INVALID_PARAMETER; } @@ -343,25 +480,8 @@ RocJpegStatus RocJpegVappiDecoder::SyncSurface(VASurfaceID surface_id) { return ROCJPEG_STATUS_SUCCESS; } -RocJpegStatus RocJpegVappiDecoder::ReleaseSurface(VASurfaceID surface_id) { - bool is_surface_id_found = false; - int idx = 0; - - for (idx = 0; idx < va_surface_ids_.size(); idx++) { - if (va_surface_ids_[idx] == surface_id) { - is_surface_id_found = true; - break; - } - } - - if (!is_surface_id_found) { - return ROCJPEG_STATUS_INVALID_PARAMETER; - } - - CHECK_VAAPI(vaDestroySurfaces(va_display_, &va_surface_ids_[idx], 1)); - va_surface_ids_.erase(va_surface_ids_.begin() + idx); - - return ROCJPEG_STATUS_SUCCESS; +RocJpegStatus RocJpegVappiDecoder::GetHipInteropMem(VASurfaceID surface_id, HipInteropDeviceMem& hip_interop) { + return vaapi_mem_pool_->GetHipInteropMem(surface_id, hip_interop); } void RocJpegVappiDecoder::GetVisibleDevices(std::vector& visible_devices_vetor) { diff --git a/src/rocjpeg_vaapi_decoder.h b/src/rocjpeg_vaapi_decoder.h index 101c8061f4..53f9eb29f2 100644 --- a/src/rocjpeg_vaapi_decoder.h +++ b/src/rocjpeg_vaapi_decoder.h @@ -33,6 +33,7 @@ THE SOFTWARE. #include #include #include +#include #include #include #include @@ -57,15 +58,49 @@ typedef struct { bool can_roi_decode; } VcnJpegSpec; +struct HipInteropDeviceMem { + hipExternalMemory_t hip_ext_mem; // Interface to the vaapi-hip interop + uint8_t* hip_mapped_device_mem; // Mapped device memory for the YUV plane + uint32_t surface_format; // Pixel format fourcc of the whole surface + uint32_t width; // Width of the surface in pixels. + uint32_t height; // Height of the surface in pixels. + uint32_t offset[3]; // Offset of each plane + uint32_t pitch[3]; // Pitch of each plane + uint32_t num_layers; // Number of layers making up the surface +}; + +struct RocJpegVappiMemPoolEntry { + uint32_t image_width; + uint32_t image_height; + VASurfaceID va_surface_id; + VAContextID va_context_id; + HipInteropDeviceMem hip_interop; +}; + +class RocJpegVappiMemoryPool { + public: + RocJpegVappiMemoryPool(); + void ReleaseResources(); + void SetPoolSize(int32_t max_pool_size); + void SetVaapiDisplay(const VADisplay& va_display); + bool FindSurfaceId(VASurfaceID surface_id); + RocJpegVappiMemPoolEntry GetEntry(uint32_t surface_format, uint32_t image_width, uint32_t image_height); + RocJpegStatus AddPoolEntry(uint32_t surface_format, const RocJpegVappiMemPoolEntry& pool_entry); + RocJpegStatus DeleteSurfaceId(VASurfaceID surface_id); + RocJpegStatus GetHipInteropMem(VASurfaceID surface_id, HipInteropDeviceMem& hip_interop); + private: + VADisplay va_display_; + std::unordered_map> mem_pool_; +}; + class RocJpegVappiDecoder { public: RocJpegVappiDecoder(int device_id = 0); ~RocJpegVappiDecoder(); RocJpegStatus InitializeDecoder(std::string device_name, std::string gcn_arch_name, int device_id); RocJpegStatus SubmitDecode(const JpegStreamParameters *jpeg_stream_params, uint32_t &surface_id, RocJpegOutputFormat output_format); - RocJpegStatus ExportSurface(VASurfaceID surface_id, VADRMPRIMESurfaceDescriptor &va_drm_prime_surface_desc); RocJpegStatus SyncSurface(VASurfaceID surface_id); - RocJpegStatus ReleaseSurface(VASurfaceID surface_id); + RocJpegStatus GetHipInteropMem(VASurfaceID surface_id, HipInteropDeviceMem& hip_interop); private: int device_id_; int drm_fd_; @@ -77,9 +112,8 @@ private: std::vector va_config_attrib_; VAConfigID va_config_id_; VAProfile va_profile_; - VAContextID va_context_id_; - std::vector va_surface_ids_; std::unordered_map vcn_jpeg_spec_; + std::unique_ptr vaapi_mem_pool_; VcnJpegSpec current_vcn_jpeg_spec_; VABufferID va_picture_parameter_buf_id_; VABufferID va_quantization_matrix_buf_id_;