Add support for memory pool management for vaapi surfaces and vaapi-hip interops (#17)
* Add support for memory pool management for vaapi surfaces * reuse memories for each channel if the sizes remain unchanged * rename hip_interop to hip_interop_dev_mem
This commit is contained in:
committed by
GitHub
orang tua
6aaca70cd9
melakukan
694a4bc07f
@@ -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;
|
||||
}
|
||||
|
||||
+51
-96
@@ -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;
|
||||
}
|
||||
@@ -25,7 +25,6 @@ THE SOFTWARE.
|
||||
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
#include <hip/hip_runtime.h>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#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_
|
||||
@@ -22,10 +22,182 @@ THE SOFTWARE.
|
||||
|
||||
#include "rocjpeg_vaapi_decoder.h"
|
||||
|
||||
RocJpegVappiMemoryPool::RocJpegVappiMemoryPool() {
|
||||
std::vector<uint32_t> 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<RocJpegVappiMemPoolEntry>();
|
||||
}
|
||||
}
|
||||
|
||||
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<RocJpegVappiMemoryPool>()), 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<int>& visible_devices_vetor) {
|
||||
|
||||
@@ -33,6 +33,7 @@ THE SOFTWARE.
|
||||
#include <unistd.h>
|
||||
#include <filesystem>
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#include <va/va.h>
|
||||
#include <va/va_drm.h>
|
||||
#include <va/va_drmcommon.h>
|
||||
@@ -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<uint32_t, std::vector<RocJpegVappiMemPoolEntry>> 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<VAConfigAttrib> va_config_attrib_;
|
||||
VAConfigID va_config_id_;
|
||||
VAProfile va_profile_;
|
||||
VAContextID va_context_id_;
|
||||
std::vector<VASurfaceID> va_surface_ids_;
|
||||
std::unordered_map<std::string, VcnJpegSpec> vcn_jpeg_spec_;
|
||||
std::unique_ptr<RocJpegVappiMemoryPool> vaapi_mem_pool_;
|
||||
VcnJpegSpec current_vcn_jpeg_spec_;
|
||||
VABufferID va_picture_parameter_buf_id_;
|
||||
VABufferID va_quantization_matrix_buf_id_;
|
||||
|
||||
Reference in New Issue
Block a user