[FFmpeg-devel] [PATCH 4/7] hwcontext_opencl: Add support for mapping DRM objects to Beignet
Rostislav Pehlivanov
atomnuker at gmail.com
Mon Mar 12 01:59:35 EET 2018
On 11 March 2018 at 22:41, Mark Thompson <sw at jkqxz.net> wrote:
> Also use that to support mapping VAAPI to Beignet.
> ---
> configure | 16 +--
> libavutil/hwcontext_opencl.c | 264 +++++++++++++++++++++---------
> -------------
> 2 files changed, 138 insertions(+), 142 deletions(-)
>
> diff --git a/configure b/configure
> index 5e38bdab17..5051fd1abf 100755
> --- a/configure
> +++ b/configure
> @@ -2137,6 +2137,7 @@ HAVE_LIST="
> makeinfo_html
> opencl_d3d11
> opencl_drm_arm
> + opencl_drm_beignet
> opencl_dxva2
> opencl_vaapi_beignet
> opencl_vaapi_intel_media
> @@ -6223,9 +6224,15 @@ enabled vaapi &&
> check_cpp_condition "va/va.h" "VA_CHECK_VERSION(1, 0, 0)" &&
> enable vaapi_1
>
> -if enabled_all opencl vaapi ; then
> +if enabled_all opencl libdrm ; then
> check_type "CL/cl_intel.h" "clCreateImageFromFdINTEL_fn" &&
> - enable opencl_vaapi_beignet
> + enable opencl_drm_beignet
> + check_func_headers "CL/cl_ext.h" clImportMemoryARM &&
> + enable opencl_drm_arm
> +fi
> +
> +if enabled_all opencl vaapi ; then
> + enabled opencl_drm_beignet && enable opencl_vaapi_beignet
> if enabled libmfx ; then
> check_type "CL/cl.h CL/va_ext.h" "clCreateFromVA_APIMediaSurfaceINTEL_fn"
> &&
> enable opencl_vaapi_intel_media
> @@ -6242,11 +6249,6 @@ if enabled_all opencl d3d11va ; then
> enable opencl_d3d11
> fi
>
> -if enabled_all opencl libdrm ; then
> - check_func_headers "CL/cl_ext.h" clImportMemoryARM &&
> - enable opencl_drm_arm
> -fi
> -
> enabled vdpau &&
> check_cpp_condition vdpau/vdpau.h "defined VDP_DECODER_PROFILE_MPEG4_PART2_ASP"
> ||
> disable vdpau
> diff --git a/libavutil/hwcontext_opencl.c b/libavutil/hwcontext_opencl.c
> index a725a491e2..334f87344e 100644
> --- a/libavutil/hwcontext_opencl.c
> +++ b/libavutil/hwcontext_opencl.c
> @@ -37,6 +37,12 @@
> #include "hwcontext_vaapi.h"
> #endif
>
> +#if HAVE_OPENCL_DRM_BEIGNET
> +#include <unistd.h>
> +#include <CL/cl_intel.h>
> +#include "hwcontext_drm.h"
> +#endif
> +
> #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
> #include <mfx/mfxstructures.h>
> #include <va/va.h>
> @@ -74,9 +80,9 @@ typedef struct OpenCLDeviceContext {
> cl_platform_id platform_id;
>
> // Platform/device-specific functions.
> -#if HAVE_OPENCL_VAAPI_BEIGNET
> - int vaapi_mapping_usable;
> - clCreateImageFromFdINTEL_fn clCreateImageFromFdINTEL;
> +#if HAVE_OPENCL_DRM_BEIGNET
> + int beignet_drm_mapping_usable;
> + clCreateImageFromFdINTEL_fn clCreateImageFromFdINTEL;
> #endif
>
> #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
> @@ -685,19 +691,19 @@ static int opencl_device_init(AVHWDeviceContext
> *hwdev)
> } \
> } while (0)
>
> -#if HAVE_OPENCL_VAAPI_BEIGNET
> +#if HAVE_OPENCL_DRM_BEIGNET
> {
> int fail = 0;
>
> CL_FUNC(clCreateImageFromFdINTEL,
> - "Intel DRM to OpenCL image mapping");
> + "Beignet DRM to OpenCL image mapping");
>
> if (fail) {
> - av_log(hwdev, AV_LOG_WARNING, "VAAPI to OpenCL mapping "
> - "not usable.\n");
> - priv->vaapi_mapping_usable = 0;
> + av_log(hwdev, AV_LOG_WARNING, "Beignet DRM to OpenCL "
> + "mapping not usable.\n");
> + priv->beignet_drm_mapping_usable = 0;
> } else {
> - priv->vaapi_mapping_usable = 1;
> + priv->beignet_drm_mapping_usable = 1;
> }
> }
> #endif
> @@ -1187,7 +1193,8 @@ static int opencl_device_derive(AVHWDeviceContext
> *hwdev,
> int err;
> switch (src_ctx->type) {
>
> -#if HAVE_OPENCL_VAAPI_BEIGNET
> +#if HAVE_OPENCL_DRM_BEIGNET
> + case AV_HWDEVICE_TYPE_DRM:
> case AV_HWDEVICE_TYPE_VAAPI:
> {
> // Surface mapping works via DRM PRIME fds with no special
> @@ -2028,175 +2035,151 @@ fail:
> return err;
> }
>
> -#if HAVE_OPENCL_VAAPI_BEIGNET
> +#if HAVE_OPENCL_DRM_BEIGNET
>
> -typedef struct VAAPItoOpenCLMapping {
> - VAImage va_image;
> - VABufferInfo va_buffer_info;
> +typedef struct DRMBeignetToOpenCLMapping {
> + AVFrame *drm_frame;
> + AVDRMFrameDescriptor *drm_desc;
>
> AVOpenCLFrameDescriptor frame;
> -} VAAPItoOpenCLMapping;
> +} DRMBeignetToOpenCLMapping;
>
> -static void opencl_unmap_from_vaapi(AVHWFramesContext *src_fc,
> - HWMapDescriptor *hwmap)
> +static void opencl_unmap_from_drm_beignet(AVHWFramesContext *dst_fc,
> + HWMapDescriptor *hwmap)
> {
> - VAAPItoOpenCLMapping *mapping = hwmap->priv;
> - AVVAAPIDeviceContext *src_dev = src_fc->device_ctx->hwctx;
> - VASurfaceID surface_id;
> - VAStatus vas;
> + DRMBeignetToOpenCLMapping *mapping = hwmap->priv;
> cl_int cle;
> int i;
>
> - surface_id = (VASurfaceID)(uintptr_t)hwmap->source->data[3];
> - av_log(src_fc, AV_LOG_DEBUG, "Unmap VAAPI surface %#x from OpenCL.\n",
> - surface_id);
> -
> for (i = 0; i < mapping->frame.nb_planes; i++) {
> cle = clReleaseMemObject(mapping->frame.planes[i]);
> if (cle != CL_SUCCESS) {
> - av_log(src_fc, AV_LOG_ERROR, "Failed to release CL "
> - "buffer of plane %d of VA image %#x (derived "
> - "from surface %#x): %d.\n", i,
> - mapping->va_image.buf, surface_id, cle);
> + av_log(dst_fc, AV_LOG_ERROR, "Failed to release CL image "
> + "of plane %d of DRM frame: %d.\n", i, cle);
> }
> }
>
> - vas = vaReleaseBufferHandle(src_dev->display,
> - mapping->va_image.buf);
> - if (vas != VA_STATUS_SUCCESS) {
> - av_log(src_fc, AV_LOG_ERROR, "Failed to release buffer "
> - "handle of image %#x (derived from surface %#x): "
> - "%d (%s).\n", mapping->va_image.buf, surface_id,
> - vas, vaErrorStr(vas));
> - }
> -
> - vas = vaDestroyImage(src_dev->display,
> - mapping->va_image.image_id);
> - if (vas != VA_STATUS_SUCCESS) {
> - av_log(src_fc, AV_LOG_ERROR, "Failed to destroy image "
> - "derived from surface %#x: %d (%s).\n",
> - surface_id, vas, vaErrorStr(vas));
> - }
> -
> av_free(mapping);
> }
>
> -static int opencl_map_from_vaapi(AVHWFramesContext *dst_fc, AVFrame *dst,
> - const AVFrame *src, int flags)
> +static int opencl_map_from_drm_beignet(AVHWFramesContext *dst_fc,
> + AVFrame *dst, const AVFrame *src,
> + int flags)
> {
> - AVHWFramesContext *src_fc =
> - (AVHWFramesContext*)src->hw_frames_ctx->data;
> - AVVAAPIDeviceContext *src_dev = src_fc->device_ctx->hwctx;
> - AVOpenCLDeviceContext *dst_dev = dst_fc->device_ctx->hwctx;
> - OpenCLDeviceContext *priv = dst_fc->device_ctx->internal->priv;
> - VAAPItoOpenCLMapping *mapping = NULL;
> - VASurfaceID surface_id;
> - VAStatus vas;
> + AVOpenCLDeviceContext *hwctx = dst_fc->device_ctx->hwctx;
> + OpenCLDeviceContext *priv = dst_fc->device_ctx->internal->priv;
> + DRMBeignetToOpenCLMapping *mapping;
> + const AVDRMFrameDescriptor *desc;
> cl_int cle;
> - int err, p;
> + int err, i, j, p;
>
> - surface_id = (VASurfaceID)(uintptr_t)src->data[3];
> - av_log(src_fc, AV_LOG_DEBUG, "Map VAAPI surface %#x to OpenCL.\n",
> - surface_id);
> + desc = (const AVDRMFrameDescriptor*)src->data[0];
>
> mapping = av_mallocz(sizeof(*mapping));
> if (!mapping)
> return AVERROR(ENOMEM);
>
> - vas = vaDeriveImage(src_dev->display, surface_id,
> - &mapping->va_image);
> - if (vas != VA_STATUS_SUCCESS) {
> - av_log(src_fc, AV_LOG_ERROR, "Failed to derive image from "
> - "surface %#x: %d (%s).\n",
> - surface_id, vas, vaErrorStr(vas));
> - err = AVERROR(EIO);
> - goto fail;
> - }
> -
> - mapping->va_buffer_info.mem_type =
> - VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
> -
> - vas = vaAcquireBufferHandle(src_dev->display,
> - mapping->va_image.buf,
> - &mapping->va_buffer_info);
> - if (vas != VA_STATUS_SUCCESS) {
> - av_log(src_fc, AV_LOG_ERROR, "Failed to get buffer "
> - "handle from image %#x (derived from surface %#x): "
> - "%d (%s).\n", mapping->va_image.buf, surface_id,
> - vas, vaErrorStr(vas));
> - vaDestroyImage(src_dev->display, mapping->va_image.buf);
> - err = AVERROR(EIO);
> - goto fail_derived;
> - }
> -
> - av_log(dst_fc, AV_LOG_DEBUG, "DRM PRIME fd is %ld.\n",
> - mapping->va_buffer_info.handle);
> + p = 0;
> + for (i = 0; i < desc->nb_layers; i++) {
> + const AVDRMLayerDescriptor *layer = &desc->layers[i];
> + for (j = 0; j < layer->nb_planes; j++) {
> + const AVDRMPlaneDescriptor *plane = &layer->planes[j];
> + const AVDRMObjectDescriptor *object =
> + &desc->objects[plane->object_index];
> +
> + cl_import_image_info_intel image_info = {
> + .fd = object->fd,
> + .size = object->size,
> + .type = CL_MEM_OBJECT_IMAGE2D,
> + .offset = plane->offset,
> + .row_pitch = plane->pitch,
> + };
> + cl_image_desc image_desc;
>
> - mapping->frame.nb_planes = mapping->va_image.num_planes;
> - for (p = 0; p < mapping->frame.nb_planes; p++) {
> - cl_import_image_info_intel image_info = {
> - .fd = mapping->va_buffer_info.handle,
> - .size = mapping->va_buffer_info.mem_size,
> - .type = CL_MEM_OBJECT_IMAGE2D,
> - .offset = mapping->va_image.offsets[p],
> - .row_pitch = mapping->va_image.pitches[p],
> - };
> - cl_image_desc image_desc;
> + err = opencl_get_plane_format(dst_fc->sw_format, p,
> + src->width, src->height,
> + &image_info.fmt,
> + &image_desc);
> + if (err < 0) {
> + av_log(dst_fc, AV_LOG_ERROR, "DRM frame layer %d "
> + "plane %d is not representable in OpenCL: %d.\n",
> + i, j, err);
> + goto fail;
> + }
> + image_info.width = image_desc.image_width;
> + image_info.height = image_desc.image_height;
> +
> + mapping->frame.planes[p] =
> + priv->clCreateImageFromFdINTEL(hwctx->context,
> + &image_info, &cle);
> + if (!mapping->frame.planes[p]) {
> + av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL image "
> + "from layer %d plane %d of DRM frame: %d.\n",
> + i, j, cle);
> + err = AVERROR(EIO);
> + goto fail;
> + }
>
> - err = opencl_get_plane_format(src_fc->sw_format, p,
> - mapping->va_image.width,
> - mapping->va_image.height,
> - &image_info.fmt,
> - &image_desc);
> - if (err < 0) {
> - av_log(dst_fc, AV_LOG_ERROR, "VA %#x (derived from "
> - "surface %#x) has invalid parameters: %d.\n",
> - mapping->va_image.buf, surface_id, err);
> - goto fail_mapped;
> + dst->data[p] = (uint8_t*)mapping->frame.planes[p];
> + mapping->frame.nb_planes = ++p;
> }
> - image_info.width = image_desc.image_width;
> - image_info.height = image_desc.image_height;
> -
> - mapping->frame.planes[p] =
> - priv->clCreateImageFromFdINTEL(dst_dev->context,
> - &image_info, &cle);
> - if (!mapping->frame.planes[p]) {
> - av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL image "
> - "from plane %d of VA image %#x (derived from "
> - "surface %#x): %d.\n", p,
> - mapping->va_image.buf, surface_id, cle);
> - err = AVERROR(EIO);
> - goto fail_mapped;
> - }
> -
> - dst->data[p] = (uint8_t*)mapping->frame.planes[p];
> }
>
> - err = ff_hwframe_map_create(src->hw_frames_ctx,
> - dst, src, &opencl_unmap_from_vaapi,
> + err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src,
> + &opencl_unmap_from_drm_beignet,
> mapping);
> if (err < 0)
> - goto fail_mapped;
> + goto fail;
>
> dst->width = src->width;
> dst->height = src->height;
>
> return 0;
>
> -fail_mapped:
> +fail:
> for (p = 0; p < mapping->frame.nb_planes; p++) {
> if (mapping->frame.planes[p])
> clReleaseMemObject(mapping->frame.planes[p]);
> }
> - vaReleaseBufferHandle(src_dev->display, mapping->va_image.buf);
> -fail_derived:
> - vaDestroyImage(src_dev->display, mapping->va_image.image_id);
> + return err;
> +}
> +
> +#if HAVE_OPENCL_VAAPI_BEIGNET
> +
> +static int opencl_map_from_vaapi(AVHWFramesContext *dst_fc,
> + AVFrame *dst, const AVFrame *src,
> + int flags)
> +{
> + HWMapDescriptor *hwmap;
> + AVFrame *tmp;
> + int err;
> +
> + tmp = av_frame_alloc();
> + if (!tmp)
> + return AVERROR(ENOMEM);
> +
> + tmp->format = AV_PIX_FMT_DRM_PRIME;
> +
> + err = av_hwframe_map(tmp, src, flags);
> + if (err < 0)
> + goto fail;
> +
> + err = opencl_map_from_drm_beignet(dst_fc, dst, tmp, flags);
> + if (err < 0)
> + goto fail;
> +
> + // Adjust the map descriptor so that unmap works correctly.
> + hwmap = (HWMapDescriptor*)dst->buf[0]->data;
> + av_frame_unref(hwmap->source);
> + err = av_frame_ref(hwmap->source, src);
> +
> fail:
> - av_freep(&mapping);
> + av_frame_free(&tmp);
> return err;
> }
>
> -#endif
> +#endif /* HAVE_OPENCL_VAAPI_BEIGNET */
> +#endif /* HAVE_OPENCL_DRM_BEIGNET */
>
> static inline cl_mem_flags opencl_mem_flags_for_mapping(int map_flags)
> {
> @@ -2826,9 +2809,14 @@ static int opencl_map_to(AVHWFramesContext *hwfc,
> AVFrame *dst,
> OpenCLDeviceContext *priv = hwfc->device_ctx->internal->priv;
> av_assert0(dst->format == AV_PIX_FMT_OPENCL);
> switch (src->format) {
> +#if HAVE_OPENCL_DRM_BEIGNET
> + case AV_PIX_FMT_DRM_PRIME:
> + if (priv->beignet_drm_mapping_usable)
> + return opencl_map_from_drm_beignet(hwfc, dst, src, flags);
> +#endif
> #if HAVE_OPENCL_VAAPI_BEIGNET
> case AV_PIX_FMT_VAAPI:
> - if (priv->vaapi_mapping_usable)
> + if (priv->beignet_drm_mapping_usable)
> return opencl_map_from_vaapi(hwfc, dst, src, flags);
> #endif
> #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
> @@ -2861,9 +2849,15 @@ static int opencl_frames_derive_to(AVHWFramesContext
> *dst_fc,
> {
> OpenCLDeviceContext *priv = dst_fc->device_ctx->internal->priv;
> switch (src_fc->device_ctx->type) {
> +#if HAVE_OPENCL_DRM_BEIGNET
> + case AV_HWDEVICE_TYPE_DRM:
> + if (!priv->beignet_drm_mapping_usable)
> + return AVERROR(ENOSYS);
> + break;
> +#endif
> #if HAVE_OPENCL_VAAPI_BEIGNET
> case AV_HWDEVICE_TYPE_VAAPI:
> - if (!priv->vaapi_mapping_usable)
> + if (!priv->beignet_drm_mapping_usable)
> return AVERROR(ENOSYS);
> break;
> #endif
> --
> 2.16.1
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
Doesn't seem to work, at least on my machine:
DRM frame layer 0 plane 0 is not representable in OpenCL: -22
More information about the ffmpeg-devel
mailing list