diff options
author | Zhao Zhili <zhilizhao@tencent.com> | 2024-02-23 22:11:43 +0800 |
---|---|---|
committer | Zhao Zhili <zhilizhao@tencent.com> | 2024-03-01 17:24:00 +0800 |
commit | f7545e90dfda0d1e49b6dcce43bf96741c9ecaed (patch) | |
tree | 994da3f5ae6e4a01fa3ca3939074c0bf4a9bcd45 /libavutil | |
parent | dcfc6089b1ea06fdcdf7778b881406b929a83cba (diff) |
avutil/hwcontext_opencl: Add map from Videotoolbox to OpenCL
For example:
./ffmpeg -hwaccel videotoolbox \
-hwaccel_output_format videotoolbox_vld \
-i foo.mp4 \
-vf hwmap=derive_device=opencl,transpose_opencl=dir=clock,hwmap,format=nv12 \
-c:v hevc_videotoolbox \
-c:a copy \
-b:v 2M -tag:v hvc1 bar.mp4
Signed-off-by: Zhao Zhili <zhilizhao@tencent.com>
Diffstat (limited to 'libavutil')
-rw-r--r-- | libavutil/hwcontext_opencl.c | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/libavutil/hwcontext_opencl.c b/libavutil/hwcontext_opencl.c index de093fffb1..efd8d0e094 100644 --- a/libavutil/hwcontext_opencl.c +++ b/libavutil/hwcontext_opencl.c @@ -72,6 +72,11 @@ #include "hwcontext_drm.h" #endif +#if HAVE_OPENCL_VIDEOTOOLBOX +#include <OpenCL/cl_gl_ext.h> +#include <VideoToolbox/VideoToolbox.h> +#endif + #if HAVE_OPENCL_VAAPI_INTEL_MEDIA && CONFIG_LIBMFX extern int ff_qsv_get_surface_base_handle(mfxFrameSurface1 *surf, enum AVHWDeviceType base_dev_typ, @@ -1364,6 +1369,12 @@ static int opencl_device_derive(AVHWDeviceContext *hwdev, break; #endif +#if HAVE_OPENCL_VIDEOTOOLBOX + case AV_HWDEVICE_TYPE_VIDEOTOOLBOX: + err = opencl_device_create(hwdev, NULL, NULL, 0); + break; +#endif + default: err = AVERROR(ENOSYS); break; @@ -2819,6 +2830,84 @@ fail: #endif +#if HAVE_OPENCL_VIDEOTOOLBOX + +static void opencl_unmap_from_vt(AVHWFramesContext *hwfc, + HWMapDescriptor *hwmap) +{ + uint8_t *desc = hwmap->priv; + opencl_pool_free(hwfc, desc); +} + +static int opencl_map_from_vt(AVHWFramesContext *dst_fc, AVFrame *dst, + const AVFrame *src, int flags) +{ + CVPixelBufferRef pixbuf = (CVPixelBufferRef) src->data[3]; + IOSurfaceRef io_surface_ref = CVPixelBufferGetIOSurface(pixbuf); + cl_int err = 0; + AVOpenCLFrameDescriptor *desc = NULL; + AVOpenCLDeviceContext *dst_dev = dst_fc->device_ctx->hwctx; + + if (!io_surface_ref) { + av_log(dst_fc, AV_LOG_ERROR, "Failed to get IOSurfaceRef\n"); + return AVERROR_EXTERNAL; + } + + desc = av_mallocz(sizeof(*desc)); + if (!desc) + return AVERROR(ENOMEM); + + for (int p = 0;; p++) { + cl_image_format image_format; + cl_image_desc image_desc; + cl_iosurface_properties_APPLE props[] = { + CL_IOSURFACE_REF_APPLE, (cl_iosurface_properties_APPLE) io_surface_ref, + CL_IOSURFACE_PLANE_APPLE, p, + 0 + }; + + err = opencl_get_plane_format(dst_fc->sw_format, p, + src->width, src->height, + &image_format, &image_desc); + if (err == AVERROR(ENOENT)) + break; + if (err < 0) + goto fail; + + desc->planes[p] = clCreateImageFromIOSurfaceWithPropertiesAPPLE(dst_dev->context, + opencl_mem_flags_for_mapping(flags), + &image_format, &image_desc, + props, &err); + if (!desc->planes[p]) { + av_log(dst_fc, AV_LOG_ERROR, "Failed to create image from IOSurfaceRef\n"); + err = AVERROR(EIO); + goto fail; + } + desc->nb_planes++; + } + + for (int i = 0; i < desc->nb_planes; i++) + dst->data[i] = (uint8_t *) desc->planes[i]; + + err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src, + opencl_unmap_from_vt, desc); + if (err < 0) + goto fail; + + dst->width = src->width; + dst->height = src->height; + + return 0; + +fail: + for (int i = 0; i < desc->nb_planes; i++) + clReleaseMemObject(desc->planes[i]); + av_freep(&desc); + return err; +} + +#endif + static int opencl_map_from(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags) { @@ -2865,6 +2954,10 @@ static int opencl_map_to(AVHWFramesContext *hwfc, AVFrame *dst, if (priv->drm_arm_mapping_usable) return opencl_map_from_drm_arm(hwfc, dst, src, flags); #endif +#if HAVE_OPENCL_VIDEOTOOLBOX + case AV_PIX_FMT_VIDEOTOOLBOX: + return opencl_map_from_vt(hwfc, dst, src, flags); +#endif } return AVERROR(ENOSYS); } @@ -2923,6 +3016,10 @@ static int opencl_frames_derive_to(AVHWFramesContext *dst_fc, return AVERROR(ENOSYS); break; #endif +#if HAVE_OPENCL_VIDEOTOOLBOX + case AV_HWDEVICE_TYPE_VIDEOTOOLBOX: + break; +#endif default: return AVERROR(ENOSYS); } |