]> git.sesse.net Git - ffmpeg/blobdiff - libavutil/hwcontext_opencl.c
Merge commit 'f8060865f3e1a16c62e0d337ef0979b6ee4ba457'
[ffmpeg] / libavutil / hwcontext_opencl.c
index a725a491e25f662e58b3e3939eaf595979e0228d..728877553f8207aa81a3b5f49c129bfe86dc23e0 100644 (file)
@@ -16,6 +16,8 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#define CL_USE_DEPRECATED_OPENCL_1_2_APIS
+
 #include <string.h>
 
 #include "config.h"
 #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
+#if CONFIG_LIBMFX
 #include <mfx/mfxstructures.h>
+#endif
 #include <va/va.h>
 #include <CL/va_ext.h>
 #include "hwcontext_vaapi.h"
@@ -74,9 +84,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
@@ -133,9 +143,10 @@ typedef struct OpenCLFramesContext {
 } OpenCLFramesContext;
 
 
-static void opencl_error_callback(const char *errinfo,
-                                  const void *private_info, size_t cb,
-                                  void *user_data)
+static void CL_CALLBACK opencl_error_callback(const char *errinfo,
+                                              const void *private_info,
+                                              size_t cb,
+                                              void *user_data)
 {
     AVHWDeviceContext *ctx = user_data;
     av_log(ctx, AV_LOG_ERROR, "OpenCL error: %s\n", errinfo);
@@ -685,19 +696,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
@@ -917,7 +928,6 @@ static int opencl_enumerate_intel_media_vaapi_devices(AVHWDeviceContext *hwdev,
     clGetDeviceIDsFromVA_APIMediaAdapterINTEL_fn
         clGetDeviceIDsFromVA_APIMediaAdapterINTEL;
     cl_int cle;
-    int err;
 
     clGetDeviceIDsFromVA_APIMediaAdapterINTEL =
         clGetExtensionFunctionAddressForPlatform(platform_id,
@@ -1187,7 +1197,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
@@ -1349,10 +1360,7 @@ static int opencl_device_derive(AVHWDeviceContext *hwdev,
         break;
     }
 
-    if (err < 0)
-        return err;
-
-    return opencl_device_init(hwdev);
+    return err;
 }
 
 static int opencl_get_plane_format(enum AVPixelFormat pixfmt,
@@ -2028,175 +2036,148 @@ 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;
-        }
-        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];
+            mapping->frame.nb_planes = ++p;
         }
-
-        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);
+    av_free(mapping);
+    return err;
+}
+
+#if HAVE_OPENCL_VAAPI_BEIGNET
+
+static int opencl_map_from_vaapi(AVHWFramesContext *dst_fc,
+                                 AVFrame *dst, const AVFrame *src,
+                                 int flags)
+{
+    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;
+
+    err = ff_hwframe_map_replace(dst, 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)
 {
@@ -2262,10 +2243,13 @@ static int opencl_map_from_qsv(AVHWFramesContext *dst_fc, AVFrame *dst,
     cl_int cle;
     int err, p;
 
+#if CONFIG_LIBMFX
     if (src->format == AV_PIX_FMT_QSV) {
         mfxFrameSurface1 *mfx_surface = (mfxFrameSurface1*)src->data[3];
         va_surface = *(VASurfaceID*)mfx_surface->Data.MemId;
-    } else if (src->format == AV_PIX_FMT_VAAPI) {
+    } else
+#endif
+        if (src->format == AV_PIX_FMT_VAAPI) {
         va_surface = (VASurfaceID)(uintptr_t)src->data[3];
     } else {
         return AVERROR(ENOSYS);
@@ -2823,12 +2807,17 @@ static int opencl_map_from(AVHWFramesContext *hwfc, AVFrame *dst,
 static int opencl_map_to(AVHWFramesContext *hwfc, AVFrame *dst,
                          const AVFrame *src, int flags)
 {
-    OpenCLDeviceContext *priv = hwfc->device_ctx->internal->priv;
+    av_unused 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
@@ -2859,11 +2848,17 @@ static int opencl_map_to(AVHWFramesContext *hwfc, AVFrame *dst,
 static int opencl_frames_derive_to(AVHWFramesContext *dst_fc,
                                    AVHWFramesContext *src_fc, int flags)
 {
-    OpenCLDeviceContext *priv = dst_fc->device_ctx->internal->priv;
+    av_unused 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