Message ID | 20180311224156.23986-4-sw@jkqxz.net |
---|---|
State | Superseded |
Headers | show |
On 11 March 2018 at 22:41, Mark Thompson <sw@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@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
On 11/03/18 23:59, Rostislav Pehlivanov wrote: > On 11 March 2018 at 22:41, Mark Thompson <sw@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(-) >> >> ... >> > > Doesn't seem to work, at least on my machine: > DRM frame layer 0 plane 0 is not representable in OpenCL: -22 What driver and input/output formats are you using? What are the versions of all the relevant components, so I can maybe try to reproduce it? (beignet, i965, libva, mesa, libdrm, .. others?) - Mark
On 12/03/18 00:22, Mark Thompson wrote: > On 11/03/18 23:59, Rostislav Pehlivanov wrote: >> On 11 March 2018 at 22:41, Mark Thompson <sw@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(-) >>> >>> ... >>> >> >> Doesn't seem to work, at least on my machine: >> DRM frame layer 0 plane 0 is not representable in OpenCL: -22 > > What driver and input/output formats are you using? What are the versions of all the relevant components, so I can maybe try to reproduce it? (beignet, i965, libva, mesa, libdrm, .. others?) Fixed in discussion on IRC - BGR0 from kmsgrab is not a valid format for OpenCL because of the padding, using BGRA instead works. - Mark
On 12 March 2018 at 12:30, Mark Thompson <sw@jkqxz.net> wrote: > On 12/03/18 00:22, Mark Thompson wrote: > > On 11/03/18 23:59, Rostislav Pehlivanov wrote: > >> On 11 March 2018 at 22:41, Mark Thompson <sw@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(-) > >>> > >>> ... > >>> > >> > >> Doesn't seem to work, at least on my machine: > >> DRM frame layer 0 plane 0 is not representable in OpenCL: -22 > > > > What driver and input/output formats are you using? What are the > versions of all the relevant components, so I can maybe try to reproduce > it? (beignet, i965, libva, mesa, libdrm, .. others?) > > Fixed in discussion on IRC - BGR0 from kmsgrab is not a valid format for > OpenCL because of the padding, using BGRA instead works. > > - Mark > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel > Patch LGTM
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