1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * This file is part of FFmpeg. 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 5cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 6cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 7cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 8cabdff1aSopenharmony_ci * 9cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 10cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 11cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12cabdff1aSopenharmony_ci * Lesser General Public License for more details. 13cabdff1aSopenharmony_ci * 14cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 15cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 16cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17cabdff1aSopenharmony_ci */ 18cabdff1aSopenharmony_ci 19cabdff1aSopenharmony_ci#define CL_USE_DEPRECATED_OPENCL_1_2_APIS 20cabdff1aSopenharmony_ci 21cabdff1aSopenharmony_ci#include <string.h> 22cabdff1aSopenharmony_ci 23cabdff1aSopenharmony_ci#include "config.h" 24cabdff1aSopenharmony_ci 25cabdff1aSopenharmony_ci#include "avassert.h" 26cabdff1aSopenharmony_ci#include "avstring.h" 27cabdff1aSopenharmony_ci#include "common.h" 28cabdff1aSopenharmony_ci#include "hwcontext.h" 29cabdff1aSopenharmony_ci#include "hwcontext_internal.h" 30cabdff1aSopenharmony_ci#include "hwcontext_opencl.h" 31cabdff1aSopenharmony_ci#include "mem.h" 32cabdff1aSopenharmony_ci#include "pixdesc.h" 33cabdff1aSopenharmony_ci 34cabdff1aSopenharmony_ci#if HAVE_OPENCL_VAAPI_BEIGNET 35cabdff1aSopenharmony_ci#include <unistd.h> 36cabdff1aSopenharmony_ci#include <va/va.h> 37cabdff1aSopenharmony_ci#include <va/va_drmcommon.h> 38cabdff1aSopenharmony_ci#include <CL/cl_intel.h> 39cabdff1aSopenharmony_ci#include "hwcontext_vaapi.h" 40cabdff1aSopenharmony_ci#endif 41cabdff1aSopenharmony_ci 42cabdff1aSopenharmony_ci#if HAVE_OPENCL_DRM_BEIGNET 43cabdff1aSopenharmony_ci#include <unistd.h> 44cabdff1aSopenharmony_ci#include <CL/cl_intel.h> 45cabdff1aSopenharmony_ci#include "hwcontext_drm.h" 46cabdff1aSopenharmony_ci#endif 47cabdff1aSopenharmony_ci 48cabdff1aSopenharmony_ci#if HAVE_OPENCL_VAAPI_INTEL_MEDIA 49cabdff1aSopenharmony_ci#if CONFIG_LIBMFX 50cabdff1aSopenharmony_ci#include <mfx/mfxstructures.h> 51cabdff1aSopenharmony_ci#endif 52cabdff1aSopenharmony_ci#include <va/va.h> 53cabdff1aSopenharmony_ci#include <CL/cl_va_api_media_sharing_intel.h> 54cabdff1aSopenharmony_ci#include "hwcontext_vaapi.h" 55cabdff1aSopenharmony_ci#endif 56cabdff1aSopenharmony_ci 57cabdff1aSopenharmony_ci#if HAVE_OPENCL_DXVA2 58cabdff1aSopenharmony_ci#define COBJMACROS 59cabdff1aSopenharmony_ci#include <CL/cl_dx9_media_sharing.h> 60cabdff1aSopenharmony_ci#include <dxva2api.h> 61cabdff1aSopenharmony_ci#include "hwcontext_dxva2.h" 62cabdff1aSopenharmony_ci#endif 63cabdff1aSopenharmony_ci 64cabdff1aSopenharmony_ci#if HAVE_OPENCL_D3D11 65cabdff1aSopenharmony_ci#include <CL/cl_d3d11.h> 66cabdff1aSopenharmony_ci#include "hwcontext_d3d11va.h" 67cabdff1aSopenharmony_ci#endif 68cabdff1aSopenharmony_ci 69cabdff1aSopenharmony_ci#if HAVE_OPENCL_DRM_ARM 70cabdff1aSopenharmony_ci#include <CL/cl_ext.h> 71cabdff1aSopenharmony_ci#include <drm_fourcc.h> 72cabdff1aSopenharmony_ci#include "hwcontext_drm.h" 73cabdff1aSopenharmony_ci#endif 74cabdff1aSopenharmony_ci 75cabdff1aSopenharmony_ci#if HAVE_OPENCL_VAAPI_INTEL_MEDIA && CONFIG_LIBMFX 76cabdff1aSopenharmony_ciextern int ff_qsv_get_surface_base_handle(mfxFrameSurface1 *surf, 77cabdff1aSopenharmony_ci enum AVHWDeviceType base_dev_typ, 78cabdff1aSopenharmony_ci void **base_handle); 79cabdff1aSopenharmony_ci#endif 80cabdff1aSopenharmony_ci 81cabdff1aSopenharmony_ci 82cabdff1aSopenharmony_citypedef struct OpenCLDeviceContext { 83cabdff1aSopenharmony_ci // Default command queue to use for transfer/mapping operations on 84cabdff1aSopenharmony_ci // the device. If the user supplies one, this is a reference to it. 85cabdff1aSopenharmony_ci // Otherwise, it is newly-created. 86cabdff1aSopenharmony_ci cl_command_queue command_queue; 87cabdff1aSopenharmony_ci 88cabdff1aSopenharmony_ci // The platform the context exists on. This is needed to query and 89cabdff1aSopenharmony_ci // retrieve extension functions. 90cabdff1aSopenharmony_ci cl_platform_id platform_id; 91cabdff1aSopenharmony_ci 92cabdff1aSopenharmony_ci // Platform/device-specific functions. 93cabdff1aSopenharmony_ci#if HAVE_OPENCL_DRM_BEIGNET 94cabdff1aSopenharmony_ci int beignet_drm_mapping_usable; 95cabdff1aSopenharmony_ci clCreateImageFromFdINTEL_fn clCreateImageFromFdINTEL; 96cabdff1aSopenharmony_ci#endif 97cabdff1aSopenharmony_ci 98cabdff1aSopenharmony_ci#if HAVE_OPENCL_VAAPI_INTEL_MEDIA 99cabdff1aSopenharmony_ci int qsv_mapping_usable; 100cabdff1aSopenharmony_ci clCreateFromVA_APIMediaSurfaceINTEL_fn 101cabdff1aSopenharmony_ci clCreateFromVA_APIMediaSurfaceINTEL; 102cabdff1aSopenharmony_ci clEnqueueAcquireVA_APIMediaSurfacesINTEL_fn 103cabdff1aSopenharmony_ci clEnqueueAcquireVA_APIMediaSurfacesINTEL; 104cabdff1aSopenharmony_ci clEnqueueReleaseVA_APIMediaSurfacesINTEL_fn 105cabdff1aSopenharmony_ci clEnqueueReleaseVA_APIMediaSurfacesINTEL; 106cabdff1aSopenharmony_ci#endif 107cabdff1aSopenharmony_ci 108cabdff1aSopenharmony_ci#if HAVE_OPENCL_DXVA2 109cabdff1aSopenharmony_ci int dxva2_mapping_usable; 110cabdff1aSopenharmony_ci cl_dx9_media_adapter_type_khr dx9_media_adapter_type; 111cabdff1aSopenharmony_ci 112cabdff1aSopenharmony_ci clCreateFromDX9MediaSurfaceKHR_fn 113cabdff1aSopenharmony_ci clCreateFromDX9MediaSurfaceKHR; 114cabdff1aSopenharmony_ci clEnqueueAcquireDX9MediaSurfacesKHR_fn 115cabdff1aSopenharmony_ci clEnqueueAcquireDX9MediaSurfacesKHR; 116cabdff1aSopenharmony_ci clEnqueueReleaseDX9MediaSurfacesKHR_fn 117cabdff1aSopenharmony_ci clEnqueueReleaseDX9MediaSurfacesKHR; 118cabdff1aSopenharmony_ci#endif 119cabdff1aSopenharmony_ci 120cabdff1aSopenharmony_ci#if HAVE_OPENCL_D3D11 121cabdff1aSopenharmony_ci int d3d11_mapping_usable; 122cabdff1aSopenharmony_ci clCreateFromD3D11Texture2DKHR_fn 123cabdff1aSopenharmony_ci clCreateFromD3D11Texture2DKHR; 124cabdff1aSopenharmony_ci clEnqueueAcquireD3D11ObjectsKHR_fn 125cabdff1aSopenharmony_ci clEnqueueAcquireD3D11ObjectsKHR; 126cabdff1aSopenharmony_ci clEnqueueReleaseD3D11ObjectsKHR_fn 127cabdff1aSopenharmony_ci clEnqueueReleaseD3D11ObjectsKHR; 128cabdff1aSopenharmony_ci#endif 129cabdff1aSopenharmony_ci 130cabdff1aSopenharmony_ci#if HAVE_OPENCL_DRM_ARM 131cabdff1aSopenharmony_ci int drm_arm_mapping_usable; 132cabdff1aSopenharmony_ci#endif 133cabdff1aSopenharmony_ci} OpenCLDeviceContext; 134cabdff1aSopenharmony_ci 135cabdff1aSopenharmony_citypedef struct OpenCLFramesContext { 136cabdff1aSopenharmony_ci // Command queue used for transfer/mapping operations on this frames 137cabdff1aSopenharmony_ci // context. If the user supplies one, this is a reference to it. 138cabdff1aSopenharmony_ci // Otherwise, it is a reference to the default command queue for the 139cabdff1aSopenharmony_ci // device. 140cabdff1aSopenharmony_ci cl_command_queue command_queue; 141cabdff1aSopenharmony_ci 142cabdff1aSopenharmony_ci#if HAVE_OPENCL_DXVA2 || HAVE_OPENCL_D3D11 143cabdff1aSopenharmony_ci // For mapping APIs which have separate creation and acquire/release 144cabdff1aSopenharmony_ci // steps, this stores the OpenCL memory objects corresponding to each 145cabdff1aSopenharmony_ci // frame. 146cabdff1aSopenharmony_ci int nb_mapped_frames; 147cabdff1aSopenharmony_ci AVOpenCLFrameDescriptor *mapped_frames; 148cabdff1aSopenharmony_ci#endif 149cabdff1aSopenharmony_ci} OpenCLFramesContext; 150cabdff1aSopenharmony_ci 151cabdff1aSopenharmony_ci 152cabdff1aSopenharmony_cistatic void CL_CALLBACK opencl_error_callback(const char *errinfo, 153cabdff1aSopenharmony_ci const void *private_info, 154cabdff1aSopenharmony_ci size_t cb, 155cabdff1aSopenharmony_ci void *user_data) 156cabdff1aSopenharmony_ci{ 157cabdff1aSopenharmony_ci AVHWDeviceContext *ctx = user_data; 158cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "OpenCL error: %s\n", errinfo); 159cabdff1aSopenharmony_ci} 160cabdff1aSopenharmony_ci 161cabdff1aSopenharmony_cistatic void opencl_device_free(AVHWDeviceContext *hwdev) 162cabdff1aSopenharmony_ci{ 163cabdff1aSopenharmony_ci AVOpenCLDeviceContext *hwctx = hwdev->hwctx; 164cabdff1aSopenharmony_ci cl_int cle; 165cabdff1aSopenharmony_ci 166cabdff1aSopenharmony_ci cle = clReleaseContext(hwctx->context); 167cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 168cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "Failed to release OpenCL " 169cabdff1aSopenharmony_ci "context: %d.\n", cle); 170cabdff1aSopenharmony_ci } 171cabdff1aSopenharmony_ci} 172cabdff1aSopenharmony_ci 173cabdff1aSopenharmony_cistatic struct { 174cabdff1aSopenharmony_ci const char *key; 175cabdff1aSopenharmony_ci cl_platform_info name; 176cabdff1aSopenharmony_ci} opencl_platform_params[] = { 177cabdff1aSopenharmony_ci { "platform_profile", CL_PLATFORM_PROFILE }, 178cabdff1aSopenharmony_ci { "platform_version", CL_PLATFORM_VERSION }, 179cabdff1aSopenharmony_ci { "platform_name", CL_PLATFORM_NAME }, 180cabdff1aSopenharmony_ci { "platform_vendor", CL_PLATFORM_VENDOR }, 181cabdff1aSopenharmony_ci { "platform_extensions", CL_PLATFORM_EXTENSIONS }, 182cabdff1aSopenharmony_ci}; 183cabdff1aSopenharmony_ci 184cabdff1aSopenharmony_cistatic struct { 185cabdff1aSopenharmony_ci const char *key; 186cabdff1aSopenharmony_ci cl_device_info name; 187cabdff1aSopenharmony_ci} opencl_device_params[] = { 188cabdff1aSopenharmony_ci { "device_name", CL_DEVICE_NAME }, 189cabdff1aSopenharmony_ci { "device_vendor", CL_DEVICE_VENDOR }, 190cabdff1aSopenharmony_ci { "driver_version", CL_DRIVER_VERSION }, 191cabdff1aSopenharmony_ci { "device_version", CL_DEVICE_VERSION }, 192cabdff1aSopenharmony_ci { "device_profile", CL_DEVICE_PROFILE }, 193cabdff1aSopenharmony_ci { "device_extensions", CL_DEVICE_EXTENSIONS }, 194cabdff1aSopenharmony_ci}; 195cabdff1aSopenharmony_ci 196cabdff1aSopenharmony_cistatic struct { 197cabdff1aSopenharmony_ci const char *key; 198cabdff1aSopenharmony_ci cl_device_type type; 199cabdff1aSopenharmony_ci} opencl_device_types[] = { 200cabdff1aSopenharmony_ci { "cpu", CL_DEVICE_TYPE_CPU }, 201cabdff1aSopenharmony_ci { "gpu", CL_DEVICE_TYPE_GPU }, 202cabdff1aSopenharmony_ci { "accelerator", CL_DEVICE_TYPE_ACCELERATOR }, 203cabdff1aSopenharmony_ci { "custom", CL_DEVICE_TYPE_CUSTOM }, 204cabdff1aSopenharmony_ci { "default", CL_DEVICE_TYPE_DEFAULT }, 205cabdff1aSopenharmony_ci { "all", CL_DEVICE_TYPE_ALL }, 206cabdff1aSopenharmony_ci}; 207cabdff1aSopenharmony_ci 208cabdff1aSopenharmony_cistatic char *opencl_get_platform_string(cl_platform_id platform_id, 209cabdff1aSopenharmony_ci cl_platform_info key) 210cabdff1aSopenharmony_ci{ 211cabdff1aSopenharmony_ci char *str; 212cabdff1aSopenharmony_ci size_t size; 213cabdff1aSopenharmony_ci cl_int cle; 214cabdff1aSopenharmony_ci cle = clGetPlatformInfo(platform_id, key, 0, NULL, &size); 215cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) 216cabdff1aSopenharmony_ci return NULL; 217cabdff1aSopenharmony_ci str = av_malloc(size); 218cabdff1aSopenharmony_ci if (!str) 219cabdff1aSopenharmony_ci return NULL; 220cabdff1aSopenharmony_ci cle = clGetPlatformInfo(platform_id, key, size, str, &size); 221cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 222cabdff1aSopenharmony_ci av_free(str); 223cabdff1aSopenharmony_ci return NULL; 224cabdff1aSopenharmony_ci } 225cabdff1aSopenharmony_ci av_assert0(strlen(str) + 1 == size); 226cabdff1aSopenharmony_ci return str; 227cabdff1aSopenharmony_ci} 228cabdff1aSopenharmony_ci 229cabdff1aSopenharmony_cistatic char *opencl_get_device_string(cl_device_id device_id, 230cabdff1aSopenharmony_ci cl_device_info key) 231cabdff1aSopenharmony_ci{ 232cabdff1aSopenharmony_ci char *str; 233cabdff1aSopenharmony_ci size_t size; 234cabdff1aSopenharmony_ci cl_int cle; 235cabdff1aSopenharmony_ci cle = clGetDeviceInfo(device_id, key, 0, NULL, &size); 236cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) 237cabdff1aSopenharmony_ci return NULL; 238cabdff1aSopenharmony_ci str = av_malloc(size); 239cabdff1aSopenharmony_ci if (!str) 240cabdff1aSopenharmony_ci return NULL; 241cabdff1aSopenharmony_ci cle = clGetDeviceInfo(device_id, key, size, str, &size); 242cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 243cabdff1aSopenharmony_ci av_free(str); 244cabdff1aSopenharmony_ci return NULL; 245cabdff1aSopenharmony_ci } 246cabdff1aSopenharmony_ci av_assert0(strlen(str) + 1== size); 247cabdff1aSopenharmony_ci return str; 248cabdff1aSopenharmony_ci} 249cabdff1aSopenharmony_ci 250cabdff1aSopenharmony_cistatic int opencl_check_platform_extension(cl_platform_id platform_id, 251cabdff1aSopenharmony_ci const char *name) 252cabdff1aSopenharmony_ci{ 253cabdff1aSopenharmony_ci char *str; 254cabdff1aSopenharmony_ci int found = 0; 255cabdff1aSopenharmony_ci str = opencl_get_platform_string(platform_id, 256cabdff1aSopenharmony_ci CL_PLATFORM_EXTENSIONS); 257cabdff1aSopenharmony_ci if (str && strstr(str, name)) 258cabdff1aSopenharmony_ci found = 1; 259cabdff1aSopenharmony_ci av_free(str); 260cabdff1aSopenharmony_ci return found; 261cabdff1aSopenharmony_ci} 262cabdff1aSopenharmony_ci 263cabdff1aSopenharmony_cistatic int opencl_check_device_extension(cl_device_id device_id, 264cabdff1aSopenharmony_ci const char *name) 265cabdff1aSopenharmony_ci{ 266cabdff1aSopenharmony_ci char *str; 267cabdff1aSopenharmony_ci int found = 0; 268cabdff1aSopenharmony_ci str = opencl_get_device_string(device_id, 269cabdff1aSopenharmony_ci CL_DEVICE_EXTENSIONS); 270cabdff1aSopenharmony_ci if (str && strstr(str, name)) 271cabdff1aSopenharmony_ci found = 1; 272cabdff1aSopenharmony_ci av_free(str); 273cabdff1aSopenharmony_ci return found; 274cabdff1aSopenharmony_ci} 275cabdff1aSopenharmony_ci 276cabdff1aSopenharmony_cistatic av_unused int opencl_check_extension(AVHWDeviceContext *hwdev, 277cabdff1aSopenharmony_ci const char *name) 278cabdff1aSopenharmony_ci{ 279cabdff1aSopenharmony_ci AVOpenCLDeviceContext *hwctx = hwdev->hwctx; 280cabdff1aSopenharmony_ci OpenCLDeviceContext *priv = hwdev->internal->priv; 281cabdff1aSopenharmony_ci 282cabdff1aSopenharmony_ci if (opencl_check_platform_extension(priv->platform_id, name)) { 283cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_DEBUG, 284cabdff1aSopenharmony_ci "%s found as platform extension.\n", name); 285cabdff1aSopenharmony_ci return 1; 286cabdff1aSopenharmony_ci } 287cabdff1aSopenharmony_ci 288cabdff1aSopenharmony_ci if (opencl_check_device_extension(hwctx->device_id, name)) { 289cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_DEBUG, 290cabdff1aSopenharmony_ci "%s found as device extension.\n", name); 291cabdff1aSopenharmony_ci return 1; 292cabdff1aSopenharmony_ci } 293cabdff1aSopenharmony_ci 294cabdff1aSopenharmony_ci return 0; 295cabdff1aSopenharmony_ci} 296cabdff1aSopenharmony_ci 297cabdff1aSopenharmony_cistatic int opencl_enumerate_platforms(AVHWDeviceContext *hwdev, 298cabdff1aSopenharmony_ci cl_uint *nb_platforms, 299cabdff1aSopenharmony_ci cl_platform_id **platforms, 300cabdff1aSopenharmony_ci void *context) 301cabdff1aSopenharmony_ci{ 302cabdff1aSopenharmony_ci cl_int cle; 303cabdff1aSopenharmony_ci 304cabdff1aSopenharmony_ci cle = clGetPlatformIDs(0, NULL, nb_platforms); 305cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 306cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "Failed to get number of " 307cabdff1aSopenharmony_ci "OpenCL platforms: %d.\n", cle); 308cabdff1aSopenharmony_ci return AVERROR(ENODEV); 309cabdff1aSopenharmony_ci } 310cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_DEBUG, "%u OpenCL platforms found.\n", 311cabdff1aSopenharmony_ci *nb_platforms); 312cabdff1aSopenharmony_ci 313cabdff1aSopenharmony_ci *platforms = av_malloc_array(*nb_platforms, sizeof(**platforms)); 314cabdff1aSopenharmony_ci if (!*platforms) 315cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 316cabdff1aSopenharmony_ci 317cabdff1aSopenharmony_ci cle = clGetPlatformIDs(*nb_platforms, *platforms, NULL); 318cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 319cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "Failed to get list of OpenCL " 320cabdff1aSopenharmony_ci "platforms: %d.\n", cle); 321cabdff1aSopenharmony_ci av_freep(platforms); 322cabdff1aSopenharmony_ci return AVERROR(ENODEV); 323cabdff1aSopenharmony_ci } 324cabdff1aSopenharmony_ci 325cabdff1aSopenharmony_ci return 0; 326cabdff1aSopenharmony_ci} 327cabdff1aSopenharmony_ci 328cabdff1aSopenharmony_cistatic int opencl_filter_platform(AVHWDeviceContext *hwdev, 329cabdff1aSopenharmony_ci cl_platform_id platform_id, 330cabdff1aSopenharmony_ci const char *platform_name, 331cabdff1aSopenharmony_ci void *context) 332cabdff1aSopenharmony_ci{ 333cabdff1aSopenharmony_ci AVDictionary *opts = context; 334cabdff1aSopenharmony_ci const AVDictionaryEntry *param; 335cabdff1aSopenharmony_ci char *str; 336cabdff1aSopenharmony_ci int i, ret = 0; 337cabdff1aSopenharmony_ci 338cabdff1aSopenharmony_ci for (i = 0; i < FF_ARRAY_ELEMS(opencl_platform_params); i++) { 339cabdff1aSopenharmony_ci param = av_dict_get(opts, opencl_platform_params[i].key, 340cabdff1aSopenharmony_ci NULL, 0); 341cabdff1aSopenharmony_ci if (!param) 342cabdff1aSopenharmony_ci continue; 343cabdff1aSopenharmony_ci 344cabdff1aSopenharmony_ci str = opencl_get_platform_string(platform_id, 345cabdff1aSopenharmony_ci opencl_platform_params[i].name); 346cabdff1aSopenharmony_ci if (!str) { 347cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "Failed to query %s " 348cabdff1aSopenharmony_ci "of platform \"%s\".\n", 349cabdff1aSopenharmony_ci opencl_platform_params[i].key, platform_name); 350cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 351cabdff1aSopenharmony_ci } 352cabdff1aSopenharmony_ci if (!av_stristr(str, param->value)) { 353cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_DEBUG, "%s does not match (\"%s\").\n", 354cabdff1aSopenharmony_ci param->key, str); 355cabdff1aSopenharmony_ci ret = 1; 356cabdff1aSopenharmony_ci } 357cabdff1aSopenharmony_ci av_free(str); 358cabdff1aSopenharmony_ci } 359cabdff1aSopenharmony_ci 360cabdff1aSopenharmony_ci return ret; 361cabdff1aSopenharmony_ci} 362cabdff1aSopenharmony_ci 363cabdff1aSopenharmony_cistatic int opencl_enumerate_devices(AVHWDeviceContext *hwdev, 364cabdff1aSopenharmony_ci cl_platform_id platform_id, 365cabdff1aSopenharmony_ci const char *platform_name, 366cabdff1aSopenharmony_ci cl_uint *nb_devices, 367cabdff1aSopenharmony_ci cl_device_id **devices, 368cabdff1aSopenharmony_ci void *context) 369cabdff1aSopenharmony_ci{ 370cabdff1aSopenharmony_ci cl_int cle; 371cabdff1aSopenharmony_ci 372cabdff1aSopenharmony_ci cle = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_ALL, 373cabdff1aSopenharmony_ci 0, NULL, nb_devices); 374cabdff1aSopenharmony_ci if (cle == CL_DEVICE_NOT_FOUND) { 375cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_DEBUG, "No devices found " 376cabdff1aSopenharmony_ci "on platform \"%s\".\n", platform_name); 377cabdff1aSopenharmony_ci *nb_devices = 0; 378cabdff1aSopenharmony_ci return 0; 379cabdff1aSopenharmony_ci } else if (cle != CL_SUCCESS) { 380cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "Failed to get number of devices " 381cabdff1aSopenharmony_ci "on platform \"%s\": %d.\n", platform_name, cle); 382cabdff1aSopenharmony_ci return AVERROR(ENODEV); 383cabdff1aSopenharmony_ci } 384cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_DEBUG, "%u OpenCL devices found on " 385cabdff1aSopenharmony_ci "platform \"%s\".\n", *nb_devices, platform_name); 386cabdff1aSopenharmony_ci 387cabdff1aSopenharmony_ci *devices = av_malloc_array(*nb_devices, sizeof(**devices)); 388cabdff1aSopenharmony_ci if (!*devices) 389cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 390cabdff1aSopenharmony_ci 391cabdff1aSopenharmony_ci cle = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_ALL, 392cabdff1aSopenharmony_ci *nb_devices, *devices, NULL); 393cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 394cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "Failed to get list of devices " 395cabdff1aSopenharmony_ci "on platform \"%s\": %d.\n", platform_name, cle); 396cabdff1aSopenharmony_ci av_freep(devices); 397cabdff1aSopenharmony_ci return AVERROR(ENODEV); 398cabdff1aSopenharmony_ci } 399cabdff1aSopenharmony_ci 400cabdff1aSopenharmony_ci return 0; 401cabdff1aSopenharmony_ci} 402cabdff1aSopenharmony_ci 403cabdff1aSopenharmony_cistatic int opencl_filter_device(AVHWDeviceContext *hwdev, 404cabdff1aSopenharmony_ci cl_device_id device_id, 405cabdff1aSopenharmony_ci const char *device_name, 406cabdff1aSopenharmony_ci void *context) 407cabdff1aSopenharmony_ci{ 408cabdff1aSopenharmony_ci AVDictionary *opts = context; 409cabdff1aSopenharmony_ci const AVDictionaryEntry *param; 410cabdff1aSopenharmony_ci char *str; 411cabdff1aSopenharmony_ci int i, ret = 0; 412cabdff1aSopenharmony_ci 413cabdff1aSopenharmony_ci param = av_dict_get(opts, "device_type", NULL, 0); 414cabdff1aSopenharmony_ci if (param) { 415cabdff1aSopenharmony_ci cl_device_type match_type = 0, device_type; 416cabdff1aSopenharmony_ci cl_int cle; 417cabdff1aSopenharmony_ci 418cabdff1aSopenharmony_ci for (i = 0; i < FF_ARRAY_ELEMS(opencl_device_types); i++) { 419cabdff1aSopenharmony_ci if (!strcmp(opencl_device_types[i].key, param->value)) { 420cabdff1aSopenharmony_ci match_type = opencl_device_types[i].type; 421cabdff1aSopenharmony_ci break; 422cabdff1aSopenharmony_ci } 423cabdff1aSopenharmony_ci } 424cabdff1aSopenharmony_ci if (!match_type) { 425cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "Unknown device type %s.\n", 426cabdff1aSopenharmony_ci param->value); 427cabdff1aSopenharmony_ci return AVERROR(EINVAL); 428cabdff1aSopenharmony_ci } 429cabdff1aSopenharmony_ci 430cabdff1aSopenharmony_ci cle = clGetDeviceInfo(device_id, CL_DEVICE_TYPE, 431cabdff1aSopenharmony_ci sizeof(device_type), &device_type, NULL); 432cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 433cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "Failed to query device type " 434cabdff1aSopenharmony_ci "of device \"%s\".\n", device_name); 435cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 436cabdff1aSopenharmony_ci } 437cabdff1aSopenharmony_ci 438cabdff1aSopenharmony_ci if (!(device_type & match_type)) { 439cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_DEBUG, "device_type does not match.\n"); 440cabdff1aSopenharmony_ci return 1; 441cabdff1aSopenharmony_ci } 442cabdff1aSopenharmony_ci } 443cabdff1aSopenharmony_ci 444cabdff1aSopenharmony_ci for (i = 0; i < FF_ARRAY_ELEMS(opencl_device_params); i++) { 445cabdff1aSopenharmony_ci param = av_dict_get(opts, opencl_device_params[i].key, 446cabdff1aSopenharmony_ci NULL, 0); 447cabdff1aSopenharmony_ci if (!param) 448cabdff1aSopenharmony_ci continue; 449cabdff1aSopenharmony_ci 450cabdff1aSopenharmony_ci str = opencl_get_device_string(device_id, 451cabdff1aSopenharmony_ci opencl_device_params[i].name); 452cabdff1aSopenharmony_ci if (!str) { 453cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "Failed to query %s " 454cabdff1aSopenharmony_ci "of device \"%s\".\n", 455cabdff1aSopenharmony_ci opencl_device_params[i].key, device_name); 456cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 457cabdff1aSopenharmony_ci } 458cabdff1aSopenharmony_ci if (!av_stristr(str, param->value)) { 459cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_DEBUG, "%s does not match (\"%s\").\n", 460cabdff1aSopenharmony_ci param->key, str); 461cabdff1aSopenharmony_ci ret = 1; 462cabdff1aSopenharmony_ci } 463cabdff1aSopenharmony_ci av_free(str); 464cabdff1aSopenharmony_ci } 465cabdff1aSopenharmony_ci 466cabdff1aSopenharmony_ci return ret; 467cabdff1aSopenharmony_ci} 468cabdff1aSopenharmony_ci 469cabdff1aSopenharmony_citypedef struct OpenCLDeviceSelector { 470cabdff1aSopenharmony_ci int platform_index; 471cabdff1aSopenharmony_ci int device_index; 472cabdff1aSopenharmony_ci void *context; 473cabdff1aSopenharmony_ci int (*enumerate_platforms)(AVHWDeviceContext *hwdev, 474cabdff1aSopenharmony_ci cl_uint *nb_platforms, 475cabdff1aSopenharmony_ci cl_platform_id **platforms, 476cabdff1aSopenharmony_ci void *context); 477cabdff1aSopenharmony_ci int (*filter_platform) (AVHWDeviceContext *hwdev, 478cabdff1aSopenharmony_ci cl_platform_id platform_id, 479cabdff1aSopenharmony_ci const char *platform_name, 480cabdff1aSopenharmony_ci void *context); 481cabdff1aSopenharmony_ci int (*enumerate_devices) (AVHWDeviceContext *hwdev, 482cabdff1aSopenharmony_ci cl_platform_id platform_id, 483cabdff1aSopenharmony_ci const char *platform_name, 484cabdff1aSopenharmony_ci cl_uint *nb_devices, 485cabdff1aSopenharmony_ci cl_device_id **devices, 486cabdff1aSopenharmony_ci void *context); 487cabdff1aSopenharmony_ci int (*filter_device) (AVHWDeviceContext *hwdev, 488cabdff1aSopenharmony_ci cl_device_id device_id, 489cabdff1aSopenharmony_ci const char *device_name, 490cabdff1aSopenharmony_ci void *context); 491cabdff1aSopenharmony_ci} OpenCLDeviceSelector; 492cabdff1aSopenharmony_ci 493cabdff1aSopenharmony_cistatic int opencl_device_create_internal(AVHWDeviceContext *hwdev, 494cabdff1aSopenharmony_ci const OpenCLDeviceSelector *selector, 495cabdff1aSopenharmony_ci cl_context_properties *props) 496cabdff1aSopenharmony_ci{ 497cabdff1aSopenharmony_ci cl_uint nb_platforms; 498cabdff1aSopenharmony_ci cl_platform_id *platforms = NULL; 499cabdff1aSopenharmony_ci cl_platform_id platform_id; 500cabdff1aSopenharmony_ci cl_uint nb_devices; 501cabdff1aSopenharmony_ci cl_device_id *devices = NULL; 502cabdff1aSopenharmony_ci AVOpenCLDeviceContext *hwctx = hwdev->hwctx; 503cabdff1aSopenharmony_ci cl_int cle; 504cabdff1aSopenharmony_ci cl_context_properties default_props[3]; 505cabdff1aSopenharmony_ci char *platform_name_src = NULL, 506cabdff1aSopenharmony_ci *device_name_src = NULL; 507cabdff1aSopenharmony_ci int err, found, p, d; 508cabdff1aSopenharmony_ci 509cabdff1aSopenharmony_ci av_assert0(selector->enumerate_platforms && 510cabdff1aSopenharmony_ci selector->enumerate_devices); 511cabdff1aSopenharmony_ci 512cabdff1aSopenharmony_ci err = selector->enumerate_platforms(hwdev, &nb_platforms, &platforms, 513cabdff1aSopenharmony_ci selector->context); 514cabdff1aSopenharmony_ci if (err) 515cabdff1aSopenharmony_ci return err; 516cabdff1aSopenharmony_ci 517cabdff1aSopenharmony_ci found = 0; 518cabdff1aSopenharmony_ci for (p = 0; p < nb_platforms; p++) { 519cabdff1aSopenharmony_ci const char *platform_name; 520cabdff1aSopenharmony_ci 521cabdff1aSopenharmony_ci if (selector->platform_index >= 0 && 522cabdff1aSopenharmony_ci selector->platform_index != p) 523cabdff1aSopenharmony_ci continue; 524cabdff1aSopenharmony_ci 525cabdff1aSopenharmony_ci av_freep(&platform_name_src); 526cabdff1aSopenharmony_ci platform_name_src = opencl_get_platform_string(platforms[p], 527cabdff1aSopenharmony_ci CL_PLATFORM_NAME); 528cabdff1aSopenharmony_ci if (platform_name_src) 529cabdff1aSopenharmony_ci platform_name = platform_name_src; 530cabdff1aSopenharmony_ci else 531cabdff1aSopenharmony_ci platform_name = "Unknown Platform"; 532cabdff1aSopenharmony_ci 533cabdff1aSopenharmony_ci if (selector->filter_platform) { 534cabdff1aSopenharmony_ci err = selector->filter_platform(hwdev, platforms[p], 535cabdff1aSopenharmony_ci platform_name, 536cabdff1aSopenharmony_ci selector->context); 537cabdff1aSopenharmony_ci if (err < 0) 538cabdff1aSopenharmony_ci goto fail; 539cabdff1aSopenharmony_ci if (err > 0) 540cabdff1aSopenharmony_ci continue; 541cabdff1aSopenharmony_ci } 542cabdff1aSopenharmony_ci 543cabdff1aSopenharmony_ci err = selector->enumerate_devices(hwdev, platforms[p], platform_name, 544cabdff1aSopenharmony_ci &nb_devices, &devices, 545cabdff1aSopenharmony_ci selector->context); 546cabdff1aSopenharmony_ci if (err < 0) 547cabdff1aSopenharmony_ci continue; 548cabdff1aSopenharmony_ci 549cabdff1aSopenharmony_ci for (d = 0; d < nb_devices; d++) { 550cabdff1aSopenharmony_ci const char *device_name; 551cabdff1aSopenharmony_ci 552cabdff1aSopenharmony_ci if (selector->device_index >= 0 && 553cabdff1aSopenharmony_ci selector->device_index != d) 554cabdff1aSopenharmony_ci continue; 555cabdff1aSopenharmony_ci 556cabdff1aSopenharmony_ci av_freep(&device_name_src); 557cabdff1aSopenharmony_ci device_name_src = opencl_get_device_string(devices[d], 558cabdff1aSopenharmony_ci CL_DEVICE_NAME); 559cabdff1aSopenharmony_ci if (device_name_src) 560cabdff1aSopenharmony_ci device_name = device_name_src; 561cabdff1aSopenharmony_ci else 562cabdff1aSopenharmony_ci device_name = "Unknown Device"; 563cabdff1aSopenharmony_ci 564cabdff1aSopenharmony_ci if (selector->filter_device) { 565cabdff1aSopenharmony_ci err = selector->filter_device(hwdev, devices[d], 566cabdff1aSopenharmony_ci device_name, 567cabdff1aSopenharmony_ci selector->context); 568cabdff1aSopenharmony_ci if (err < 0) 569cabdff1aSopenharmony_ci goto fail; 570cabdff1aSopenharmony_ci if (err > 0) 571cabdff1aSopenharmony_ci continue; 572cabdff1aSopenharmony_ci } 573cabdff1aSopenharmony_ci 574cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_VERBOSE, "%d.%d: %s / %s\n", p, d, 575cabdff1aSopenharmony_ci platform_name, device_name); 576cabdff1aSopenharmony_ci 577cabdff1aSopenharmony_ci ++found; 578cabdff1aSopenharmony_ci platform_id = platforms[p]; 579cabdff1aSopenharmony_ci hwctx->device_id = devices[d]; 580cabdff1aSopenharmony_ci } 581cabdff1aSopenharmony_ci 582cabdff1aSopenharmony_ci av_freep(&devices); 583cabdff1aSopenharmony_ci } 584cabdff1aSopenharmony_ci 585cabdff1aSopenharmony_ci if (found == 0) { 586cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "No matching devices found.\n"); 587cabdff1aSopenharmony_ci err = AVERROR(ENODEV); 588cabdff1aSopenharmony_ci goto fail; 589cabdff1aSopenharmony_ci } 590cabdff1aSopenharmony_ci if (found > 1) { 591cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "More than one matching device found.\n"); 592cabdff1aSopenharmony_ci err = AVERROR(ENODEV); 593cabdff1aSopenharmony_ci goto fail; 594cabdff1aSopenharmony_ci } 595cabdff1aSopenharmony_ci 596cabdff1aSopenharmony_ci if (!props) { 597cabdff1aSopenharmony_ci props = default_props; 598cabdff1aSopenharmony_ci default_props[0] = CL_CONTEXT_PLATFORM; 599cabdff1aSopenharmony_ci default_props[1] = (intptr_t)platform_id; 600cabdff1aSopenharmony_ci default_props[2] = 0; 601cabdff1aSopenharmony_ci } else { 602cabdff1aSopenharmony_ci if (props[0] == CL_CONTEXT_PLATFORM && props[1] == 0) 603cabdff1aSopenharmony_ci props[1] = (intptr_t)platform_id; 604cabdff1aSopenharmony_ci } 605cabdff1aSopenharmony_ci 606cabdff1aSopenharmony_ci hwctx->context = clCreateContext(props, 1, &hwctx->device_id, 607cabdff1aSopenharmony_ci &opencl_error_callback, hwdev, &cle); 608cabdff1aSopenharmony_ci if (!hwctx->context) { 609cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "Failed to create OpenCL context: " 610cabdff1aSopenharmony_ci "%d.\n", cle); 611cabdff1aSopenharmony_ci err = AVERROR(ENODEV); 612cabdff1aSopenharmony_ci goto fail; 613cabdff1aSopenharmony_ci } 614cabdff1aSopenharmony_ci 615cabdff1aSopenharmony_ci hwdev->free = &opencl_device_free; 616cabdff1aSopenharmony_ci 617cabdff1aSopenharmony_ci err = 0; 618cabdff1aSopenharmony_cifail: 619cabdff1aSopenharmony_ci av_freep(&platform_name_src); 620cabdff1aSopenharmony_ci av_freep(&device_name_src); 621cabdff1aSopenharmony_ci av_freep(&platforms); 622cabdff1aSopenharmony_ci av_freep(&devices); 623cabdff1aSopenharmony_ci return err; 624cabdff1aSopenharmony_ci} 625cabdff1aSopenharmony_ci 626cabdff1aSopenharmony_cistatic int opencl_device_create(AVHWDeviceContext *hwdev, const char *device, 627cabdff1aSopenharmony_ci AVDictionary *opts, int flags) 628cabdff1aSopenharmony_ci{ 629cabdff1aSopenharmony_ci OpenCLDeviceSelector selector = { 630cabdff1aSopenharmony_ci .context = opts, 631cabdff1aSopenharmony_ci .enumerate_platforms = &opencl_enumerate_platforms, 632cabdff1aSopenharmony_ci .filter_platform = &opencl_filter_platform, 633cabdff1aSopenharmony_ci .enumerate_devices = &opencl_enumerate_devices, 634cabdff1aSopenharmony_ci .filter_device = &opencl_filter_device, 635cabdff1aSopenharmony_ci }; 636cabdff1aSopenharmony_ci 637cabdff1aSopenharmony_ci if (device && device[0]) { 638cabdff1aSopenharmony_ci // Match one or both indices for platform and device. 639cabdff1aSopenharmony_ci int d = -1, p = -1, ret; 640cabdff1aSopenharmony_ci if (device[0] == '.') 641cabdff1aSopenharmony_ci ret = sscanf(device, ".%d", &d); 642cabdff1aSopenharmony_ci else 643cabdff1aSopenharmony_ci ret = sscanf(device, "%d.%d", &p, &d); 644cabdff1aSopenharmony_ci if (ret < 1) { 645cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "Invalid OpenCL platform/device " 646cabdff1aSopenharmony_ci "index specification \"%s\".\n", device); 647cabdff1aSopenharmony_ci return AVERROR(EINVAL); 648cabdff1aSopenharmony_ci } 649cabdff1aSopenharmony_ci selector.platform_index = p; 650cabdff1aSopenharmony_ci selector.device_index = d; 651cabdff1aSopenharmony_ci } else { 652cabdff1aSopenharmony_ci selector.platform_index = -1; 653cabdff1aSopenharmony_ci selector.device_index = -1; 654cabdff1aSopenharmony_ci } 655cabdff1aSopenharmony_ci 656cabdff1aSopenharmony_ci return opencl_device_create_internal(hwdev, &selector, NULL); 657cabdff1aSopenharmony_ci} 658cabdff1aSopenharmony_ci 659cabdff1aSopenharmony_cistatic int opencl_device_init(AVHWDeviceContext *hwdev) 660cabdff1aSopenharmony_ci{ 661cabdff1aSopenharmony_ci AVOpenCLDeviceContext *hwctx = hwdev->hwctx; 662cabdff1aSopenharmony_ci OpenCLDeviceContext *priv = hwdev->internal->priv; 663cabdff1aSopenharmony_ci cl_int cle; 664cabdff1aSopenharmony_ci 665cabdff1aSopenharmony_ci if (hwctx->command_queue) { 666cabdff1aSopenharmony_ci cle = clRetainCommandQueue(hwctx->command_queue); 667cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 668cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "Failed to retain external " 669cabdff1aSopenharmony_ci "command queue: %d.\n", cle); 670cabdff1aSopenharmony_ci return AVERROR(EIO); 671cabdff1aSopenharmony_ci } 672cabdff1aSopenharmony_ci priv->command_queue = hwctx->command_queue; 673cabdff1aSopenharmony_ci } else { 674cabdff1aSopenharmony_ci priv->command_queue = clCreateCommandQueue(hwctx->context, 675cabdff1aSopenharmony_ci hwctx->device_id, 676cabdff1aSopenharmony_ci 0, &cle); 677cabdff1aSopenharmony_ci if (!priv->command_queue) { 678cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "Failed to create internal " 679cabdff1aSopenharmony_ci "command queue: %d.\n", cle); 680cabdff1aSopenharmony_ci return AVERROR(EIO); 681cabdff1aSopenharmony_ci } 682cabdff1aSopenharmony_ci } 683cabdff1aSopenharmony_ci 684cabdff1aSopenharmony_ci cle = clGetDeviceInfo(hwctx->device_id, CL_DEVICE_PLATFORM, 685cabdff1aSopenharmony_ci sizeof(priv->platform_id), &priv->platform_id, 686cabdff1aSopenharmony_ci NULL); 687cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 688cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "Failed to determine the OpenCL " 689cabdff1aSopenharmony_ci "platform containing the device.\n"); 690cabdff1aSopenharmony_ci return AVERROR(EIO); 691cabdff1aSopenharmony_ci } 692cabdff1aSopenharmony_ci 693cabdff1aSopenharmony_ci#define CL_FUNC(name, desc) do { \ 694cabdff1aSopenharmony_ci if (fail) \ 695cabdff1aSopenharmony_ci break; \ 696cabdff1aSopenharmony_ci priv->name = clGetExtensionFunctionAddressForPlatform( \ 697cabdff1aSopenharmony_ci priv->platform_id, #name); \ 698cabdff1aSopenharmony_ci if (!priv->name) { \ 699cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_VERBOSE, \ 700cabdff1aSopenharmony_ci desc " function not found (%s).\n", #name); \ 701cabdff1aSopenharmony_ci fail = 1; \ 702cabdff1aSopenharmony_ci } else { \ 703cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_VERBOSE, \ 704cabdff1aSopenharmony_ci desc " function found (%s).\n", #name); \ 705cabdff1aSopenharmony_ci } \ 706cabdff1aSopenharmony_ci } while (0) 707cabdff1aSopenharmony_ci 708cabdff1aSopenharmony_ci#if HAVE_OPENCL_DRM_BEIGNET 709cabdff1aSopenharmony_ci { 710cabdff1aSopenharmony_ci int fail = 0; 711cabdff1aSopenharmony_ci 712cabdff1aSopenharmony_ci CL_FUNC(clCreateImageFromFdINTEL, 713cabdff1aSopenharmony_ci "Beignet DRM to OpenCL image mapping"); 714cabdff1aSopenharmony_ci 715cabdff1aSopenharmony_ci if (fail) { 716cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_WARNING, "Beignet DRM to OpenCL " 717cabdff1aSopenharmony_ci "mapping not usable.\n"); 718cabdff1aSopenharmony_ci priv->beignet_drm_mapping_usable = 0; 719cabdff1aSopenharmony_ci } else { 720cabdff1aSopenharmony_ci priv->beignet_drm_mapping_usable = 1; 721cabdff1aSopenharmony_ci } 722cabdff1aSopenharmony_ci } 723cabdff1aSopenharmony_ci#endif 724cabdff1aSopenharmony_ci 725cabdff1aSopenharmony_ci#if HAVE_OPENCL_VAAPI_INTEL_MEDIA 726cabdff1aSopenharmony_ci { 727cabdff1aSopenharmony_ci size_t props_size; 728cabdff1aSopenharmony_ci cl_context_properties *props = NULL; 729cabdff1aSopenharmony_ci VADisplay va_display; 730cabdff1aSopenharmony_ci const char *va_ext = "cl_intel_va_api_media_sharing"; 731cabdff1aSopenharmony_ci int i, fail = 0; 732cabdff1aSopenharmony_ci 733cabdff1aSopenharmony_ci if (!opencl_check_extension(hwdev, va_ext)) { 734cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_VERBOSE, "The %s extension is " 735cabdff1aSopenharmony_ci "required for QSV to OpenCL mapping.\n", va_ext); 736cabdff1aSopenharmony_ci goto no_qsv; 737cabdff1aSopenharmony_ci } 738cabdff1aSopenharmony_ci 739cabdff1aSopenharmony_ci cle = clGetContextInfo(hwctx->context, CL_CONTEXT_PROPERTIES, 740cabdff1aSopenharmony_ci 0, NULL, &props_size); 741cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 742cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_VERBOSE, "Failed to get context " 743cabdff1aSopenharmony_ci "properties: %d.\n", cle); 744cabdff1aSopenharmony_ci goto no_qsv; 745cabdff1aSopenharmony_ci } 746cabdff1aSopenharmony_ci if (props_size == 0) { 747cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_VERBOSE, "Media sharing must be " 748cabdff1aSopenharmony_ci "enabled on context creation to use QSV to " 749cabdff1aSopenharmony_ci "OpenCL mapping.\n"); 750cabdff1aSopenharmony_ci goto no_qsv; 751cabdff1aSopenharmony_ci } 752cabdff1aSopenharmony_ci 753cabdff1aSopenharmony_ci props = av_malloc(props_size); 754cabdff1aSopenharmony_ci if (!props) 755cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 756cabdff1aSopenharmony_ci 757cabdff1aSopenharmony_ci cle = clGetContextInfo(hwctx->context, CL_CONTEXT_PROPERTIES, 758cabdff1aSopenharmony_ci props_size, props, NULL); 759cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 760cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_VERBOSE, "Failed to get context " 761cabdff1aSopenharmony_ci "properties: %d.\n", cle); 762cabdff1aSopenharmony_ci goto no_qsv; 763cabdff1aSopenharmony_ci } 764cabdff1aSopenharmony_ci 765cabdff1aSopenharmony_ci va_display = NULL; 766cabdff1aSopenharmony_ci for (i = 0; i < (props_size / sizeof(*props) - 1); i++) { 767cabdff1aSopenharmony_ci if (props[i] == CL_CONTEXT_VA_API_DISPLAY_INTEL) { 768cabdff1aSopenharmony_ci va_display = (VADisplay)(intptr_t)props[i+1]; 769cabdff1aSopenharmony_ci break; 770cabdff1aSopenharmony_ci } 771cabdff1aSopenharmony_ci } 772cabdff1aSopenharmony_ci if (!va_display) { 773cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_VERBOSE, "Media sharing must be " 774cabdff1aSopenharmony_ci "enabled on context creation to use QSV to " 775cabdff1aSopenharmony_ci "OpenCL mapping.\n"); 776cabdff1aSopenharmony_ci goto no_qsv; 777cabdff1aSopenharmony_ci } 778cabdff1aSopenharmony_ci if (!vaDisplayIsValid(va_display)) { 779cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_VERBOSE, "A valid VADisplay is " 780cabdff1aSopenharmony_ci "required on context creation to use QSV to " 781cabdff1aSopenharmony_ci "OpenCL mapping.\n"); 782cabdff1aSopenharmony_ci goto no_qsv; 783cabdff1aSopenharmony_ci } 784cabdff1aSopenharmony_ci 785cabdff1aSopenharmony_ci CL_FUNC(clCreateFromVA_APIMediaSurfaceINTEL, 786cabdff1aSopenharmony_ci "Intel QSV to OpenCL mapping"); 787cabdff1aSopenharmony_ci CL_FUNC(clEnqueueAcquireVA_APIMediaSurfacesINTEL, 788cabdff1aSopenharmony_ci "Intel QSV in OpenCL acquire"); 789cabdff1aSopenharmony_ci CL_FUNC(clEnqueueReleaseVA_APIMediaSurfacesINTEL, 790cabdff1aSopenharmony_ci "Intel QSV in OpenCL release"); 791cabdff1aSopenharmony_ci 792cabdff1aSopenharmony_ci if (fail) { 793cabdff1aSopenharmony_ci no_qsv: 794cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_WARNING, "QSV to OpenCL mapping " 795cabdff1aSopenharmony_ci "not usable.\n"); 796cabdff1aSopenharmony_ci priv->qsv_mapping_usable = 0; 797cabdff1aSopenharmony_ci } else { 798cabdff1aSopenharmony_ci priv->qsv_mapping_usable = 1; 799cabdff1aSopenharmony_ci } 800cabdff1aSopenharmony_ci av_free(props); 801cabdff1aSopenharmony_ci } 802cabdff1aSopenharmony_ci#endif 803cabdff1aSopenharmony_ci 804cabdff1aSopenharmony_ci#if HAVE_OPENCL_DXVA2 805cabdff1aSopenharmony_ci { 806cabdff1aSopenharmony_ci int fail = 0; 807cabdff1aSopenharmony_ci 808cabdff1aSopenharmony_ci CL_FUNC(clCreateFromDX9MediaSurfaceKHR, 809cabdff1aSopenharmony_ci "DXVA2 to OpenCL mapping"); 810cabdff1aSopenharmony_ci CL_FUNC(clEnqueueAcquireDX9MediaSurfacesKHR, 811cabdff1aSopenharmony_ci "DXVA2 in OpenCL acquire"); 812cabdff1aSopenharmony_ci CL_FUNC(clEnqueueReleaseDX9MediaSurfacesKHR, 813cabdff1aSopenharmony_ci "DXVA2 in OpenCL release"); 814cabdff1aSopenharmony_ci 815cabdff1aSopenharmony_ci if (fail) { 816cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_WARNING, "DXVA2 to OpenCL mapping " 817cabdff1aSopenharmony_ci "not usable.\n"); 818cabdff1aSopenharmony_ci priv->dxva2_mapping_usable = 0; 819cabdff1aSopenharmony_ci } else { 820cabdff1aSopenharmony_ci priv->dx9_media_adapter_type = CL_ADAPTER_D3D9EX_KHR; 821cabdff1aSopenharmony_ci priv->dxva2_mapping_usable = 1; 822cabdff1aSopenharmony_ci } 823cabdff1aSopenharmony_ci } 824cabdff1aSopenharmony_ci#endif 825cabdff1aSopenharmony_ci 826cabdff1aSopenharmony_ci#if HAVE_OPENCL_D3D11 827cabdff1aSopenharmony_ci { 828cabdff1aSopenharmony_ci const char *d3d11_ext = "cl_khr_d3d11_sharing"; 829cabdff1aSopenharmony_ci const char *nv12_ext = "cl_intel_d3d11_nv12_media_sharing"; 830cabdff1aSopenharmony_ci int fail = 0; 831cabdff1aSopenharmony_ci 832cabdff1aSopenharmony_ci if (!opencl_check_extension(hwdev, d3d11_ext)) { 833cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_VERBOSE, "The %s extension is " 834cabdff1aSopenharmony_ci "required for D3D11 to OpenCL mapping.\n", d3d11_ext); 835cabdff1aSopenharmony_ci fail = 1; 836cabdff1aSopenharmony_ci } else if (!opencl_check_extension(hwdev, nv12_ext)) { 837cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_VERBOSE, "The %s extension may be " 838cabdff1aSopenharmony_ci "required for D3D11 to OpenCL mapping.\n", nv12_ext); 839cabdff1aSopenharmony_ci // Not fatal. 840cabdff1aSopenharmony_ci } 841cabdff1aSopenharmony_ci 842cabdff1aSopenharmony_ci CL_FUNC(clCreateFromD3D11Texture2DKHR, 843cabdff1aSopenharmony_ci "D3D11 to OpenCL mapping"); 844cabdff1aSopenharmony_ci CL_FUNC(clEnqueueAcquireD3D11ObjectsKHR, 845cabdff1aSopenharmony_ci "D3D11 in OpenCL acquire"); 846cabdff1aSopenharmony_ci CL_FUNC(clEnqueueReleaseD3D11ObjectsKHR, 847cabdff1aSopenharmony_ci "D3D11 in OpenCL release"); 848cabdff1aSopenharmony_ci 849cabdff1aSopenharmony_ci if (fail) { 850cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_WARNING, "D3D11 to OpenCL mapping " 851cabdff1aSopenharmony_ci "not usable.\n"); 852cabdff1aSopenharmony_ci priv->d3d11_mapping_usable = 0; 853cabdff1aSopenharmony_ci } else { 854cabdff1aSopenharmony_ci priv->d3d11_mapping_usable = 1; 855cabdff1aSopenharmony_ci } 856cabdff1aSopenharmony_ci } 857cabdff1aSopenharmony_ci#endif 858cabdff1aSopenharmony_ci 859cabdff1aSopenharmony_ci#if HAVE_OPENCL_DRM_ARM 860cabdff1aSopenharmony_ci { 861cabdff1aSopenharmony_ci const char *drm_arm_ext = "cl_arm_import_memory"; 862cabdff1aSopenharmony_ci const char *image_ext = "cl_khr_image2d_from_buffer"; 863cabdff1aSopenharmony_ci int fail = 0; 864cabdff1aSopenharmony_ci 865cabdff1aSopenharmony_ci if (!opencl_check_extension(hwdev, drm_arm_ext)) { 866cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_VERBOSE, "The %s extension is " 867cabdff1aSopenharmony_ci "required for DRM to OpenCL mapping on ARM.\n", 868cabdff1aSopenharmony_ci drm_arm_ext); 869cabdff1aSopenharmony_ci fail = 1; 870cabdff1aSopenharmony_ci } 871cabdff1aSopenharmony_ci if (!opencl_check_extension(hwdev, image_ext)) { 872cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_VERBOSE, "The %s extension is " 873cabdff1aSopenharmony_ci "required for DRM to OpenCL mapping on ARM.\n", 874cabdff1aSopenharmony_ci image_ext); 875cabdff1aSopenharmony_ci fail = 1; 876cabdff1aSopenharmony_ci } 877cabdff1aSopenharmony_ci 878cabdff1aSopenharmony_ci // clImportMemoryARM() is linked statically. 879cabdff1aSopenharmony_ci 880cabdff1aSopenharmony_ci if (fail) { 881cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_WARNING, "DRM to OpenCL mapping on ARM " 882cabdff1aSopenharmony_ci "not usable.\n"); 883cabdff1aSopenharmony_ci priv->drm_arm_mapping_usable = 0; 884cabdff1aSopenharmony_ci } else { 885cabdff1aSopenharmony_ci priv->drm_arm_mapping_usable = 1; 886cabdff1aSopenharmony_ci } 887cabdff1aSopenharmony_ci } 888cabdff1aSopenharmony_ci#endif 889cabdff1aSopenharmony_ci 890cabdff1aSopenharmony_ci#undef CL_FUNC 891cabdff1aSopenharmony_ci 892cabdff1aSopenharmony_ci return 0; 893cabdff1aSopenharmony_ci} 894cabdff1aSopenharmony_ci 895cabdff1aSopenharmony_cistatic void opencl_device_uninit(AVHWDeviceContext *hwdev) 896cabdff1aSopenharmony_ci{ 897cabdff1aSopenharmony_ci OpenCLDeviceContext *priv = hwdev->internal->priv; 898cabdff1aSopenharmony_ci cl_int cle; 899cabdff1aSopenharmony_ci 900cabdff1aSopenharmony_ci if (priv->command_queue) { 901cabdff1aSopenharmony_ci cle = clReleaseCommandQueue(priv->command_queue); 902cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 903cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "Failed to release internal " 904cabdff1aSopenharmony_ci "command queue reference: %d.\n", cle); 905cabdff1aSopenharmony_ci } 906cabdff1aSopenharmony_ci priv->command_queue = NULL; 907cabdff1aSopenharmony_ci } 908cabdff1aSopenharmony_ci} 909cabdff1aSopenharmony_ci 910cabdff1aSopenharmony_ci#if HAVE_OPENCL_VAAPI_INTEL_MEDIA 911cabdff1aSopenharmony_cistatic int opencl_filter_intel_media_vaapi_platform(AVHWDeviceContext *hwdev, 912cabdff1aSopenharmony_ci cl_platform_id platform_id, 913cabdff1aSopenharmony_ci const char *platform_name, 914cabdff1aSopenharmony_ci void *context) 915cabdff1aSopenharmony_ci{ 916cabdff1aSopenharmony_ci // This doesn't exist as a platform extension, so just test whether 917cabdff1aSopenharmony_ci // the function we will use for device enumeration exists. 918cabdff1aSopenharmony_ci 919cabdff1aSopenharmony_ci if (!clGetExtensionFunctionAddressForPlatform(platform_id, 920cabdff1aSopenharmony_ci "clGetDeviceIDsFromVA_APIMediaAdapterINTEL")) { 921cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_DEBUG, "Platform %s does not export the " 922cabdff1aSopenharmony_ci "VAAPI device enumeration function.\n", platform_name); 923cabdff1aSopenharmony_ci return 1; 924cabdff1aSopenharmony_ci } else { 925cabdff1aSopenharmony_ci return 0; 926cabdff1aSopenharmony_ci } 927cabdff1aSopenharmony_ci} 928cabdff1aSopenharmony_ci 929cabdff1aSopenharmony_cistatic int opencl_enumerate_intel_media_vaapi_devices(AVHWDeviceContext *hwdev, 930cabdff1aSopenharmony_ci cl_platform_id platform_id, 931cabdff1aSopenharmony_ci const char *platform_name, 932cabdff1aSopenharmony_ci cl_uint *nb_devices, 933cabdff1aSopenharmony_ci cl_device_id **devices, 934cabdff1aSopenharmony_ci void *context) 935cabdff1aSopenharmony_ci{ 936cabdff1aSopenharmony_ci VADisplay va_display = context; 937cabdff1aSopenharmony_ci clGetDeviceIDsFromVA_APIMediaAdapterINTEL_fn 938cabdff1aSopenharmony_ci clGetDeviceIDsFromVA_APIMediaAdapterINTEL; 939cabdff1aSopenharmony_ci cl_int cle; 940cabdff1aSopenharmony_ci 941cabdff1aSopenharmony_ci clGetDeviceIDsFromVA_APIMediaAdapterINTEL = 942cabdff1aSopenharmony_ci clGetExtensionFunctionAddressForPlatform(platform_id, 943cabdff1aSopenharmony_ci "clGetDeviceIDsFromVA_APIMediaAdapterINTEL"); 944cabdff1aSopenharmony_ci if (!clGetDeviceIDsFromVA_APIMediaAdapterINTEL) { 945cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "Failed to get address of " 946cabdff1aSopenharmony_ci "clGetDeviceIDsFromVA_APIMediaAdapterINTEL().\n"); 947cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 948cabdff1aSopenharmony_ci } 949cabdff1aSopenharmony_ci 950cabdff1aSopenharmony_ci cle = clGetDeviceIDsFromVA_APIMediaAdapterINTEL( 951cabdff1aSopenharmony_ci platform_id, CL_VA_API_DISPLAY_INTEL, va_display, 952cabdff1aSopenharmony_ci CL_PREFERRED_DEVICES_FOR_VA_API_INTEL, 0, NULL, nb_devices); 953cabdff1aSopenharmony_ci if (cle == CL_DEVICE_NOT_FOUND) { 954cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_DEBUG, "No VAAPI-supporting devices found " 955cabdff1aSopenharmony_ci "on platform \"%s\".\n", platform_name); 956cabdff1aSopenharmony_ci *nb_devices = 0; 957cabdff1aSopenharmony_ci return 0; 958cabdff1aSopenharmony_ci } else if (cle != CL_SUCCESS) { 959cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "Failed to get number of devices " 960cabdff1aSopenharmony_ci "on platform \"%s\": %d.\n", platform_name, cle); 961cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 962cabdff1aSopenharmony_ci } 963cabdff1aSopenharmony_ci 964cabdff1aSopenharmony_ci *devices = av_malloc_array(*nb_devices, sizeof(**devices)); 965cabdff1aSopenharmony_ci if (!*devices) 966cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 967cabdff1aSopenharmony_ci 968cabdff1aSopenharmony_ci cle = clGetDeviceIDsFromVA_APIMediaAdapterINTEL( 969cabdff1aSopenharmony_ci platform_id, CL_VA_API_DISPLAY_INTEL, va_display, 970cabdff1aSopenharmony_ci CL_PREFERRED_DEVICES_FOR_VA_API_INTEL, *nb_devices, *devices, NULL); 971cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 972cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "Failed to get list of VAAPI-supporting " 973cabdff1aSopenharmony_ci "devices on platform \"%s\": %d.\n", platform_name, cle); 974cabdff1aSopenharmony_ci av_freep(devices); 975cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 976cabdff1aSopenharmony_ci } 977cabdff1aSopenharmony_ci 978cabdff1aSopenharmony_ci return 0; 979cabdff1aSopenharmony_ci} 980cabdff1aSopenharmony_ci 981cabdff1aSopenharmony_cistatic int opencl_filter_intel_media_vaapi_device(AVHWDeviceContext *hwdev, 982cabdff1aSopenharmony_ci cl_device_id device_id, 983cabdff1aSopenharmony_ci const char *device_name, 984cabdff1aSopenharmony_ci void *context) 985cabdff1aSopenharmony_ci{ 986cabdff1aSopenharmony_ci const char *va_ext = "cl_intel_va_api_media_sharing"; 987cabdff1aSopenharmony_ci 988cabdff1aSopenharmony_ci if (opencl_check_device_extension(device_id, va_ext)) { 989cabdff1aSopenharmony_ci return 0; 990cabdff1aSopenharmony_ci } else { 991cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_DEBUG, "Device %s does not support the " 992cabdff1aSopenharmony_ci "%s extension.\n", device_name, va_ext); 993cabdff1aSopenharmony_ci return 1; 994cabdff1aSopenharmony_ci } 995cabdff1aSopenharmony_ci} 996cabdff1aSopenharmony_ci#endif 997cabdff1aSopenharmony_ci 998cabdff1aSopenharmony_ci#if HAVE_OPENCL_DXVA2 999cabdff1aSopenharmony_cistatic int opencl_filter_dxva2_platform(AVHWDeviceContext *hwdev, 1000cabdff1aSopenharmony_ci cl_platform_id platform_id, 1001cabdff1aSopenharmony_ci const char *platform_name, 1002cabdff1aSopenharmony_ci void *context) 1003cabdff1aSopenharmony_ci{ 1004cabdff1aSopenharmony_ci const char *dx9_ext = "cl_khr_dx9_media_sharing"; 1005cabdff1aSopenharmony_ci 1006cabdff1aSopenharmony_ci if (opencl_check_platform_extension(platform_id, dx9_ext)) { 1007cabdff1aSopenharmony_ci return 0; 1008cabdff1aSopenharmony_ci } else { 1009cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_DEBUG, "Platform %s does not support the " 1010cabdff1aSopenharmony_ci "%s extension.\n", platform_name, dx9_ext); 1011cabdff1aSopenharmony_ci return 1; 1012cabdff1aSopenharmony_ci } 1013cabdff1aSopenharmony_ci} 1014cabdff1aSopenharmony_ci 1015cabdff1aSopenharmony_cistatic int opencl_enumerate_dxva2_devices(AVHWDeviceContext *hwdev, 1016cabdff1aSopenharmony_ci cl_platform_id platform_id, 1017cabdff1aSopenharmony_ci const char *platform_name, 1018cabdff1aSopenharmony_ci cl_uint *nb_devices, 1019cabdff1aSopenharmony_ci cl_device_id **devices, 1020cabdff1aSopenharmony_ci void *context) 1021cabdff1aSopenharmony_ci{ 1022cabdff1aSopenharmony_ci IDirect3DDevice9 *device = context; 1023cabdff1aSopenharmony_ci clGetDeviceIDsFromDX9MediaAdapterKHR_fn 1024cabdff1aSopenharmony_ci clGetDeviceIDsFromDX9MediaAdapterKHR; 1025cabdff1aSopenharmony_ci cl_dx9_media_adapter_type_khr media_adapter_type = CL_ADAPTER_D3D9EX_KHR; 1026cabdff1aSopenharmony_ci cl_int cle; 1027cabdff1aSopenharmony_ci 1028cabdff1aSopenharmony_ci clGetDeviceIDsFromDX9MediaAdapterKHR = 1029cabdff1aSopenharmony_ci clGetExtensionFunctionAddressForPlatform(platform_id, 1030cabdff1aSopenharmony_ci "clGetDeviceIDsFromDX9MediaAdapterKHR"); 1031cabdff1aSopenharmony_ci if (!clGetDeviceIDsFromDX9MediaAdapterKHR) { 1032cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "Failed to get address of " 1033cabdff1aSopenharmony_ci "clGetDeviceIDsFromDX9MediaAdapterKHR().\n"); 1034cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 1035cabdff1aSopenharmony_ci } 1036cabdff1aSopenharmony_ci 1037cabdff1aSopenharmony_ci cle = clGetDeviceIDsFromDX9MediaAdapterKHR( 1038cabdff1aSopenharmony_ci platform_id, 1, &media_adapter_type, (void**)&device, 1039cabdff1aSopenharmony_ci CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR, 1040cabdff1aSopenharmony_ci 0, NULL, nb_devices); 1041cabdff1aSopenharmony_ci if (cle == CL_DEVICE_NOT_FOUND) { 1042cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_DEBUG, "No DXVA2-supporting devices found " 1043cabdff1aSopenharmony_ci "on platform \"%s\".\n", platform_name); 1044cabdff1aSopenharmony_ci *nb_devices = 0; 1045cabdff1aSopenharmony_ci return 0; 1046cabdff1aSopenharmony_ci } else if (cle != CL_SUCCESS) { 1047cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "Failed to get number of devices " 1048cabdff1aSopenharmony_ci "on platform \"%s\": %d.\n", platform_name, cle); 1049cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 1050cabdff1aSopenharmony_ci } 1051cabdff1aSopenharmony_ci 1052cabdff1aSopenharmony_ci *devices = av_malloc_array(*nb_devices, sizeof(**devices)); 1053cabdff1aSopenharmony_ci if (!*devices) 1054cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 1055cabdff1aSopenharmony_ci 1056cabdff1aSopenharmony_ci cle = clGetDeviceIDsFromDX9MediaAdapterKHR( 1057cabdff1aSopenharmony_ci platform_id, 1, &media_adapter_type, (void**)&device, 1058cabdff1aSopenharmony_ci CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR, 1059cabdff1aSopenharmony_ci *nb_devices, *devices, NULL); 1060cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 1061cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "Failed to get list of DXVA2-supporting " 1062cabdff1aSopenharmony_ci "devices on platform \"%s\": %d.\n", platform_name, cle); 1063cabdff1aSopenharmony_ci av_freep(devices); 1064cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 1065cabdff1aSopenharmony_ci } 1066cabdff1aSopenharmony_ci 1067cabdff1aSopenharmony_ci return 0; 1068cabdff1aSopenharmony_ci} 1069cabdff1aSopenharmony_ci#endif 1070cabdff1aSopenharmony_ci 1071cabdff1aSopenharmony_ci#if HAVE_OPENCL_D3D11 1072cabdff1aSopenharmony_cistatic int opencl_filter_d3d11_platform(AVHWDeviceContext *hwdev, 1073cabdff1aSopenharmony_ci cl_platform_id platform_id, 1074cabdff1aSopenharmony_ci const char *platform_name, 1075cabdff1aSopenharmony_ci void *context) 1076cabdff1aSopenharmony_ci{ 1077cabdff1aSopenharmony_ci const char *d3d11_ext = "cl_khr_d3d11_sharing"; 1078cabdff1aSopenharmony_ci 1079cabdff1aSopenharmony_ci if (opencl_check_platform_extension(platform_id, d3d11_ext)) { 1080cabdff1aSopenharmony_ci return 0; 1081cabdff1aSopenharmony_ci } else { 1082cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_DEBUG, "Platform %s does not support the " 1083cabdff1aSopenharmony_ci "%s extension.\n", platform_name, d3d11_ext); 1084cabdff1aSopenharmony_ci return 1; 1085cabdff1aSopenharmony_ci } 1086cabdff1aSopenharmony_ci} 1087cabdff1aSopenharmony_ci 1088cabdff1aSopenharmony_cistatic int opencl_enumerate_d3d11_devices(AVHWDeviceContext *hwdev, 1089cabdff1aSopenharmony_ci cl_platform_id platform_id, 1090cabdff1aSopenharmony_ci const char *platform_name, 1091cabdff1aSopenharmony_ci cl_uint *nb_devices, 1092cabdff1aSopenharmony_ci cl_device_id **devices, 1093cabdff1aSopenharmony_ci void *context) 1094cabdff1aSopenharmony_ci{ 1095cabdff1aSopenharmony_ci ID3D11Device *device = context; 1096cabdff1aSopenharmony_ci clGetDeviceIDsFromD3D11KHR_fn clGetDeviceIDsFromD3D11KHR; 1097cabdff1aSopenharmony_ci cl_int cle; 1098cabdff1aSopenharmony_ci 1099cabdff1aSopenharmony_ci clGetDeviceIDsFromD3D11KHR = 1100cabdff1aSopenharmony_ci clGetExtensionFunctionAddressForPlatform(platform_id, 1101cabdff1aSopenharmony_ci "clGetDeviceIDsFromD3D11KHR"); 1102cabdff1aSopenharmony_ci if (!clGetDeviceIDsFromD3D11KHR) { 1103cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "Failed to get address of " 1104cabdff1aSopenharmony_ci "clGetDeviceIDsFromD3D11KHR().\n"); 1105cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 1106cabdff1aSopenharmony_ci } 1107cabdff1aSopenharmony_ci 1108cabdff1aSopenharmony_ci cle = clGetDeviceIDsFromD3D11KHR(platform_id, 1109cabdff1aSopenharmony_ci CL_D3D11_DEVICE_KHR, device, 1110cabdff1aSopenharmony_ci CL_PREFERRED_DEVICES_FOR_D3D11_KHR, 1111cabdff1aSopenharmony_ci 0, NULL, nb_devices); 1112cabdff1aSopenharmony_ci if (cle == CL_DEVICE_NOT_FOUND) { 1113cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_DEBUG, "No D3D11-supporting devices found " 1114cabdff1aSopenharmony_ci "on platform \"%s\".\n", platform_name); 1115cabdff1aSopenharmony_ci *nb_devices = 0; 1116cabdff1aSopenharmony_ci return 0; 1117cabdff1aSopenharmony_ci } else if (cle != CL_SUCCESS) { 1118cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "Failed to get number of devices " 1119cabdff1aSopenharmony_ci "on platform \"%s\": %d.\n", platform_name, cle); 1120cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 1121cabdff1aSopenharmony_ci } 1122cabdff1aSopenharmony_ci 1123cabdff1aSopenharmony_ci *devices = av_malloc_array(*nb_devices, sizeof(**devices)); 1124cabdff1aSopenharmony_ci if (!*devices) 1125cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 1126cabdff1aSopenharmony_ci 1127cabdff1aSopenharmony_ci cle = clGetDeviceIDsFromD3D11KHR(platform_id, 1128cabdff1aSopenharmony_ci CL_D3D11_DEVICE_KHR, device, 1129cabdff1aSopenharmony_ci CL_PREFERRED_DEVICES_FOR_D3D11_KHR, 1130cabdff1aSopenharmony_ci *nb_devices, *devices, NULL); 1131cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 1132cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "Failed to get list of D3D11-supporting " 1133cabdff1aSopenharmony_ci "devices on platform \"%s\": %d.\n", platform_name, cle); 1134cabdff1aSopenharmony_ci av_freep(devices); 1135cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 1136cabdff1aSopenharmony_ci } 1137cabdff1aSopenharmony_ci 1138cabdff1aSopenharmony_ci return 0; 1139cabdff1aSopenharmony_ci} 1140cabdff1aSopenharmony_ci#endif 1141cabdff1aSopenharmony_ci 1142cabdff1aSopenharmony_ci#if HAVE_OPENCL_DXVA2 || HAVE_OPENCL_D3D11 1143cabdff1aSopenharmony_cistatic int opencl_filter_gpu_device(AVHWDeviceContext *hwdev, 1144cabdff1aSopenharmony_ci cl_device_id device_id, 1145cabdff1aSopenharmony_ci const char *device_name, 1146cabdff1aSopenharmony_ci void *context) 1147cabdff1aSopenharmony_ci{ 1148cabdff1aSopenharmony_ci cl_device_type device_type; 1149cabdff1aSopenharmony_ci cl_int cle; 1150cabdff1aSopenharmony_ci 1151cabdff1aSopenharmony_ci cle = clGetDeviceInfo(device_id, CL_DEVICE_TYPE, 1152cabdff1aSopenharmony_ci sizeof(device_type), &device_type, NULL); 1153cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 1154cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "Failed to query device type " 1155cabdff1aSopenharmony_ci "of device \"%s\".\n", device_name); 1156cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 1157cabdff1aSopenharmony_ci } 1158cabdff1aSopenharmony_ci if (!(device_type & CL_DEVICE_TYPE_GPU)) { 1159cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_DEBUG, "Device %s skipped (not GPU).\n", 1160cabdff1aSopenharmony_ci device_name); 1161cabdff1aSopenharmony_ci return 1; 1162cabdff1aSopenharmony_ci } 1163cabdff1aSopenharmony_ci 1164cabdff1aSopenharmony_ci return 0; 1165cabdff1aSopenharmony_ci} 1166cabdff1aSopenharmony_ci#endif 1167cabdff1aSopenharmony_ci 1168cabdff1aSopenharmony_ci#if HAVE_OPENCL_DRM_ARM 1169cabdff1aSopenharmony_cistatic int opencl_filter_drm_arm_platform(AVHWDeviceContext *hwdev, 1170cabdff1aSopenharmony_ci cl_platform_id platform_id, 1171cabdff1aSopenharmony_ci const char *platform_name, 1172cabdff1aSopenharmony_ci void *context) 1173cabdff1aSopenharmony_ci{ 1174cabdff1aSopenharmony_ci const char *drm_arm_ext = "cl_arm_import_memory"; 1175cabdff1aSopenharmony_ci 1176cabdff1aSopenharmony_ci if (opencl_check_platform_extension(platform_id, drm_arm_ext)) { 1177cabdff1aSopenharmony_ci return 0; 1178cabdff1aSopenharmony_ci } else { 1179cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_DEBUG, "Platform %s does not support the " 1180cabdff1aSopenharmony_ci "%s extension.\n", platform_name, drm_arm_ext); 1181cabdff1aSopenharmony_ci return 1; 1182cabdff1aSopenharmony_ci } 1183cabdff1aSopenharmony_ci} 1184cabdff1aSopenharmony_ci 1185cabdff1aSopenharmony_cistatic int opencl_filter_drm_arm_device(AVHWDeviceContext *hwdev, 1186cabdff1aSopenharmony_ci cl_device_id device_id, 1187cabdff1aSopenharmony_ci const char *device_name, 1188cabdff1aSopenharmony_ci void *context) 1189cabdff1aSopenharmony_ci{ 1190cabdff1aSopenharmony_ci const char *drm_arm_ext = "cl_arm_import_memory"; 1191cabdff1aSopenharmony_ci 1192cabdff1aSopenharmony_ci if (opencl_check_device_extension(device_id, drm_arm_ext)) { 1193cabdff1aSopenharmony_ci return 0; 1194cabdff1aSopenharmony_ci } else { 1195cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_DEBUG, "Device %s does not support the " 1196cabdff1aSopenharmony_ci "%s extension.\n", device_name, drm_arm_ext); 1197cabdff1aSopenharmony_ci return 1; 1198cabdff1aSopenharmony_ci } 1199cabdff1aSopenharmony_ci} 1200cabdff1aSopenharmony_ci#endif 1201cabdff1aSopenharmony_ci 1202cabdff1aSopenharmony_cistatic int opencl_device_derive(AVHWDeviceContext *hwdev, 1203cabdff1aSopenharmony_ci AVHWDeviceContext *src_ctx, AVDictionary *opts, 1204cabdff1aSopenharmony_ci int flags) 1205cabdff1aSopenharmony_ci{ 1206cabdff1aSopenharmony_ci int err; 1207cabdff1aSopenharmony_ci switch (src_ctx->type) { 1208cabdff1aSopenharmony_ci 1209cabdff1aSopenharmony_ci#if HAVE_OPENCL_DRM_BEIGNET 1210cabdff1aSopenharmony_ci case AV_HWDEVICE_TYPE_DRM: 1211cabdff1aSopenharmony_ci case AV_HWDEVICE_TYPE_VAAPI: 1212cabdff1aSopenharmony_ci { 1213cabdff1aSopenharmony_ci // Surface mapping works via DRM PRIME fds with no special 1214cabdff1aSopenharmony_ci // initialisation required in advance. This just finds the 1215cabdff1aSopenharmony_ci // Beignet ICD by name. 1216cabdff1aSopenharmony_ci AVDictionary *selector_opts = NULL; 1217cabdff1aSopenharmony_ci 1218cabdff1aSopenharmony_ci err = av_dict_set(&selector_opts, "platform_vendor", "Intel", 0); 1219cabdff1aSopenharmony_ci if (err >= 0) 1220cabdff1aSopenharmony_ci err = av_dict_set(&selector_opts, "platform_version", "beignet", 0); 1221cabdff1aSopenharmony_ci if (err >= 0) { 1222cabdff1aSopenharmony_ci OpenCLDeviceSelector selector = { 1223cabdff1aSopenharmony_ci .platform_index = -1, 1224cabdff1aSopenharmony_ci .device_index = 0, 1225cabdff1aSopenharmony_ci .context = selector_opts, 1226cabdff1aSopenharmony_ci .enumerate_platforms = &opencl_enumerate_platforms, 1227cabdff1aSopenharmony_ci .filter_platform = &opencl_filter_platform, 1228cabdff1aSopenharmony_ci .enumerate_devices = &opencl_enumerate_devices, 1229cabdff1aSopenharmony_ci .filter_device = NULL, 1230cabdff1aSopenharmony_ci }; 1231cabdff1aSopenharmony_ci err = opencl_device_create_internal(hwdev, &selector, NULL); 1232cabdff1aSopenharmony_ci } 1233cabdff1aSopenharmony_ci av_dict_free(&selector_opts); 1234cabdff1aSopenharmony_ci } 1235cabdff1aSopenharmony_ci break; 1236cabdff1aSopenharmony_ci#endif 1237cabdff1aSopenharmony_ci 1238cabdff1aSopenharmony_ci#if HAVE_OPENCL_VAAPI_INTEL_MEDIA 1239cabdff1aSopenharmony_ci // The generic code automatically attempts to derive from all 1240cabdff1aSopenharmony_ci // ancestors of the given device, so we can ignore QSV devices here 1241cabdff1aSopenharmony_ci // and just consider the inner VAAPI device it was derived from. 1242cabdff1aSopenharmony_ci case AV_HWDEVICE_TYPE_VAAPI: 1243cabdff1aSopenharmony_ci { 1244cabdff1aSopenharmony_ci AVVAAPIDeviceContext *src_hwctx = src_ctx->hwctx; 1245cabdff1aSopenharmony_ci cl_context_properties props[7] = { 1246cabdff1aSopenharmony_ci CL_CONTEXT_PLATFORM, 1247cabdff1aSopenharmony_ci 0, 1248cabdff1aSopenharmony_ci CL_CONTEXT_VA_API_DISPLAY_INTEL, 1249cabdff1aSopenharmony_ci (intptr_t)src_hwctx->display, 1250cabdff1aSopenharmony_ci CL_CONTEXT_INTEROP_USER_SYNC, 1251cabdff1aSopenharmony_ci CL_FALSE, 1252cabdff1aSopenharmony_ci 0, 1253cabdff1aSopenharmony_ci }; 1254cabdff1aSopenharmony_ci OpenCLDeviceSelector selector = { 1255cabdff1aSopenharmony_ci .platform_index = -1, 1256cabdff1aSopenharmony_ci .device_index = -1, 1257cabdff1aSopenharmony_ci .context = src_hwctx->display, 1258cabdff1aSopenharmony_ci .enumerate_platforms = &opencl_enumerate_platforms, 1259cabdff1aSopenharmony_ci .filter_platform = &opencl_filter_intel_media_vaapi_platform, 1260cabdff1aSopenharmony_ci .enumerate_devices = &opencl_enumerate_intel_media_vaapi_devices, 1261cabdff1aSopenharmony_ci .filter_device = &opencl_filter_intel_media_vaapi_device, 1262cabdff1aSopenharmony_ci }; 1263cabdff1aSopenharmony_ci 1264cabdff1aSopenharmony_ci err = opencl_device_create_internal(hwdev, &selector, props); 1265cabdff1aSopenharmony_ci } 1266cabdff1aSopenharmony_ci break; 1267cabdff1aSopenharmony_ci#endif 1268cabdff1aSopenharmony_ci 1269cabdff1aSopenharmony_ci#if HAVE_OPENCL_DXVA2 1270cabdff1aSopenharmony_ci case AV_HWDEVICE_TYPE_DXVA2: 1271cabdff1aSopenharmony_ci { 1272cabdff1aSopenharmony_ci AVDXVA2DeviceContext *src_hwctx = src_ctx->hwctx; 1273cabdff1aSopenharmony_ci IDirect3DDevice9 *device; 1274cabdff1aSopenharmony_ci HANDLE device_handle; 1275cabdff1aSopenharmony_ci HRESULT hr; 1276cabdff1aSopenharmony_ci 1277cabdff1aSopenharmony_ci hr = IDirect3DDeviceManager9_OpenDeviceHandle(src_hwctx->devmgr, 1278cabdff1aSopenharmony_ci &device_handle); 1279cabdff1aSopenharmony_ci if (FAILED(hr)) { 1280cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "Failed to open device handle " 1281cabdff1aSopenharmony_ci "for Direct3D9 device: %lx.\n", (unsigned long)hr); 1282cabdff1aSopenharmony_ci err = AVERROR_UNKNOWN; 1283cabdff1aSopenharmony_ci break; 1284cabdff1aSopenharmony_ci } 1285cabdff1aSopenharmony_ci 1286cabdff1aSopenharmony_ci hr = IDirect3DDeviceManager9_LockDevice(src_hwctx->devmgr, 1287cabdff1aSopenharmony_ci device_handle, 1288cabdff1aSopenharmony_ci &device, FALSE); 1289cabdff1aSopenharmony_ci if (SUCCEEDED(hr)) { 1290cabdff1aSopenharmony_ci cl_context_properties props[5] = { 1291cabdff1aSopenharmony_ci CL_CONTEXT_PLATFORM, 1292cabdff1aSopenharmony_ci 0, 1293cabdff1aSopenharmony_ci CL_CONTEXT_ADAPTER_D3D9EX_KHR, 1294cabdff1aSopenharmony_ci (intptr_t)device, 1295cabdff1aSopenharmony_ci 0, 1296cabdff1aSopenharmony_ci }; 1297cabdff1aSopenharmony_ci OpenCLDeviceSelector selector = { 1298cabdff1aSopenharmony_ci .platform_index = -1, 1299cabdff1aSopenharmony_ci .device_index = -1, 1300cabdff1aSopenharmony_ci .context = device, 1301cabdff1aSopenharmony_ci .enumerate_platforms = &opencl_enumerate_platforms, 1302cabdff1aSopenharmony_ci .filter_platform = &opencl_filter_dxva2_platform, 1303cabdff1aSopenharmony_ci .enumerate_devices = &opencl_enumerate_dxva2_devices, 1304cabdff1aSopenharmony_ci .filter_device = &opencl_filter_gpu_device, 1305cabdff1aSopenharmony_ci }; 1306cabdff1aSopenharmony_ci 1307cabdff1aSopenharmony_ci err = opencl_device_create_internal(hwdev, &selector, props); 1308cabdff1aSopenharmony_ci 1309cabdff1aSopenharmony_ci IDirect3DDeviceManager9_UnlockDevice(src_hwctx->devmgr, 1310cabdff1aSopenharmony_ci device_handle, FALSE); 1311cabdff1aSopenharmony_ci } else { 1312cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "Failed to lock device handle " 1313cabdff1aSopenharmony_ci "for Direct3D9 device: %lx.\n", (unsigned long)hr); 1314cabdff1aSopenharmony_ci err = AVERROR_UNKNOWN; 1315cabdff1aSopenharmony_ci } 1316cabdff1aSopenharmony_ci 1317cabdff1aSopenharmony_ci IDirect3DDeviceManager9_CloseDeviceHandle(src_hwctx->devmgr, 1318cabdff1aSopenharmony_ci device_handle); 1319cabdff1aSopenharmony_ci } 1320cabdff1aSopenharmony_ci break; 1321cabdff1aSopenharmony_ci#endif 1322cabdff1aSopenharmony_ci 1323cabdff1aSopenharmony_ci#if HAVE_OPENCL_D3D11 1324cabdff1aSopenharmony_ci case AV_HWDEVICE_TYPE_D3D11VA: 1325cabdff1aSopenharmony_ci { 1326cabdff1aSopenharmony_ci AVD3D11VADeviceContext *src_hwctx = src_ctx->hwctx; 1327cabdff1aSopenharmony_ci cl_context_properties props[5] = { 1328cabdff1aSopenharmony_ci CL_CONTEXT_PLATFORM, 1329cabdff1aSopenharmony_ci 0, 1330cabdff1aSopenharmony_ci CL_CONTEXT_D3D11_DEVICE_KHR, 1331cabdff1aSopenharmony_ci (intptr_t)src_hwctx->device, 1332cabdff1aSopenharmony_ci 0, 1333cabdff1aSopenharmony_ci }; 1334cabdff1aSopenharmony_ci OpenCLDeviceSelector selector = { 1335cabdff1aSopenharmony_ci .platform_index = -1, 1336cabdff1aSopenharmony_ci .device_index = -1, 1337cabdff1aSopenharmony_ci .context = src_hwctx->device, 1338cabdff1aSopenharmony_ci .enumerate_platforms = &opencl_enumerate_platforms, 1339cabdff1aSopenharmony_ci .filter_platform = &opencl_filter_d3d11_platform, 1340cabdff1aSopenharmony_ci .enumerate_devices = &opencl_enumerate_d3d11_devices, 1341cabdff1aSopenharmony_ci .filter_device = &opencl_filter_gpu_device, 1342cabdff1aSopenharmony_ci }; 1343cabdff1aSopenharmony_ci 1344cabdff1aSopenharmony_ci err = opencl_device_create_internal(hwdev, &selector, props); 1345cabdff1aSopenharmony_ci } 1346cabdff1aSopenharmony_ci break; 1347cabdff1aSopenharmony_ci#endif 1348cabdff1aSopenharmony_ci 1349cabdff1aSopenharmony_ci#if HAVE_OPENCL_DRM_ARM 1350cabdff1aSopenharmony_ci case AV_HWDEVICE_TYPE_DRM: 1351cabdff1aSopenharmony_ci { 1352cabdff1aSopenharmony_ci OpenCLDeviceSelector selector = { 1353cabdff1aSopenharmony_ci .platform_index = -1, 1354cabdff1aSopenharmony_ci .device_index = -1, 1355cabdff1aSopenharmony_ci .context = NULL, 1356cabdff1aSopenharmony_ci .enumerate_platforms = &opencl_enumerate_platforms, 1357cabdff1aSopenharmony_ci .filter_platform = &opencl_filter_drm_arm_platform, 1358cabdff1aSopenharmony_ci .enumerate_devices = &opencl_enumerate_devices, 1359cabdff1aSopenharmony_ci .filter_device = &opencl_filter_drm_arm_device, 1360cabdff1aSopenharmony_ci }; 1361cabdff1aSopenharmony_ci 1362cabdff1aSopenharmony_ci err = opencl_device_create_internal(hwdev, &selector, NULL); 1363cabdff1aSopenharmony_ci } 1364cabdff1aSopenharmony_ci break; 1365cabdff1aSopenharmony_ci#endif 1366cabdff1aSopenharmony_ci 1367cabdff1aSopenharmony_ci default: 1368cabdff1aSopenharmony_ci err = AVERROR(ENOSYS); 1369cabdff1aSopenharmony_ci break; 1370cabdff1aSopenharmony_ci } 1371cabdff1aSopenharmony_ci 1372cabdff1aSopenharmony_ci return err; 1373cabdff1aSopenharmony_ci} 1374cabdff1aSopenharmony_ci 1375cabdff1aSopenharmony_cistatic int opencl_get_plane_format(enum AVPixelFormat pixfmt, 1376cabdff1aSopenharmony_ci int plane, int width, int height, 1377cabdff1aSopenharmony_ci cl_image_format *image_format, 1378cabdff1aSopenharmony_ci cl_image_desc *image_desc) 1379cabdff1aSopenharmony_ci{ 1380cabdff1aSopenharmony_ci const AVPixFmtDescriptor *desc; 1381cabdff1aSopenharmony_ci const AVComponentDescriptor *comp; 1382cabdff1aSopenharmony_ci int channels = 0, order = 0, depth = 0, step = 0; 1383cabdff1aSopenharmony_ci int wsub, hsub, alpha; 1384cabdff1aSopenharmony_ci int c; 1385cabdff1aSopenharmony_ci 1386cabdff1aSopenharmony_ci if (plane >= AV_NUM_DATA_POINTERS) 1387cabdff1aSopenharmony_ci return AVERROR(ENOENT); 1388cabdff1aSopenharmony_ci 1389cabdff1aSopenharmony_ci desc = av_pix_fmt_desc_get(pixfmt); 1390cabdff1aSopenharmony_ci 1391cabdff1aSopenharmony_ci // Only normal images are allowed. 1392cabdff1aSopenharmony_ci if (desc->flags & (AV_PIX_FMT_FLAG_BITSTREAM | 1393cabdff1aSopenharmony_ci AV_PIX_FMT_FLAG_HWACCEL | 1394cabdff1aSopenharmony_ci AV_PIX_FMT_FLAG_PAL)) 1395cabdff1aSopenharmony_ci return AVERROR(EINVAL); 1396cabdff1aSopenharmony_ci 1397cabdff1aSopenharmony_ci wsub = 1 << desc->log2_chroma_w; 1398cabdff1aSopenharmony_ci hsub = 1 << desc->log2_chroma_h; 1399cabdff1aSopenharmony_ci // Subsampled components must be exact. 1400cabdff1aSopenharmony_ci if (width & wsub - 1 || height & hsub - 1) 1401cabdff1aSopenharmony_ci return AVERROR(EINVAL); 1402cabdff1aSopenharmony_ci 1403cabdff1aSopenharmony_ci for (c = 0; c < desc->nb_components; c++) { 1404cabdff1aSopenharmony_ci comp = &desc->comp[c]; 1405cabdff1aSopenharmony_ci if (comp->plane != plane) 1406cabdff1aSopenharmony_ci continue; 1407cabdff1aSopenharmony_ci // The step size must be a power of two. 1408cabdff1aSopenharmony_ci if (comp->step != 1 && comp->step != 2 && 1409cabdff1aSopenharmony_ci comp->step != 4 && comp->step != 8) 1410cabdff1aSopenharmony_ci return AVERROR(EINVAL); 1411cabdff1aSopenharmony_ci // The bits in each component must be packed in the 1412cabdff1aSopenharmony_ci // most-significant-bits of the relevant bytes. 1413cabdff1aSopenharmony_ci if (comp->shift + comp->depth != 8 && 1414cabdff1aSopenharmony_ci comp->shift + comp->depth != 16 && 1415cabdff1aSopenharmony_ci comp->shift + comp->depth != 32) 1416cabdff1aSopenharmony_ci return AVERROR(EINVAL); 1417cabdff1aSopenharmony_ci // The depth must not vary between components. 1418cabdff1aSopenharmony_ci if (depth && comp->depth != depth) 1419cabdff1aSopenharmony_ci return AVERROR(EINVAL); 1420cabdff1aSopenharmony_ci // If a single data element crosses multiple bytes then 1421cabdff1aSopenharmony_ci // it must match the native endianness. 1422cabdff1aSopenharmony_ci if (comp->depth > 8 && 1423cabdff1aSopenharmony_ci HAVE_BIGENDIAN == !(desc->flags & AV_PIX_FMT_FLAG_BE)) 1424cabdff1aSopenharmony_ci return AVERROR(EINVAL); 1425cabdff1aSopenharmony_ci // A single data element must not contain multiple samples 1426cabdff1aSopenharmony_ci // from the same component. 1427cabdff1aSopenharmony_ci if (step && comp->step != step) 1428cabdff1aSopenharmony_ci return AVERROR(EINVAL); 1429cabdff1aSopenharmony_ci 1430cabdff1aSopenharmony_ci depth = comp->depth; 1431cabdff1aSopenharmony_ci order = order * 10 + comp->offset / ((depth + 7) / 8) + 1; 1432cabdff1aSopenharmony_ci step = comp->step; 1433cabdff1aSopenharmony_ci alpha = (desc->flags & AV_PIX_FMT_FLAG_ALPHA && 1434cabdff1aSopenharmony_ci c == desc->nb_components - 1); 1435cabdff1aSopenharmony_ci ++channels; 1436cabdff1aSopenharmony_ci } 1437cabdff1aSopenharmony_ci if (channels == 0) 1438cabdff1aSopenharmony_ci return AVERROR(ENOENT); 1439cabdff1aSopenharmony_ci 1440cabdff1aSopenharmony_ci memset(image_format, 0, sizeof(*image_format)); 1441cabdff1aSopenharmony_ci memset(image_desc, 0, sizeof(*image_desc)); 1442cabdff1aSopenharmony_ci image_desc->image_type = CL_MEM_OBJECT_IMAGE2D; 1443cabdff1aSopenharmony_ci 1444cabdff1aSopenharmony_ci if (plane == 0 || alpha) { 1445cabdff1aSopenharmony_ci image_desc->image_width = width; 1446cabdff1aSopenharmony_ci image_desc->image_height = height; 1447cabdff1aSopenharmony_ci image_desc->image_row_pitch = step * width; 1448cabdff1aSopenharmony_ci } else { 1449cabdff1aSopenharmony_ci image_desc->image_width = width / wsub; 1450cabdff1aSopenharmony_ci image_desc->image_height = height / hsub; 1451cabdff1aSopenharmony_ci image_desc->image_row_pitch = step * width / wsub; 1452cabdff1aSopenharmony_ci } 1453cabdff1aSopenharmony_ci 1454cabdff1aSopenharmony_ci if (depth <= 8) { 1455cabdff1aSopenharmony_ci image_format->image_channel_data_type = CL_UNORM_INT8; 1456cabdff1aSopenharmony_ci } else { 1457cabdff1aSopenharmony_ci if (depth <= 16) 1458cabdff1aSopenharmony_ci image_format->image_channel_data_type = CL_UNORM_INT16; 1459cabdff1aSopenharmony_ci else if (depth == 32) 1460cabdff1aSopenharmony_ci image_format->image_channel_data_type = CL_FLOAT; 1461cabdff1aSopenharmony_ci else 1462cabdff1aSopenharmony_ci return AVERROR(EINVAL); 1463cabdff1aSopenharmony_ci } 1464cabdff1aSopenharmony_ci 1465cabdff1aSopenharmony_ci#define CHANNEL_ORDER(order, type) \ 1466cabdff1aSopenharmony_ci case order: image_format->image_channel_order = type; break; 1467cabdff1aSopenharmony_ci switch (order) { 1468cabdff1aSopenharmony_ci CHANNEL_ORDER(1, CL_R); 1469cabdff1aSopenharmony_ci CHANNEL_ORDER(12, CL_RG); 1470cabdff1aSopenharmony_ci CHANNEL_ORDER(1234, CL_RGBA); 1471cabdff1aSopenharmony_ci CHANNEL_ORDER(2341, CL_ARGB); 1472cabdff1aSopenharmony_ci CHANNEL_ORDER(3214, CL_BGRA); 1473cabdff1aSopenharmony_ci#ifdef CL_ABGR 1474cabdff1aSopenharmony_ci CHANNEL_ORDER(4321, CL_ABGR); 1475cabdff1aSopenharmony_ci#endif 1476cabdff1aSopenharmony_ci default: 1477cabdff1aSopenharmony_ci return AVERROR(EINVAL); 1478cabdff1aSopenharmony_ci } 1479cabdff1aSopenharmony_ci#undef CHANNEL_ORDER 1480cabdff1aSopenharmony_ci 1481cabdff1aSopenharmony_ci return 0; 1482cabdff1aSopenharmony_ci} 1483cabdff1aSopenharmony_ci 1484cabdff1aSopenharmony_cistatic int opencl_frames_get_constraints(AVHWDeviceContext *hwdev, 1485cabdff1aSopenharmony_ci const void *hwconfig, 1486cabdff1aSopenharmony_ci AVHWFramesConstraints *constraints) 1487cabdff1aSopenharmony_ci{ 1488cabdff1aSopenharmony_ci AVOpenCLDeviceContext *hwctx = hwdev->hwctx; 1489cabdff1aSopenharmony_ci cl_uint nb_image_formats; 1490cabdff1aSopenharmony_ci cl_image_format *image_formats = NULL; 1491cabdff1aSopenharmony_ci cl_int cle; 1492cabdff1aSopenharmony_ci enum AVPixelFormat pix_fmt; 1493cabdff1aSopenharmony_ci int err, pix_fmts_found; 1494cabdff1aSopenharmony_ci size_t max_width, max_height; 1495cabdff1aSopenharmony_ci 1496cabdff1aSopenharmony_ci cle = clGetDeviceInfo(hwctx->device_id, CL_DEVICE_IMAGE2D_MAX_WIDTH, 1497cabdff1aSopenharmony_ci sizeof(max_width), &max_width, NULL); 1498cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 1499cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "Failed to query maximum " 1500cabdff1aSopenharmony_ci "supported image width: %d.\n", cle); 1501cabdff1aSopenharmony_ci } else { 1502cabdff1aSopenharmony_ci constraints->max_width = max_width; 1503cabdff1aSopenharmony_ci } 1504cabdff1aSopenharmony_ci cle = clGetDeviceInfo(hwctx->device_id, CL_DEVICE_IMAGE2D_MAX_HEIGHT, 1505cabdff1aSopenharmony_ci sizeof(max_height), &max_height, NULL); 1506cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 1507cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "Failed to query maximum " 1508cabdff1aSopenharmony_ci "supported image height: %d.\n", cle); 1509cabdff1aSopenharmony_ci } else { 1510cabdff1aSopenharmony_ci constraints->max_height = max_height; 1511cabdff1aSopenharmony_ci } 1512cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_DEBUG, "Maximum supported image size %dx%d.\n", 1513cabdff1aSopenharmony_ci constraints->max_width, constraints->max_height); 1514cabdff1aSopenharmony_ci 1515cabdff1aSopenharmony_ci cle = clGetSupportedImageFormats(hwctx->context, 1516cabdff1aSopenharmony_ci CL_MEM_READ_WRITE, 1517cabdff1aSopenharmony_ci CL_MEM_OBJECT_IMAGE2D, 1518cabdff1aSopenharmony_ci 0, NULL, &nb_image_formats); 1519cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 1520cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "Failed to query supported " 1521cabdff1aSopenharmony_ci "image formats: %d.\n", cle); 1522cabdff1aSopenharmony_ci err = AVERROR(ENOSYS); 1523cabdff1aSopenharmony_ci goto fail; 1524cabdff1aSopenharmony_ci } 1525cabdff1aSopenharmony_ci if (nb_image_formats == 0) { 1526cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "No image support in OpenCL " 1527cabdff1aSopenharmony_ci "driver (zero supported image formats).\n"); 1528cabdff1aSopenharmony_ci err = AVERROR(ENOSYS); 1529cabdff1aSopenharmony_ci goto fail; 1530cabdff1aSopenharmony_ci } 1531cabdff1aSopenharmony_ci 1532cabdff1aSopenharmony_ci image_formats = 1533cabdff1aSopenharmony_ci av_malloc_array(nb_image_formats, sizeof(*image_formats)); 1534cabdff1aSopenharmony_ci if (!image_formats) { 1535cabdff1aSopenharmony_ci err = AVERROR(ENOMEM); 1536cabdff1aSopenharmony_ci goto fail; 1537cabdff1aSopenharmony_ci } 1538cabdff1aSopenharmony_ci 1539cabdff1aSopenharmony_ci cle = clGetSupportedImageFormats(hwctx->context, 1540cabdff1aSopenharmony_ci CL_MEM_READ_WRITE, 1541cabdff1aSopenharmony_ci CL_MEM_OBJECT_IMAGE2D, 1542cabdff1aSopenharmony_ci nb_image_formats, 1543cabdff1aSopenharmony_ci image_formats, NULL); 1544cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 1545cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_ERROR, "Failed to query supported " 1546cabdff1aSopenharmony_ci "image formats: %d.\n", cle); 1547cabdff1aSopenharmony_ci err = AVERROR(ENOSYS); 1548cabdff1aSopenharmony_ci goto fail; 1549cabdff1aSopenharmony_ci } 1550cabdff1aSopenharmony_ci 1551cabdff1aSopenharmony_ci pix_fmts_found = 0; 1552cabdff1aSopenharmony_ci for (pix_fmt = 0; pix_fmt < AV_PIX_FMT_NB; pix_fmt++) { 1553cabdff1aSopenharmony_ci cl_image_format image_format; 1554cabdff1aSopenharmony_ci cl_image_desc image_desc; 1555cabdff1aSopenharmony_ci int plane, i; 1556cabdff1aSopenharmony_ci 1557cabdff1aSopenharmony_ci for (plane = 0;; plane++) { 1558cabdff1aSopenharmony_ci err = opencl_get_plane_format(pix_fmt, plane, 0, 0, 1559cabdff1aSopenharmony_ci &image_format, 1560cabdff1aSopenharmony_ci &image_desc); 1561cabdff1aSopenharmony_ci if (err < 0) 1562cabdff1aSopenharmony_ci break; 1563cabdff1aSopenharmony_ci 1564cabdff1aSopenharmony_ci for (i = 0; i < nb_image_formats; i++) { 1565cabdff1aSopenharmony_ci if (image_formats[i].image_channel_order == 1566cabdff1aSopenharmony_ci image_format.image_channel_order && 1567cabdff1aSopenharmony_ci image_formats[i].image_channel_data_type == 1568cabdff1aSopenharmony_ci image_format.image_channel_data_type) 1569cabdff1aSopenharmony_ci break; 1570cabdff1aSopenharmony_ci } 1571cabdff1aSopenharmony_ci if (i == nb_image_formats) { 1572cabdff1aSopenharmony_ci err = AVERROR(EINVAL); 1573cabdff1aSopenharmony_ci break; 1574cabdff1aSopenharmony_ci } 1575cabdff1aSopenharmony_ci } 1576cabdff1aSopenharmony_ci if (err != AVERROR(ENOENT)) 1577cabdff1aSopenharmony_ci continue; 1578cabdff1aSopenharmony_ci 1579cabdff1aSopenharmony_ci av_log(hwdev, AV_LOG_DEBUG, "Format %s supported.\n", 1580cabdff1aSopenharmony_ci av_get_pix_fmt_name(pix_fmt)); 1581cabdff1aSopenharmony_ci 1582cabdff1aSopenharmony_ci err = av_reallocp_array(&constraints->valid_sw_formats, 1583cabdff1aSopenharmony_ci pix_fmts_found + 2, 1584cabdff1aSopenharmony_ci sizeof(*constraints->valid_sw_formats)); 1585cabdff1aSopenharmony_ci if (err < 0) 1586cabdff1aSopenharmony_ci goto fail; 1587cabdff1aSopenharmony_ci constraints->valid_sw_formats[pix_fmts_found] = pix_fmt; 1588cabdff1aSopenharmony_ci constraints->valid_sw_formats[pix_fmts_found + 1] = 1589cabdff1aSopenharmony_ci AV_PIX_FMT_NONE; 1590cabdff1aSopenharmony_ci ++pix_fmts_found; 1591cabdff1aSopenharmony_ci } 1592cabdff1aSopenharmony_ci 1593cabdff1aSopenharmony_ci av_freep(&image_formats); 1594cabdff1aSopenharmony_ci 1595cabdff1aSopenharmony_ci constraints->valid_hw_formats = 1596cabdff1aSopenharmony_ci av_malloc_array(2, sizeof(*constraints->valid_hw_formats)); 1597cabdff1aSopenharmony_ci if (!constraints->valid_hw_formats) { 1598cabdff1aSopenharmony_ci err = AVERROR(ENOMEM); 1599cabdff1aSopenharmony_ci goto fail; 1600cabdff1aSopenharmony_ci } 1601cabdff1aSopenharmony_ci constraints->valid_hw_formats[0] = AV_PIX_FMT_OPENCL; 1602cabdff1aSopenharmony_ci constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE; 1603cabdff1aSopenharmony_ci 1604cabdff1aSopenharmony_ci return 0; 1605cabdff1aSopenharmony_ci 1606cabdff1aSopenharmony_cifail: 1607cabdff1aSopenharmony_ci av_freep(&image_formats); 1608cabdff1aSopenharmony_ci return err; 1609cabdff1aSopenharmony_ci} 1610cabdff1aSopenharmony_ci 1611cabdff1aSopenharmony_cistatic void opencl_pool_free(void *opaque, uint8_t *data) 1612cabdff1aSopenharmony_ci{ 1613cabdff1aSopenharmony_ci AVHWFramesContext *hwfc = opaque; 1614cabdff1aSopenharmony_ci AVOpenCLFrameDescriptor *desc = (AVOpenCLFrameDescriptor*)data; 1615cabdff1aSopenharmony_ci cl_int cle; 1616cabdff1aSopenharmony_ci int p; 1617cabdff1aSopenharmony_ci 1618cabdff1aSopenharmony_ci for (p = 0; p < desc->nb_planes; p++) { 1619cabdff1aSopenharmony_ci cle = clReleaseMemObject(desc->planes[p]); 1620cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 1621cabdff1aSopenharmony_ci av_log(hwfc, AV_LOG_ERROR, "Failed to release plane %d: " 1622cabdff1aSopenharmony_ci "%d.\n", p, cle); 1623cabdff1aSopenharmony_ci } 1624cabdff1aSopenharmony_ci } 1625cabdff1aSopenharmony_ci 1626cabdff1aSopenharmony_ci av_free(desc); 1627cabdff1aSopenharmony_ci} 1628cabdff1aSopenharmony_ci 1629cabdff1aSopenharmony_cistatic AVBufferRef *opencl_pool_alloc(void *opaque, size_t size) 1630cabdff1aSopenharmony_ci{ 1631cabdff1aSopenharmony_ci AVHWFramesContext *hwfc = opaque; 1632cabdff1aSopenharmony_ci AVOpenCLDeviceContext *hwctx = hwfc->device_ctx->hwctx; 1633cabdff1aSopenharmony_ci AVOpenCLFrameDescriptor *desc; 1634cabdff1aSopenharmony_ci cl_int cle; 1635cabdff1aSopenharmony_ci cl_mem image; 1636cabdff1aSopenharmony_ci cl_image_format image_format; 1637cabdff1aSopenharmony_ci cl_image_desc image_desc; 1638cabdff1aSopenharmony_ci int err, p; 1639cabdff1aSopenharmony_ci AVBufferRef *ref; 1640cabdff1aSopenharmony_ci 1641cabdff1aSopenharmony_ci desc = av_mallocz(sizeof(*desc)); 1642cabdff1aSopenharmony_ci if (!desc) 1643cabdff1aSopenharmony_ci return NULL; 1644cabdff1aSopenharmony_ci 1645cabdff1aSopenharmony_ci for (p = 0;; p++) { 1646cabdff1aSopenharmony_ci err = opencl_get_plane_format(hwfc->sw_format, p, 1647cabdff1aSopenharmony_ci hwfc->width, hwfc->height, 1648cabdff1aSopenharmony_ci &image_format, &image_desc); 1649cabdff1aSopenharmony_ci if (err == AVERROR(ENOENT)) 1650cabdff1aSopenharmony_ci break; 1651cabdff1aSopenharmony_ci if (err < 0) 1652cabdff1aSopenharmony_ci goto fail; 1653cabdff1aSopenharmony_ci 1654cabdff1aSopenharmony_ci // For generic image objects, the pitch is determined by the 1655cabdff1aSopenharmony_ci // implementation. 1656cabdff1aSopenharmony_ci image_desc.image_row_pitch = 0; 1657cabdff1aSopenharmony_ci 1658cabdff1aSopenharmony_ci image = clCreateImage(hwctx->context, CL_MEM_READ_WRITE, 1659cabdff1aSopenharmony_ci &image_format, &image_desc, NULL, &cle); 1660cabdff1aSopenharmony_ci if (!image) { 1661cabdff1aSopenharmony_ci av_log(hwfc, AV_LOG_ERROR, "Failed to create image for " 1662cabdff1aSopenharmony_ci "plane %d: %d.\n", p, cle); 1663cabdff1aSopenharmony_ci goto fail; 1664cabdff1aSopenharmony_ci } 1665cabdff1aSopenharmony_ci 1666cabdff1aSopenharmony_ci desc->planes[p] = image; 1667cabdff1aSopenharmony_ci } 1668cabdff1aSopenharmony_ci 1669cabdff1aSopenharmony_ci desc->nb_planes = p; 1670cabdff1aSopenharmony_ci 1671cabdff1aSopenharmony_ci ref = av_buffer_create((uint8_t*)desc, sizeof(*desc), 1672cabdff1aSopenharmony_ci &opencl_pool_free, hwfc, 0); 1673cabdff1aSopenharmony_ci if (!ref) 1674cabdff1aSopenharmony_ci goto fail; 1675cabdff1aSopenharmony_ci 1676cabdff1aSopenharmony_ci return ref; 1677cabdff1aSopenharmony_ci 1678cabdff1aSopenharmony_cifail: 1679cabdff1aSopenharmony_ci for (p = 0; desc->planes[p]; p++) 1680cabdff1aSopenharmony_ci clReleaseMemObject(desc->planes[p]); 1681cabdff1aSopenharmony_ci av_free(desc); 1682cabdff1aSopenharmony_ci return NULL; 1683cabdff1aSopenharmony_ci} 1684cabdff1aSopenharmony_ci 1685cabdff1aSopenharmony_cistatic int opencl_frames_init_command_queue(AVHWFramesContext *hwfc) 1686cabdff1aSopenharmony_ci{ 1687cabdff1aSopenharmony_ci AVOpenCLFramesContext *hwctx = hwfc->hwctx; 1688cabdff1aSopenharmony_ci OpenCLDeviceContext *devpriv = hwfc->device_ctx->internal->priv; 1689cabdff1aSopenharmony_ci OpenCLFramesContext *priv = hwfc->internal->priv; 1690cabdff1aSopenharmony_ci cl_int cle; 1691cabdff1aSopenharmony_ci 1692cabdff1aSopenharmony_ci priv->command_queue = hwctx->command_queue ? hwctx->command_queue 1693cabdff1aSopenharmony_ci : devpriv->command_queue; 1694cabdff1aSopenharmony_ci cle = clRetainCommandQueue(priv->command_queue); 1695cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 1696cabdff1aSopenharmony_ci av_log(hwfc, AV_LOG_ERROR, "Failed to retain frame " 1697cabdff1aSopenharmony_ci "command queue: %d.\n", cle); 1698cabdff1aSopenharmony_ci return AVERROR(EIO); 1699cabdff1aSopenharmony_ci } 1700cabdff1aSopenharmony_ci 1701cabdff1aSopenharmony_ci return 0; 1702cabdff1aSopenharmony_ci} 1703cabdff1aSopenharmony_ci 1704cabdff1aSopenharmony_cistatic int opencl_frames_init(AVHWFramesContext *hwfc) 1705cabdff1aSopenharmony_ci{ 1706cabdff1aSopenharmony_ci if (!hwfc->pool) { 1707cabdff1aSopenharmony_ci hwfc->internal->pool_internal = 1708cabdff1aSopenharmony_ci av_buffer_pool_init2(sizeof(cl_mem), hwfc, 1709cabdff1aSopenharmony_ci &opencl_pool_alloc, NULL); 1710cabdff1aSopenharmony_ci if (!hwfc->internal->pool_internal) 1711cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 1712cabdff1aSopenharmony_ci } 1713cabdff1aSopenharmony_ci 1714cabdff1aSopenharmony_ci return opencl_frames_init_command_queue(hwfc); 1715cabdff1aSopenharmony_ci} 1716cabdff1aSopenharmony_ci 1717cabdff1aSopenharmony_cistatic void opencl_frames_uninit(AVHWFramesContext *hwfc) 1718cabdff1aSopenharmony_ci{ 1719cabdff1aSopenharmony_ci OpenCLFramesContext *priv = hwfc->internal->priv; 1720cabdff1aSopenharmony_ci cl_int cle; 1721cabdff1aSopenharmony_ci 1722cabdff1aSopenharmony_ci#if HAVE_OPENCL_DXVA2 || HAVE_OPENCL_D3D11 1723cabdff1aSopenharmony_ci int i, p; 1724cabdff1aSopenharmony_ci for (i = 0; i < priv->nb_mapped_frames; i++) { 1725cabdff1aSopenharmony_ci AVOpenCLFrameDescriptor *desc = &priv->mapped_frames[i]; 1726cabdff1aSopenharmony_ci for (p = 0; p < desc->nb_planes; p++) { 1727cabdff1aSopenharmony_ci cle = clReleaseMemObject(desc->planes[p]); 1728cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 1729cabdff1aSopenharmony_ci av_log(hwfc, AV_LOG_ERROR, "Failed to release mapped " 1730cabdff1aSopenharmony_ci "frame object (frame %d plane %d): %d.\n", 1731cabdff1aSopenharmony_ci i, p, cle); 1732cabdff1aSopenharmony_ci } 1733cabdff1aSopenharmony_ci } 1734cabdff1aSopenharmony_ci } 1735cabdff1aSopenharmony_ci av_freep(&priv->mapped_frames); 1736cabdff1aSopenharmony_ci#endif 1737cabdff1aSopenharmony_ci 1738cabdff1aSopenharmony_ci if (priv->command_queue) { 1739cabdff1aSopenharmony_ci cle = clReleaseCommandQueue(priv->command_queue); 1740cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 1741cabdff1aSopenharmony_ci av_log(hwfc, AV_LOG_ERROR, "Failed to release frame " 1742cabdff1aSopenharmony_ci "command queue: %d.\n", cle); 1743cabdff1aSopenharmony_ci } 1744cabdff1aSopenharmony_ci priv->command_queue = NULL; 1745cabdff1aSopenharmony_ci } 1746cabdff1aSopenharmony_ci} 1747cabdff1aSopenharmony_ci 1748cabdff1aSopenharmony_cistatic int opencl_get_buffer(AVHWFramesContext *hwfc, AVFrame *frame) 1749cabdff1aSopenharmony_ci{ 1750cabdff1aSopenharmony_ci AVOpenCLFrameDescriptor *desc; 1751cabdff1aSopenharmony_ci int p; 1752cabdff1aSopenharmony_ci 1753cabdff1aSopenharmony_ci frame->buf[0] = av_buffer_pool_get(hwfc->pool); 1754cabdff1aSopenharmony_ci if (!frame->buf[0]) 1755cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 1756cabdff1aSopenharmony_ci 1757cabdff1aSopenharmony_ci desc = (AVOpenCLFrameDescriptor*)frame->buf[0]->data; 1758cabdff1aSopenharmony_ci 1759cabdff1aSopenharmony_ci for (p = 0; p < desc->nb_planes; p++) 1760cabdff1aSopenharmony_ci frame->data[p] = (uint8_t*)desc->planes[p]; 1761cabdff1aSopenharmony_ci 1762cabdff1aSopenharmony_ci frame->format = AV_PIX_FMT_OPENCL; 1763cabdff1aSopenharmony_ci frame->width = hwfc->width; 1764cabdff1aSopenharmony_ci frame->height = hwfc->height; 1765cabdff1aSopenharmony_ci 1766cabdff1aSopenharmony_ci return 0; 1767cabdff1aSopenharmony_ci} 1768cabdff1aSopenharmony_ci 1769cabdff1aSopenharmony_cistatic int opencl_transfer_get_formats(AVHWFramesContext *hwfc, 1770cabdff1aSopenharmony_ci enum AVHWFrameTransferDirection dir, 1771cabdff1aSopenharmony_ci enum AVPixelFormat **formats) 1772cabdff1aSopenharmony_ci{ 1773cabdff1aSopenharmony_ci enum AVPixelFormat *fmts; 1774cabdff1aSopenharmony_ci 1775cabdff1aSopenharmony_ci fmts = av_malloc_array(2, sizeof(*fmts)); 1776cabdff1aSopenharmony_ci if (!fmts) 1777cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 1778cabdff1aSopenharmony_ci 1779cabdff1aSopenharmony_ci fmts[0] = hwfc->sw_format; 1780cabdff1aSopenharmony_ci fmts[1] = AV_PIX_FMT_NONE; 1781cabdff1aSopenharmony_ci 1782cabdff1aSopenharmony_ci *formats = fmts; 1783cabdff1aSopenharmony_ci return 0; 1784cabdff1aSopenharmony_ci} 1785cabdff1aSopenharmony_ci 1786cabdff1aSopenharmony_cistatic int opencl_wait_events(AVHWFramesContext *hwfc, 1787cabdff1aSopenharmony_ci cl_event *events, int nb_events) 1788cabdff1aSopenharmony_ci{ 1789cabdff1aSopenharmony_ci cl_int cle; 1790cabdff1aSopenharmony_ci int i; 1791cabdff1aSopenharmony_ci 1792cabdff1aSopenharmony_ci cle = clWaitForEvents(nb_events, events); 1793cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 1794cabdff1aSopenharmony_ci av_log(hwfc, AV_LOG_ERROR, "Failed to wait for event " 1795cabdff1aSopenharmony_ci "completion: %d.\n", cle); 1796cabdff1aSopenharmony_ci return AVERROR(EIO); 1797cabdff1aSopenharmony_ci } 1798cabdff1aSopenharmony_ci 1799cabdff1aSopenharmony_ci for (i = 0; i < nb_events; i++) { 1800cabdff1aSopenharmony_ci cle = clReleaseEvent(events[i]); 1801cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 1802cabdff1aSopenharmony_ci av_log(hwfc, AV_LOG_ERROR, "Failed to release " 1803cabdff1aSopenharmony_ci "event: %d.\n", cle); 1804cabdff1aSopenharmony_ci } 1805cabdff1aSopenharmony_ci } 1806cabdff1aSopenharmony_ci 1807cabdff1aSopenharmony_ci return 0; 1808cabdff1aSopenharmony_ci} 1809cabdff1aSopenharmony_ci 1810cabdff1aSopenharmony_cistatic int opencl_transfer_data_from(AVHWFramesContext *hwfc, 1811cabdff1aSopenharmony_ci AVFrame *dst, const AVFrame *src) 1812cabdff1aSopenharmony_ci{ 1813cabdff1aSopenharmony_ci OpenCLFramesContext *priv = hwfc->internal->priv; 1814cabdff1aSopenharmony_ci cl_image_format image_format; 1815cabdff1aSopenharmony_ci cl_image_desc image_desc; 1816cabdff1aSopenharmony_ci cl_int cle; 1817cabdff1aSopenharmony_ci size_t origin[3] = { 0, 0, 0 }; 1818cabdff1aSopenharmony_ci size_t region[3]; 1819cabdff1aSopenharmony_ci cl_event events[AV_NUM_DATA_POINTERS]; 1820cabdff1aSopenharmony_ci int err, p; 1821cabdff1aSopenharmony_ci 1822cabdff1aSopenharmony_ci if (dst->format != hwfc->sw_format) 1823cabdff1aSopenharmony_ci return AVERROR(EINVAL); 1824cabdff1aSopenharmony_ci 1825cabdff1aSopenharmony_ci for (p = 0;; p++) { 1826cabdff1aSopenharmony_ci err = opencl_get_plane_format(hwfc->sw_format, p, 1827cabdff1aSopenharmony_ci src->width, src->height, 1828cabdff1aSopenharmony_ci &image_format, &image_desc); 1829cabdff1aSopenharmony_ci if (err < 0) { 1830cabdff1aSopenharmony_ci if (err == AVERROR(ENOENT)) 1831cabdff1aSopenharmony_ci err = 0; 1832cabdff1aSopenharmony_ci break; 1833cabdff1aSopenharmony_ci } 1834cabdff1aSopenharmony_ci 1835cabdff1aSopenharmony_ci if (!dst->data[p]) { 1836cabdff1aSopenharmony_ci av_log(hwfc, AV_LOG_ERROR, "Plane %d missing on " 1837cabdff1aSopenharmony_ci "destination frame for transfer.\n", p); 1838cabdff1aSopenharmony_ci err = AVERROR(EINVAL); 1839cabdff1aSopenharmony_ci break; 1840cabdff1aSopenharmony_ci } 1841cabdff1aSopenharmony_ci 1842cabdff1aSopenharmony_ci region[0] = image_desc.image_width; 1843cabdff1aSopenharmony_ci region[1] = image_desc.image_height; 1844cabdff1aSopenharmony_ci region[2] = 1; 1845cabdff1aSopenharmony_ci 1846cabdff1aSopenharmony_ci cle = clEnqueueReadImage(priv->command_queue, 1847cabdff1aSopenharmony_ci (cl_mem)src->data[p], 1848cabdff1aSopenharmony_ci CL_FALSE, origin, region, 1849cabdff1aSopenharmony_ci dst->linesize[p], 0, 1850cabdff1aSopenharmony_ci dst->data[p], 1851cabdff1aSopenharmony_ci 0, NULL, &events[p]); 1852cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 1853cabdff1aSopenharmony_ci av_log(hwfc, AV_LOG_ERROR, "Failed to enqueue read of " 1854cabdff1aSopenharmony_ci "OpenCL image plane %d: %d.\n", p, cle); 1855cabdff1aSopenharmony_ci err = AVERROR(EIO); 1856cabdff1aSopenharmony_ci break; 1857cabdff1aSopenharmony_ci } 1858cabdff1aSopenharmony_ci } 1859cabdff1aSopenharmony_ci 1860cabdff1aSopenharmony_ci opencl_wait_events(hwfc, events, p); 1861cabdff1aSopenharmony_ci 1862cabdff1aSopenharmony_ci return err; 1863cabdff1aSopenharmony_ci} 1864cabdff1aSopenharmony_ci 1865cabdff1aSopenharmony_cistatic int opencl_transfer_data_to(AVHWFramesContext *hwfc, 1866cabdff1aSopenharmony_ci AVFrame *dst, const AVFrame *src) 1867cabdff1aSopenharmony_ci{ 1868cabdff1aSopenharmony_ci OpenCLFramesContext *priv = hwfc->internal->priv; 1869cabdff1aSopenharmony_ci cl_image_format image_format; 1870cabdff1aSopenharmony_ci cl_image_desc image_desc; 1871cabdff1aSopenharmony_ci cl_int cle; 1872cabdff1aSopenharmony_ci size_t origin[3] = { 0, 0, 0 }; 1873cabdff1aSopenharmony_ci size_t region[3]; 1874cabdff1aSopenharmony_ci cl_event events[AV_NUM_DATA_POINTERS]; 1875cabdff1aSopenharmony_ci int err, p; 1876cabdff1aSopenharmony_ci 1877cabdff1aSopenharmony_ci if (src->format != hwfc->sw_format) 1878cabdff1aSopenharmony_ci return AVERROR(EINVAL); 1879cabdff1aSopenharmony_ci 1880cabdff1aSopenharmony_ci for (p = 0;; p++) { 1881cabdff1aSopenharmony_ci err = opencl_get_plane_format(hwfc->sw_format, p, 1882cabdff1aSopenharmony_ci src->width, src->height, 1883cabdff1aSopenharmony_ci &image_format, &image_desc); 1884cabdff1aSopenharmony_ci if (err < 0) { 1885cabdff1aSopenharmony_ci if (err == AVERROR(ENOENT)) 1886cabdff1aSopenharmony_ci err = 0; 1887cabdff1aSopenharmony_ci break; 1888cabdff1aSopenharmony_ci } 1889cabdff1aSopenharmony_ci 1890cabdff1aSopenharmony_ci if (!src->data[p]) { 1891cabdff1aSopenharmony_ci av_log(hwfc, AV_LOG_ERROR, "Plane %d missing on " 1892cabdff1aSopenharmony_ci "source frame for transfer.\n", p); 1893cabdff1aSopenharmony_ci err = AVERROR(EINVAL); 1894cabdff1aSopenharmony_ci break; 1895cabdff1aSopenharmony_ci } 1896cabdff1aSopenharmony_ci 1897cabdff1aSopenharmony_ci region[0] = image_desc.image_width; 1898cabdff1aSopenharmony_ci region[1] = image_desc.image_height; 1899cabdff1aSopenharmony_ci region[2] = 1; 1900cabdff1aSopenharmony_ci 1901cabdff1aSopenharmony_ci cle = clEnqueueWriteImage(priv->command_queue, 1902cabdff1aSopenharmony_ci (cl_mem)dst->data[p], 1903cabdff1aSopenharmony_ci CL_FALSE, origin, region, 1904cabdff1aSopenharmony_ci src->linesize[p], 0, 1905cabdff1aSopenharmony_ci src->data[p], 1906cabdff1aSopenharmony_ci 0, NULL, &events[p]); 1907cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 1908cabdff1aSopenharmony_ci av_log(hwfc, AV_LOG_ERROR, "Failed to enqueue write of " 1909cabdff1aSopenharmony_ci "OpenCL image plane %d: %d.\n", p, cle); 1910cabdff1aSopenharmony_ci err = AVERROR(EIO); 1911cabdff1aSopenharmony_ci break; 1912cabdff1aSopenharmony_ci } 1913cabdff1aSopenharmony_ci } 1914cabdff1aSopenharmony_ci 1915cabdff1aSopenharmony_ci opencl_wait_events(hwfc, events, p); 1916cabdff1aSopenharmony_ci 1917cabdff1aSopenharmony_ci return err; 1918cabdff1aSopenharmony_ci} 1919cabdff1aSopenharmony_ci 1920cabdff1aSopenharmony_citypedef struct OpenCLMapping { 1921cabdff1aSopenharmony_ci // The mapped addresses for each plane. 1922cabdff1aSopenharmony_ci // The destination frame is not available when we unmap, so these 1923cabdff1aSopenharmony_ci // need to be stored separately. 1924cabdff1aSopenharmony_ci void *address[AV_NUM_DATA_POINTERS]; 1925cabdff1aSopenharmony_ci} OpenCLMapping; 1926cabdff1aSopenharmony_ci 1927cabdff1aSopenharmony_cistatic void opencl_unmap_frame(AVHWFramesContext *hwfc, 1928cabdff1aSopenharmony_ci HWMapDescriptor *hwmap) 1929cabdff1aSopenharmony_ci{ 1930cabdff1aSopenharmony_ci OpenCLFramesContext *priv = hwfc->internal->priv; 1931cabdff1aSopenharmony_ci OpenCLMapping *map = hwmap->priv; 1932cabdff1aSopenharmony_ci cl_event events[AV_NUM_DATA_POINTERS]; 1933cabdff1aSopenharmony_ci int p, e; 1934cabdff1aSopenharmony_ci cl_int cle; 1935cabdff1aSopenharmony_ci 1936cabdff1aSopenharmony_ci for (p = e = 0; p < FF_ARRAY_ELEMS(map->address); p++) { 1937cabdff1aSopenharmony_ci if (!map->address[p]) 1938cabdff1aSopenharmony_ci break; 1939cabdff1aSopenharmony_ci 1940cabdff1aSopenharmony_ci cle = clEnqueueUnmapMemObject(priv->command_queue, 1941cabdff1aSopenharmony_ci (cl_mem)hwmap->source->data[p], 1942cabdff1aSopenharmony_ci map->address[p], 1943cabdff1aSopenharmony_ci 0, NULL, &events[e]); 1944cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 1945cabdff1aSopenharmony_ci av_log(hwfc, AV_LOG_ERROR, "Failed to unmap OpenCL " 1946cabdff1aSopenharmony_ci "image plane %d: %d.\n", p, cle); 1947cabdff1aSopenharmony_ci } 1948cabdff1aSopenharmony_ci ++e; 1949cabdff1aSopenharmony_ci } 1950cabdff1aSopenharmony_ci 1951cabdff1aSopenharmony_ci opencl_wait_events(hwfc, events, e); 1952cabdff1aSopenharmony_ci 1953cabdff1aSopenharmony_ci av_free(map); 1954cabdff1aSopenharmony_ci} 1955cabdff1aSopenharmony_ci 1956cabdff1aSopenharmony_cistatic int opencl_map_frame(AVHWFramesContext *hwfc, AVFrame *dst, 1957cabdff1aSopenharmony_ci const AVFrame *src, int flags) 1958cabdff1aSopenharmony_ci{ 1959cabdff1aSopenharmony_ci OpenCLFramesContext *priv = hwfc->internal->priv; 1960cabdff1aSopenharmony_ci cl_map_flags map_flags; 1961cabdff1aSopenharmony_ci cl_image_format image_format; 1962cabdff1aSopenharmony_ci cl_image_desc image_desc; 1963cabdff1aSopenharmony_ci cl_int cle; 1964cabdff1aSopenharmony_ci OpenCLMapping *map; 1965cabdff1aSopenharmony_ci size_t origin[3] = { 0, 0, 0 }; 1966cabdff1aSopenharmony_ci size_t region[3]; 1967cabdff1aSopenharmony_ci size_t row_pitch; 1968cabdff1aSopenharmony_ci cl_event events[AV_NUM_DATA_POINTERS]; 1969cabdff1aSopenharmony_ci int err, p; 1970cabdff1aSopenharmony_ci 1971cabdff1aSopenharmony_ci av_assert0(hwfc->sw_format == dst->format); 1972cabdff1aSopenharmony_ci 1973cabdff1aSopenharmony_ci if (flags & AV_HWFRAME_MAP_OVERWRITE && 1974cabdff1aSopenharmony_ci !(flags & AV_HWFRAME_MAP_READ)) { 1975cabdff1aSopenharmony_ci // This is mutually exclusive with the read/write flags, so 1976cabdff1aSopenharmony_ci // there is no way to map with read here. 1977cabdff1aSopenharmony_ci map_flags = CL_MAP_WRITE_INVALIDATE_REGION; 1978cabdff1aSopenharmony_ci } else { 1979cabdff1aSopenharmony_ci map_flags = 0; 1980cabdff1aSopenharmony_ci if (flags & AV_HWFRAME_MAP_READ) 1981cabdff1aSopenharmony_ci map_flags |= CL_MAP_READ; 1982cabdff1aSopenharmony_ci if (flags & AV_HWFRAME_MAP_WRITE) 1983cabdff1aSopenharmony_ci map_flags |= CL_MAP_WRITE; 1984cabdff1aSopenharmony_ci } 1985cabdff1aSopenharmony_ci 1986cabdff1aSopenharmony_ci map = av_mallocz(sizeof(*map)); 1987cabdff1aSopenharmony_ci if (!map) 1988cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 1989cabdff1aSopenharmony_ci 1990cabdff1aSopenharmony_ci for (p = 0;; p++) { 1991cabdff1aSopenharmony_ci err = opencl_get_plane_format(hwfc->sw_format, p, 1992cabdff1aSopenharmony_ci src->width, src->height, 1993cabdff1aSopenharmony_ci &image_format, &image_desc); 1994cabdff1aSopenharmony_ci if (err == AVERROR(ENOENT)) 1995cabdff1aSopenharmony_ci break; 1996cabdff1aSopenharmony_ci if (err < 0) 1997cabdff1aSopenharmony_ci goto fail; 1998cabdff1aSopenharmony_ci 1999cabdff1aSopenharmony_ci region[0] = image_desc.image_width; 2000cabdff1aSopenharmony_ci region[1] = image_desc.image_height; 2001cabdff1aSopenharmony_ci region[2] = 1; 2002cabdff1aSopenharmony_ci 2003cabdff1aSopenharmony_ci map->address[p] = 2004cabdff1aSopenharmony_ci clEnqueueMapImage(priv->command_queue, 2005cabdff1aSopenharmony_ci (cl_mem)src->data[p], 2006cabdff1aSopenharmony_ci CL_FALSE, map_flags, origin, region, 2007cabdff1aSopenharmony_ci &row_pitch, NULL, 0, NULL, 2008cabdff1aSopenharmony_ci &events[p], &cle); 2009cabdff1aSopenharmony_ci if (!map->address[p]) { 2010cabdff1aSopenharmony_ci av_log(hwfc, AV_LOG_ERROR, "Failed to map OpenCL " 2011cabdff1aSopenharmony_ci "image plane %d: %d.\n", p, cle); 2012cabdff1aSopenharmony_ci err = AVERROR(EIO); 2013cabdff1aSopenharmony_ci goto fail; 2014cabdff1aSopenharmony_ci } 2015cabdff1aSopenharmony_ci 2016cabdff1aSopenharmony_ci dst->data[p] = map->address[p]; 2017cabdff1aSopenharmony_ci 2018cabdff1aSopenharmony_ci av_log(hwfc, AV_LOG_DEBUG, "Map plane %d (%p -> %p).\n", 2019cabdff1aSopenharmony_ci p, src->data[p], dst->data[p]); 2020cabdff1aSopenharmony_ci } 2021cabdff1aSopenharmony_ci 2022cabdff1aSopenharmony_ci err = opencl_wait_events(hwfc, events, p); 2023cabdff1aSopenharmony_ci if (err < 0) 2024cabdff1aSopenharmony_ci goto fail; 2025cabdff1aSopenharmony_ci 2026cabdff1aSopenharmony_ci err = ff_hwframe_map_create(src->hw_frames_ctx, dst, src, 2027cabdff1aSopenharmony_ci &opencl_unmap_frame, map); 2028cabdff1aSopenharmony_ci if (err < 0) 2029cabdff1aSopenharmony_ci goto fail; 2030cabdff1aSopenharmony_ci 2031cabdff1aSopenharmony_ci dst->width = src->width; 2032cabdff1aSopenharmony_ci dst->height = src->height; 2033cabdff1aSopenharmony_ci 2034cabdff1aSopenharmony_ci return 0; 2035cabdff1aSopenharmony_ci 2036cabdff1aSopenharmony_cifail: 2037cabdff1aSopenharmony_ci for (p = 0; p < AV_NUM_DATA_POINTERS; p++) { 2038cabdff1aSopenharmony_ci if (!map->address[p]) 2039cabdff1aSopenharmony_ci break; 2040cabdff1aSopenharmony_ci clEnqueueUnmapMemObject(priv->command_queue, 2041cabdff1aSopenharmony_ci (cl_mem)src->data[p], 2042cabdff1aSopenharmony_ci map->address[p], 2043cabdff1aSopenharmony_ci 0, NULL, &events[p]); 2044cabdff1aSopenharmony_ci } 2045cabdff1aSopenharmony_ci if (p > 0) 2046cabdff1aSopenharmony_ci opencl_wait_events(hwfc, events, p); 2047cabdff1aSopenharmony_ci av_freep(&map); 2048cabdff1aSopenharmony_ci return err; 2049cabdff1aSopenharmony_ci} 2050cabdff1aSopenharmony_ci 2051cabdff1aSopenharmony_ci#if HAVE_OPENCL_DRM_BEIGNET 2052cabdff1aSopenharmony_ci 2053cabdff1aSopenharmony_citypedef struct DRMBeignetToOpenCLMapping { 2054cabdff1aSopenharmony_ci AVFrame *drm_frame; 2055cabdff1aSopenharmony_ci AVDRMFrameDescriptor *drm_desc; 2056cabdff1aSopenharmony_ci 2057cabdff1aSopenharmony_ci AVOpenCLFrameDescriptor frame; 2058cabdff1aSopenharmony_ci} DRMBeignetToOpenCLMapping; 2059cabdff1aSopenharmony_ci 2060cabdff1aSopenharmony_cistatic void opencl_unmap_from_drm_beignet(AVHWFramesContext *dst_fc, 2061cabdff1aSopenharmony_ci HWMapDescriptor *hwmap) 2062cabdff1aSopenharmony_ci{ 2063cabdff1aSopenharmony_ci DRMBeignetToOpenCLMapping *mapping = hwmap->priv; 2064cabdff1aSopenharmony_ci cl_int cle; 2065cabdff1aSopenharmony_ci int i; 2066cabdff1aSopenharmony_ci 2067cabdff1aSopenharmony_ci for (i = 0; i < mapping->frame.nb_planes; i++) { 2068cabdff1aSopenharmony_ci cle = clReleaseMemObject(mapping->frame.planes[i]); 2069cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 2070cabdff1aSopenharmony_ci av_log(dst_fc, AV_LOG_ERROR, "Failed to release CL image " 2071cabdff1aSopenharmony_ci "of plane %d of DRM frame: %d.\n", i, cle); 2072cabdff1aSopenharmony_ci } 2073cabdff1aSopenharmony_ci } 2074cabdff1aSopenharmony_ci 2075cabdff1aSopenharmony_ci av_free(mapping); 2076cabdff1aSopenharmony_ci} 2077cabdff1aSopenharmony_ci 2078cabdff1aSopenharmony_cistatic int opencl_map_from_drm_beignet(AVHWFramesContext *dst_fc, 2079cabdff1aSopenharmony_ci AVFrame *dst, const AVFrame *src, 2080cabdff1aSopenharmony_ci int flags) 2081cabdff1aSopenharmony_ci{ 2082cabdff1aSopenharmony_ci AVOpenCLDeviceContext *hwctx = dst_fc->device_ctx->hwctx; 2083cabdff1aSopenharmony_ci OpenCLDeviceContext *priv = dst_fc->device_ctx->internal->priv; 2084cabdff1aSopenharmony_ci DRMBeignetToOpenCLMapping *mapping; 2085cabdff1aSopenharmony_ci const AVDRMFrameDescriptor *desc; 2086cabdff1aSopenharmony_ci cl_int cle; 2087cabdff1aSopenharmony_ci int err, i, j, p; 2088cabdff1aSopenharmony_ci 2089cabdff1aSopenharmony_ci desc = (const AVDRMFrameDescriptor*)src->data[0]; 2090cabdff1aSopenharmony_ci 2091cabdff1aSopenharmony_ci mapping = av_mallocz(sizeof(*mapping)); 2092cabdff1aSopenharmony_ci if (!mapping) 2093cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 2094cabdff1aSopenharmony_ci 2095cabdff1aSopenharmony_ci p = 0; 2096cabdff1aSopenharmony_ci for (i = 0; i < desc->nb_layers; i++) { 2097cabdff1aSopenharmony_ci const AVDRMLayerDescriptor *layer = &desc->layers[i]; 2098cabdff1aSopenharmony_ci for (j = 0; j < layer->nb_planes; j++) { 2099cabdff1aSopenharmony_ci const AVDRMPlaneDescriptor *plane = &layer->planes[j]; 2100cabdff1aSopenharmony_ci const AVDRMObjectDescriptor *object = 2101cabdff1aSopenharmony_ci &desc->objects[plane->object_index]; 2102cabdff1aSopenharmony_ci 2103cabdff1aSopenharmony_ci cl_import_image_info_intel image_info = { 2104cabdff1aSopenharmony_ci .fd = object->fd, 2105cabdff1aSopenharmony_ci .size = object->size, 2106cabdff1aSopenharmony_ci .type = CL_MEM_OBJECT_IMAGE2D, 2107cabdff1aSopenharmony_ci .offset = plane->offset, 2108cabdff1aSopenharmony_ci .row_pitch = plane->pitch, 2109cabdff1aSopenharmony_ci }; 2110cabdff1aSopenharmony_ci cl_image_desc image_desc; 2111cabdff1aSopenharmony_ci 2112cabdff1aSopenharmony_ci err = opencl_get_plane_format(dst_fc->sw_format, p, 2113cabdff1aSopenharmony_ci src->width, src->height, 2114cabdff1aSopenharmony_ci &image_info.fmt, 2115cabdff1aSopenharmony_ci &image_desc); 2116cabdff1aSopenharmony_ci if (err < 0) { 2117cabdff1aSopenharmony_ci av_log(dst_fc, AV_LOG_ERROR, "DRM frame layer %d " 2118cabdff1aSopenharmony_ci "plane %d is not representable in OpenCL: %d.\n", 2119cabdff1aSopenharmony_ci i, j, err); 2120cabdff1aSopenharmony_ci goto fail; 2121cabdff1aSopenharmony_ci } 2122cabdff1aSopenharmony_ci image_info.width = image_desc.image_width; 2123cabdff1aSopenharmony_ci image_info.height = image_desc.image_height; 2124cabdff1aSopenharmony_ci 2125cabdff1aSopenharmony_ci mapping->frame.planes[p] = 2126cabdff1aSopenharmony_ci priv->clCreateImageFromFdINTEL(hwctx->context, 2127cabdff1aSopenharmony_ci &image_info, &cle); 2128cabdff1aSopenharmony_ci if (!mapping->frame.planes[p]) { 2129cabdff1aSopenharmony_ci av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL image " 2130cabdff1aSopenharmony_ci "from layer %d plane %d of DRM frame: %d.\n", 2131cabdff1aSopenharmony_ci i, j, cle); 2132cabdff1aSopenharmony_ci err = AVERROR(EIO); 2133cabdff1aSopenharmony_ci goto fail; 2134cabdff1aSopenharmony_ci } 2135cabdff1aSopenharmony_ci 2136cabdff1aSopenharmony_ci dst->data[p] = (uint8_t*)mapping->frame.planes[p]; 2137cabdff1aSopenharmony_ci mapping->frame.nb_planes = ++p; 2138cabdff1aSopenharmony_ci } 2139cabdff1aSopenharmony_ci } 2140cabdff1aSopenharmony_ci 2141cabdff1aSopenharmony_ci err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src, 2142cabdff1aSopenharmony_ci &opencl_unmap_from_drm_beignet, 2143cabdff1aSopenharmony_ci mapping); 2144cabdff1aSopenharmony_ci if (err < 0) 2145cabdff1aSopenharmony_ci goto fail; 2146cabdff1aSopenharmony_ci 2147cabdff1aSopenharmony_ci dst->width = src->width; 2148cabdff1aSopenharmony_ci dst->height = src->height; 2149cabdff1aSopenharmony_ci 2150cabdff1aSopenharmony_ci return 0; 2151cabdff1aSopenharmony_ci 2152cabdff1aSopenharmony_cifail: 2153cabdff1aSopenharmony_ci for (p = 0; p < mapping->frame.nb_planes; p++) { 2154cabdff1aSopenharmony_ci if (mapping->frame.planes[p]) 2155cabdff1aSopenharmony_ci clReleaseMemObject(mapping->frame.planes[p]); 2156cabdff1aSopenharmony_ci } 2157cabdff1aSopenharmony_ci av_free(mapping); 2158cabdff1aSopenharmony_ci memset(dst->data, 0, sizeof(dst->data)); 2159cabdff1aSopenharmony_ci return err; 2160cabdff1aSopenharmony_ci} 2161cabdff1aSopenharmony_ci 2162cabdff1aSopenharmony_ci#if HAVE_OPENCL_VAAPI_BEIGNET 2163cabdff1aSopenharmony_ci 2164cabdff1aSopenharmony_cistatic int opencl_map_from_vaapi(AVHWFramesContext *dst_fc, 2165cabdff1aSopenharmony_ci AVFrame *dst, const AVFrame *src, 2166cabdff1aSopenharmony_ci int flags) 2167cabdff1aSopenharmony_ci{ 2168cabdff1aSopenharmony_ci AVFrame *tmp; 2169cabdff1aSopenharmony_ci int err; 2170cabdff1aSopenharmony_ci 2171cabdff1aSopenharmony_ci tmp = av_frame_alloc(); 2172cabdff1aSopenharmony_ci if (!tmp) 2173cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 2174cabdff1aSopenharmony_ci 2175cabdff1aSopenharmony_ci tmp->format = AV_PIX_FMT_DRM_PRIME; 2176cabdff1aSopenharmony_ci 2177cabdff1aSopenharmony_ci err = av_hwframe_map(tmp, src, flags); 2178cabdff1aSopenharmony_ci if (err < 0) 2179cabdff1aSopenharmony_ci goto fail; 2180cabdff1aSopenharmony_ci 2181cabdff1aSopenharmony_ci err = opencl_map_from_drm_beignet(dst_fc, dst, tmp, flags); 2182cabdff1aSopenharmony_ci if (err < 0) 2183cabdff1aSopenharmony_ci goto fail; 2184cabdff1aSopenharmony_ci 2185cabdff1aSopenharmony_ci err = ff_hwframe_map_replace(dst, src); 2186cabdff1aSopenharmony_ci 2187cabdff1aSopenharmony_cifail: 2188cabdff1aSopenharmony_ci av_frame_free(&tmp); 2189cabdff1aSopenharmony_ci return err; 2190cabdff1aSopenharmony_ci} 2191cabdff1aSopenharmony_ci 2192cabdff1aSopenharmony_ci#endif /* HAVE_OPENCL_VAAPI_BEIGNET */ 2193cabdff1aSopenharmony_ci#endif /* HAVE_OPENCL_DRM_BEIGNET */ 2194cabdff1aSopenharmony_ci 2195cabdff1aSopenharmony_cistatic inline cl_mem_flags opencl_mem_flags_for_mapping(int map_flags) 2196cabdff1aSopenharmony_ci{ 2197cabdff1aSopenharmony_ci if ((map_flags & AV_HWFRAME_MAP_READ) && 2198cabdff1aSopenharmony_ci (map_flags & AV_HWFRAME_MAP_WRITE)) 2199cabdff1aSopenharmony_ci return CL_MEM_READ_WRITE; 2200cabdff1aSopenharmony_ci else if (map_flags & AV_HWFRAME_MAP_READ) 2201cabdff1aSopenharmony_ci return CL_MEM_READ_ONLY; 2202cabdff1aSopenharmony_ci else if (map_flags & AV_HWFRAME_MAP_WRITE) 2203cabdff1aSopenharmony_ci return CL_MEM_WRITE_ONLY; 2204cabdff1aSopenharmony_ci else 2205cabdff1aSopenharmony_ci return 0; 2206cabdff1aSopenharmony_ci} 2207cabdff1aSopenharmony_ci 2208cabdff1aSopenharmony_ci#if HAVE_OPENCL_VAAPI_INTEL_MEDIA 2209cabdff1aSopenharmony_ci 2210cabdff1aSopenharmony_cistatic void opencl_unmap_from_qsv(AVHWFramesContext *dst_fc, 2211cabdff1aSopenharmony_ci HWMapDescriptor *hwmap) 2212cabdff1aSopenharmony_ci{ 2213cabdff1aSopenharmony_ci AVOpenCLFrameDescriptor *desc = hwmap->priv; 2214cabdff1aSopenharmony_ci OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv; 2215cabdff1aSopenharmony_ci OpenCLFramesContext *frames_priv = dst_fc->internal->priv; 2216cabdff1aSopenharmony_ci cl_event event; 2217cabdff1aSopenharmony_ci cl_int cle; 2218cabdff1aSopenharmony_ci int p; 2219cabdff1aSopenharmony_ci 2220cabdff1aSopenharmony_ci av_log(dst_fc, AV_LOG_DEBUG, "Unmap QSV/VAAPI surface from OpenCL.\n"); 2221cabdff1aSopenharmony_ci 2222cabdff1aSopenharmony_ci cle = device_priv->clEnqueueReleaseVA_APIMediaSurfacesINTEL( 2223cabdff1aSopenharmony_ci frames_priv->command_queue, desc->nb_planes, desc->planes, 2224cabdff1aSopenharmony_ci 0, NULL, &event); 2225cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 2226cabdff1aSopenharmony_ci av_log(dst_fc, AV_LOG_ERROR, "Failed to release surface " 2227cabdff1aSopenharmony_ci "handles: %d.\n", cle); 2228cabdff1aSopenharmony_ci } 2229cabdff1aSopenharmony_ci 2230cabdff1aSopenharmony_ci opencl_wait_events(dst_fc, &event, 1); 2231cabdff1aSopenharmony_ci 2232cabdff1aSopenharmony_ci for (p = 0; p < desc->nb_planes; p++) { 2233cabdff1aSopenharmony_ci cle = clReleaseMemObject(desc->planes[p]); 2234cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 2235cabdff1aSopenharmony_ci av_log(dst_fc, AV_LOG_ERROR, "Failed to release CL " 2236cabdff1aSopenharmony_ci "image of plane %d of QSV/VAAPI surface: %d\n", 2237cabdff1aSopenharmony_ci p, cle); 2238cabdff1aSopenharmony_ci } 2239cabdff1aSopenharmony_ci } 2240cabdff1aSopenharmony_ci 2241cabdff1aSopenharmony_ci av_free(desc); 2242cabdff1aSopenharmony_ci} 2243cabdff1aSopenharmony_ci 2244cabdff1aSopenharmony_cistatic int opencl_map_from_qsv(AVHWFramesContext *dst_fc, AVFrame *dst, 2245cabdff1aSopenharmony_ci const AVFrame *src, int flags) 2246cabdff1aSopenharmony_ci{ 2247cabdff1aSopenharmony_ci AVHWFramesContext *src_fc = 2248cabdff1aSopenharmony_ci (AVHWFramesContext*)src->hw_frames_ctx->data; 2249cabdff1aSopenharmony_ci AVOpenCLDeviceContext *dst_dev = dst_fc->device_ctx->hwctx; 2250cabdff1aSopenharmony_ci OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv; 2251cabdff1aSopenharmony_ci OpenCLFramesContext *frames_priv = dst_fc->internal->priv; 2252cabdff1aSopenharmony_ci AVOpenCLFrameDescriptor *desc; 2253cabdff1aSopenharmony_ci VASurfaceID va_surface; 2254cabdff1aSopenharmony_ci cl_mem_flags cl_flags; 2255cabdff1aSopenharmony_ci cl_event event; 2256cabdff1aSopenharmony_ci cl_int cle; 2257cabdff1aSopenharmony_ci int err, p; 2258cabdff1aSopenharmony_ci 2259cabdff1aSopenharmony_ci#if CONFIG_LIBMFX 2260cabdff1aSopenharmony_ci if (src->format == AV_PIX_FMT_QSV) { 2261cabdff1aSopenharmony_ci void *base_handle; 2262cabdff1aSopenharmony_ci mfxFrameSurface1 *mfx_surface = (mfxFrameSurface1*)src->data[3]; 2263cabdff1aSopenharmony_ci err = ff_qsv_get_surface_base_handle(mfx_surface, 2264cabdff1aSopenharmony_ci AV_HWDEVICE_TYPE_VAAPI, 2265cabdff1aSopenharmony_ci &base_handle); 2266cabdff1aSopenharmony_ci if (err < 0) 2267cabdff1aSopenharmony_ci return err; 2268cabdff1aSopenharmony_ci va_surface = *(VASurfaceID *)base_handle; 2269cabdff1aSopenharmony_ci } else 2270cabdff1aSopenharmony_ci#endif 2271cabdff1aSopenharmony_ci if (src->format == AV_PIX_FMT_VAAPI) { 2272cabdff1aSopenharmony_ci va_surface = (VASurfaceID)(uintptr_t)src->data[3]; 2273cabdff1aSopenharmony_ci } else { 2274cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 2275cabdff1aSopenharmony_ci } 2276cabdff1aSopenharmony_ci 2277cabdff1aSopenharmony_ci cl_flags = opencl_mem_flags_for_mapping(flags); 2278cabdff1aSopenharmony_ci if (!cl_flags) 2279cabdff1aSopenharmony_ci return AVERROR(EINVAL); 2280cabdff1aSopenharmony_ci 2281cabdff1aSopenharmony_ci av_log(src_fc, AV_LOG_DEBUG, "Map QSV/VAAPI surface %#x to " 2282cabdff1aSopenharmony_ci "OpenCL.\n", va_surface); 2283cabdff1aSopenharmony_ci 2284cabdff1aSopenharmony_ci desc = av_mallocz(sizeof(*desc)); 2285cabdff1aSopenharmony_ci if (!desc) 2286cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 2287cabdff1aSopenharmony_ci 2288cabdff1aSopenharmony_ci // The cl_intel_va_api_media_sharing extension only supports NV12 2289cabdff1aSopenharmony_ci // surfaces, so for now there are always exactly two planes. 2290cabdff1aSopenharmony_ci desc->nb_planes = 2; 2291cabdff1aSopenharmony_ci 2292cabdff1aSopenharmony_ci for (p = 0; p < desc->nb_planes; p++) { 2293cabdff1aSopenharmony_ci desc->planes[p] = 2294cabdff1aSopenharmony_ci device_priv->clCreateFromVA_APIMediaSurfaceINTEL( 2295cabdff1aSopenharmony_ci dst_dev->context, cl_flags, &va_surface, p, &cle); 2296cabdff1aSopenharmony_ci if (!desc->planes[p]) { 2297cabdff1aSopenharmony_ci av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL " 2298cabdff1aSopenharmony_ci "image from plane %d of QSV/VAAPI surface " 2299cabdff1aSopenharmony_ci "%#x: %d.\n", p, va_surface, cle); 2300cabdff1aSopenharmony_ci err = AVERROR(EIO); 2301cabdff1aSopenharmony_ci goto fail; 2302cabdff1aSopenharmony_ci } 2303cabdff1aSopenharmony_ci 2304cabdff1aSopenharmony_ci dst->data[p] = (uint8_t*)desc->planes[p]; 2305cabdff1aSopenharmony_ci } 2306cabdff1aSopenharmony_ci 2307cabdff1aSopenharmony_ci cle = device_priv->clEnqueueAcquireVA_APIMediaSurfacesINTEL( 2308cabdff1aSopenharmony_ci frames_priv->command_queue, desc->nb_planes, desc->planes, 2309cabdff1aSopenharmony_ci 0, NULL, &event); 2310cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 2311cabdff1aSopenharmony_ci av_log(dst_fc, AV_LOG_ERROR, "Failed to acquire surface " 2312cabdff1aSopenharmony_ci "handles: %d.\n", cle); 2313cabdff1aSopenharmony_ci err = AVERROR(EIO); 2314cabdff1aSopenharmony_ci goto fail; 2315cabdff1aSopenharmony_ci } 2316cabdff1aSopenharmony_ci 2317cabdff1aSopenharmony_ci err = opencl_wait_events(dst_fc, &event, 1); 2318cabdff1aSopenharmony_ci if (err < 0) 2319cabdff1aSopenharmony_ci goto fail; 2320cabdff1aSopenharmony_ci 2321cabdff1aSopenharmony_ci err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src, 2322cabdff1aSopenharmony_ci &opencl_unmap_from_qsv, desc); 2323cabdff1aSopenharmony_ci if (err < 0) 2324cabdff1aSopenharmony_ci goto fail; 2325cabdff1aSopenharmony_ci 2326cabdff1aSopenharmony_ci dst->width = src->width; 2327cabdff1aSopenharmony_ci dst->height = src->height; 2328cabdff1aSopenharmony_ci 2329cabdff1aSopenharmony_ci return 0; 2330cabdff1aSopenharmony_ci 2331cabdff1aSopenharmony_cifail: 2332cabdff1aSopenharmony_ci for (p = 0; p < desc->nb_planes; p++) 2333cabdff1aSopenharmony_ci if (desc->planes[p]) 2334cabdff1aSopenharmony_ci clReleaseMemObject(desc->planes[p]); 2335cabdff1aSopenharmony_ci av_freep(&desc); 2336cabdff1aSopenharmony_ci memset(dst->data, 0, sizeof(dst->data)); 2337cabdff1aSopenharmony_ci return err; 2338cabdff1aSopenharmony_ci} 2339cabdff1aSopenharmony_ci 2340cabdff1aSopenharmony_ci#endif 2341cabdff1aSopenharmony_ci 2342cabdff1aSopenharmony_ci#if HAVE_OPENCL_DXVA2 2343cabdff1aSopenharmony_ci 2344cabdff1aSopenharmony_cistatic void opencl_unmap_from_dxva2(AVHWFramesContext *dst_fc, 2345cabdff1aSopenharmony_ci HWMapDescriptor *hwmap) 2346cabdff1aSopenharmony_ci{ 2347cabdff1aSopenharmony_ci AVOpenCLFrameDescriptor *desc = hwmap->priv; 2348cabdff1aSopenharmony_ci OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv; 2349cabdff1aSopenharmony_ci OpenCLFramesContext *frames_priv = dst_fc->device_ctx->internal->priv; 2350cabdff1aSopenharmony_ci cl_event event; 2351cabdff1aSopenharmony_ci cl_int cle; 2352cabdff1aSopenharmony_ci 2353cabdff1aSopenharmony_ci av_log(dst_fc, AV_LOG_DEBUG, "Unmap DXVA2 surface from OpenCL.\n"); 2354cabdff1aSopenharmony_ci 2355cabdff1aSopenharmony_ci cle = device_priv->clEnqueueReleaseDX9MediaSurfacesKHR( 2356cabdff1aSopenharmony_ci frames_priv->command_queue, desc->nb_planes, desc->planes, 2357cabdff1aSopenharmony_ci 0, NULL, &event); 2358cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 2359cabdff1aSopenharmony_ci av_log(dst_fc, AV_LOG_ERROR, "Failed to release surface " 2360cabdff1aSopenharmony_ci "handle: %d.\n", cle); 2361cabdff1aSopenharmony_ci return; 2362cabdff1aSopenharmony_ci } 2363cabdff1aSopenharmony_ci 2364cabdff1aSopenharmony_ci opencl_wait_events(dst_fc, &event, 1); 2365cabdff1aSopenharmony_ci} 2366cabdff1aSopenharmony_ci 2367cabdff1aSopenharmony_cistatic int opencl_map_from_dxva2(AVHWFramesContext *dst_fc, AVFrame *dst, 2368cabdff1aSopenharmony_ci const AVFrame *src, int flags) 2369cabdff1aSopenharmony_ci{ 2370cabdff1aSopenharmony_ci AVHWFramesContext *src_fc = 2371cabdff1aSopenharmony_ci (AVHWFramesContext*)src->hw_frames_ctx->data; 2372cabdff1aSopenharmony_ci AVDXVA2FramesContext *src_hwctx = src_fc->hwctx; 2373cabdff1aSopenharmony_ci OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv; 2374cabdff1aSopenharmony_ci OpenCLFramesContext *frames_priv = dst_fc->internal->priv; 2375cabdff1aSopenharmony_ci AVOpenCLFrameDescriptor *desc; 2376cabdff1aSopenharmony_ci cl_event event; 2377cabdff1aSopenharmony_ci cl_int cle; 2378cabdff1aSopenharmony_ci int err, i; 2379cabdff1aSopenharmony_ci 2380cabdff1aSopenharmony_ci av_log(dst_fc, AV_LOG_DEBUG, "Map DXVA2 surface %p to " 2381cabdff1aSopenharmony_ci "OpenCL.\n", src->data[3]); 2382cabdff1aSopenharmony_ci 2383cabdff1aSopenharmony_ci for (i = 0; i < src_hwctx->nb_surfaces; i++) { 2384cabdff1aSopenharmony_ci if (src_hwctx->surfaces[i] == (IDirect3DSurface9*)src->data[3]) 2385cabdff1aSopenharmony_ci break; 2386cabdff1aSopenharmony_ci } 2387cabdff1aSopenharmony_ci if (i >= src_hwctx->nb_surfaces) { 2388cabdff1aSopenharmony_ci av_log(dst_fc, AV_LOG_ERROR, "Trying to map from a surface which " 2389cabdff1aSopenharmony_ci "is not in the mapped frames context.\n"); 2390cabdff1aSopenharmony_ci return AVERROR(EINVAL); 2391cabdff1aSopenharmony_ci } 2392cabdff1aSopenharmony_ci 2393cabdff1aSopenharmony_ci desc = &frames_priv->mapped_frames[i]; 2394cabdff1aSopenharmony_ci 2395cabdff1aSopenharmony_ci cle = device_priv->clEnqueueAcquireDX9MediaSurfacesKHR( 2396cabdff1aSopenharmony_ci frames_priv->command_queue, desc->nb_planes, desc->planes, 2397cabdff1aSopenharmony_ci 0, NULL, &event); 2398cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 2399cabdff1aSopenharmony_ci av_log(dst_fc, AV_LOG_ERROR, "Failed to acquire surface " 2400cabdff1aSopenharmony_ci "handle: %d.\n", cle); 2401cabdff1aSopenharmony_ci return AVERROR(EIO); 2402cabdff1aSopenharmony_ci } 2403cabdff1aSopenharmony_ci 2404cabdff1aSopenharmony_ci err = opencl_wait_events(dst_fc, &event, 1); 2405cabdff1aSopenharmony_ci if (err < 0) 2406cabdff1aSopenharmony_ci goto fail; 2407cabdff1aSopenharmony_ci 2408cabdff1aSopenharmony_ci for (i = 0; i < desc->nb_planes; i++) 2409cabdff1aSopenharmony_ci dst->data[i] = (uint8_t*)desc->planes[i]; 2410cabdff1aSopenharmony_ci 2411cabdff1aSopenharmony_ci err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src, 2412cabdff1aSopenharmony_ci &opencl_unmap_from_dxva2, desc); 2413cabdff1aSopenharmony_ci if (err < 0) 2414cabdff1aSopenharmony_ci goto fail; 2415cabdff1aSopenharmony_ci 2416cabdff1aSopenharmony_ci dst->width = src->width; 2417cabdff1aSopenharmony_ci dst->height = src->height; 2418cabdff1aSopenharmony_ci 2419cabdff1aSopenharmony_ci return 0; 2420cabdff1aSopenharmony_ci 2421cabdff1aSopenharmony_cifail: 2422cabdff1aSopenharmony_ci cle = device_priv->clEnqueueReleaseDX9MediaSurfacesKHR( 2423cabdff1aSopenharmony_ci frames_priv->command_queue, desc->nb_planes, desc->planes, 2424cabdff1aSopenharmony_ci 0, NULL, &event); 2425cabdff1aSopenharmony_ci if (cle == CL_SUCCESS) 2426cabdff1aSopenharmony_ci opencl_wait_events(dst_fc, &event, 1); 2427cabdff1aSopenharmony_ci memset(dst->data, 0, sizeof(dst->data)); 2428cabdff1aSopenharmony_ci return err; 2429cabdff1aSopenharmony_ci} 2430cabdff1aSopenharmony_ci 2431cabdff1aSopenharmony_cistatic int opencl_frames_derive_from_dxva2(AVHWFramesContext *dst_fc, 2432cabdff1aSopenharmony_ci AVHWFramesContext *src_fc, int flags) 2433cabdff1aSopenharmony_ci{ 2434cabdff1aSopenharmony_ci AVOpenCLDeviceContext *dst_dev = dst_fc->device_ctx->hwctx; 2435cabdff1aSopenharmony_ci AVDXVA2FramesContext *src_hwctx = src_fc->hwctx; 2436cabdff1aSopenharmony_ci OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv; 2437cabdff1aSopenharmony_ci OpenCLFramesContext *frames_priv = dst_fc->internal->priv; 2438cabdff1aSopenharmony_ci cl_mem_flags cl_flags; 2439cabdff1aSopenharmony_ci cl_int cle; 2440cabdff1aSopenharmony_ci int err, i, p, nb_planes; 2441cabdff1aSopenharmony_ci 2442cabdff1aSopenharmony_ci if (src_fc->sw_format != AV_PIX_FMT_NV12) { 2443cabdff1aSopenharmony_ci av_log(dst_fc, AV_LOG_ERROR, "Only NV12 textures are supported " 2444cabdff1aSopenharmony_ci "for DXVA2 to OpenCL mapping.\n"); 2445cabdff1aSopenharmony_ci return AVERROR(EINVAL); 2446cabdff1aSopenharmony_ci } 2447cabdff1aSopenharmony_ci nb_planes = 2; 2448cabdff1aSopenharmony_ci 2449cabdff1aSopenharmony_ci if (src_fc->initial_pool_size == 0) { 2450cabdff1aSopenharmony_ci av_log(dst_fc, AV_LOG_ERROR, "Only fixed-size pools are supported " 2451cabdff1aSopenharmony_ci "for DXVA2 to OpenCL mapping.\n"); 2452cabdff1aSopenharmony_ci return AVERROR(EINVAL); 2453cabdff1aSopenharmony_ci } 2454cabdff1aSopenharmony_ci 2455cabdff1aSopenharmony_ci cl_flags = opencl_mem_flags_for_mapping(flags); 2456cabdff1aSopenharmony_ci if (!cl_flags) 2457cabdff1aSopenharmony_ci return AVERROR(EINVAL); 2458cabdff1aSopenharmony_ci 2459cabdff1aSopenharmony_ci frames_priv->nb_mapped_frames = src_hwctx->nb_surfaces; 2460cabdff1aSopenharmony_ci 2461cabdff1aSopenharmony_ci frames_priv->mapped_frames = 2462cabdff1aSopenharmony_ci av_calloc(frames_priv->nb_mapped_frames, 2463cabdff1aSopenharmony_ci sizeof(*frames_priv->mapped_frames)); 2464cabdff1aSopenharmony_ci if (!frames_priv->mapped_frames) 2465cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 2466cabdff1aSopenharmony_ci 2467cabdff1aSopenharmony_ci for (i = 0; i < frames_priv->nb_mapped_frames; i++) { 2468cabdff1aSopenharmony_ci AVOpenCLFrameDescriptor *desc = &frames_priv->mapped_frames[i]; 2469cabdff1aSopenharmony_ci cl_dx9_surface_info_khr surface_info = { 2470cabdff1aSopenharmony_ci .resource = src_hwctx->surfaces[i], 2471cabdff1aSopenharmony_ci .shared_handle = NULL, 2472cabdff1aSopenharmony_ci }; 2473cabdff1aSopenharmony_ci desc->nb_planes = nb_planes; 2474cabdff1aSopenharmony_ci for (p = 0; p < nb_planes; p++) { 2475cabdff1aSopenharmony_ci desc->planes[p] = 2476cabdff1aSopenharmony_ci device_priv->clCreateFromDX9MediaSurfaceKHR( 2477cabdff1aSopenharmony_ci dst_dev->context, cl_flags, 2478cabdff1aSopenharmony_ci device_priv->dx9_media_adapter_type, 2479cabdff1aSopenharmony_ci &surface_info, p, &cle); 2480cabdff1aSopenharmony_ci if (!desc->planes[p]) { 2481cabdff1aSopenharmony_ci av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL " 2482cabdff1aSopenharmony_ci "image from plane %d of DXVA2 surface %d: %d.\n", 2483cabdff1aSopenharmony_ci p, i, cle); 2484cabdff1aSopenharmony_ci err = AVERROR(EIO); 2485cabdff1aSopenharmony_ci goto fail; 2486cabdff1aSopenharmony_ci } 2487cabdff1aSopenharmony_ci } 2488cabdff1aSopenharmony_ci } 2489cabdff1aSopenharmony_ci 2490cabdff1aSopenharmony_ci return 0; 2491cabdff1aSopenharmony_ci 2492cabdff1aSopenharmony_cifail: 2493cabdff1aSopenharmony_ci for (i = 0; i < frames_priv->nb_mapped_frames; i++) { 2494cabdff1aSopenharmony_ci AVOpenCLFrameDescriptor *desc = &frames_priv->mapped_frames[i]; 2495cabdff1aSopenharmony_ci for (p = 0; p < desc->nb_planes; p++) { 2496cabdff1aSopenharmony_ci if (desc->planes[p]) 2497cabdff1aSopenharmony_ci clReleaseMemObject(desc->planes[p]); 2498cabdff1aSopenharmony_ci } 2499cabdff1aSopenharmony_ci } 2500cabdff1aSopenharmony_ci av_freep(&frames_priv->mapped_frames); 2501cabdff1aSopenharmony_ci frames_priv->nb_mapped_frames = 0; 2502cabdff1aSopenharmony_ci return err; 2503cabdff1aSopenharmony_ci} 2504cabdff1aSopenharmony_ci 2505cabdff1aSopenharmony_ci#endif 2506cabdff1aSopenharmony_ci 2507cabdff1aSopenharmony_ci#if HAVE_OPENCL_D3D11 2508cabdff1aSopenharmony_ci 2509cabdff1aSopenharmony_cistatic void opencl_unmap_from_d3d11(AVHWFramesContext *dst_fc, 2510cabdff1aSopenharmony_ci HWMapDescriptor *hwmap) 2511cabdff1aSopenharmony_ci{ 2512cabdff1aSopenharmony_ci AVOpenCLFrameDescriptor *desc = hwmap->priv; 2513cabdff1aSopenharmony_ci OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv; 2514cabdff1aSopenharmony_ci OpenCLFramesContext *frames_priv = dst_fc->device_ctx->internal->priv; 2515cabdff1aSopenharmony_ci cl_event event; 2516cabdff1aSopenharmony_ci cl_int cle; 2517cabdff1aSopenharmony_ci 2518cabdff1aSopenharmony_ci cle = device_priv->clEnqueueReleaseD3D11ObjectsKHR( 2519cabdff1aSopenharmony_ci frames_priv->command_queue, desc->nb_planes, desc->planes, 2520cabdff1aSopenharmony_ci 0, NULL, &event); 2521cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 2522cabdff1aSopenharmony_ci av_log(dst_fc, AV_LOG_ERROR, "Failed to release surface " 2523cabdff1aSopenharmony_ci "handle: %d.\n", cle); 2524cabdff1aSopenharmony_ci } 2525cabdff1aSopenharmony_ci 2526cabdff1aSopenharmony_ci opencl_wait_events(dst_fc, &event, 1); 2527cabdff1aSopenharmony_ci} 2528cabdff1aSopenharmony_ci 2529cabdff1aSopenharmony_cistatic int opencl_map_from_d3d11(AVHWFramesContext *dst_fc, AVFrame *dst, 2530cabdff1aSopenharmony_ci const AVFrame *src, int flags) 2531cabdff1aSopenharmony_ci{ 2532cabdff1aSopenharmony_ci OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv; 2533cabdff1aSopenharmony_ci OpenCLFramesContext *frames_priv = dst_fc->internal->priv; 2534cabdff1aSopenharmony_ci AVOpenCLFrameDescriptor *desc; 2535cabdff1aSopenharmony_ci cl_event event; 2536cabdff1aSopenharmony_ci cl_int cle; 2537cabdff1aSopenharmony_ci int err, index, i; 2538cabdff1aSopenharmony_ci 2539cabdff1aSopenharmony_ci index = (intptr_t)src->data[1]; 2540cabdff1aSopenharmony_ci if (index >= frames_priv->nb_mapped_frames) { 2541cabdff1aSopenharmony_ci av_log(dst_fc, AV_LOG_ERROR, "Texture array index out of range for " 2542cabdff1aSopenharmony_ci "mapping: %d >= %d.\n", index, frames_priv->nb_mapped_frames); 2543cabdff1aSopenharmony_ci return AVERROR(EINVAL); 2544cabdff1aSopenharmony_ci } 2545cabdff1aSopenharmony_ci 2546cabdff1aSopenharmony_ci av_log(dst_fc, AV_LOG_DEBUG, "Map D3D11 texture %d to OpenCL.\n", 2547cabdff1aSopenharmony_ci index); 2548cabdff1aSopenharmony_ci 2549cabdff1aSopenharmony_ci desc = &frames_priv->mapped_frames[index]; 2550cabdff1aSopenharmony_ci 2551cabdff1aSopenharmony_ci cle = device_priv->clEnqueueAcquireD3D11ObjectsKHR( 2552cabdff1aSopenharmony_ci frames_priv->command_queue, desc->nb_planes, desc->planes, 2553cabdff1aSopenharmony_ci 0, NULL, &event); 2554cabdff1aSopenharmony_ci if (cle != CL_SUCCESS) { 2555cabdff1aSopenharmony_ci av_log(dst_fc, AV_LOG_ERROR, "Failed to acquire surface " 2556cabdff1aSopenharmony_ci "handle: %d.\n", cle); 2557cabdff1aSopenharmony_ci return AVERROR(EIO); 2558cabdff1aSopenharmony_ci } 2559cabdff1aSopenharmony_ci 2560cabdff1aSopenharmony_ci err = opencl_wait_events(dst_fc, &event, 1); 2561cabdff1aSopenharmony_ci if (err < 0) 2562cabdff1aSopenharmony_ci goto fail; 2563cabdff1aSopenharmony_ci 2564cabdff1aSopenharmony_ci for (i = 0; i < desc->nb_planes; i++) 2565cabdff1aSopenharmony_ci dst->data[i] = (uint8_t*)desc->planes[i]; 2566cabdff1aSopenharmony_ci 2567cabdff1aSopenharmony_ci err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src, 2568cabdff1aSopenharmony_ci &opencl_unmap_from_d3d11, desc); 2569cabdff1aSopenharmony_ci if (err < 0) 2570cabdff1aSopenharmony_ci goto fail; 2571cabdff1aSopenharmony_ci 2572cabdff1aSopenharmony_ci dst->width = src->width; 2573cabdff1aSopenharmony_ci dst->height = src->height; 2574cabdff1aSopenharmony_ci 2575cabdff1aSopenharmony_ci return 0; 2576cabdff1aSopenharmony_ci 2577cabdff1aSopenharmony_cifail: 2578cabdff1aSopenharmony_ci cle = device_priv->clEnqueueReleaseD3D11ObjectsKHR( 2579cabdff1aSopenharmony_ci frames_priv->command_queue, desc->nb_planes, desc->planes, 2580cabdff1aSopenharmony_ci 0, NULL, &event); 2581cabdff1aSopenharmony_ci if (cle == CL_SUCCESS) 2582cabdff1aSopenharmony_ci opencl_wait_events(dst_fc, &event, 1); 2583cabdff1aSopenharmony_ci memset(dst->data, 0, sizeof(dst->data)); 2584cabdff1aSopenharmony_ci return err; 2585cabdff1aSopenharmony_ci} 2586cabdff1aSopenharmony_ci 2587cabdff1aSopenharmony_cistatic int opencl_frames_derive_from_d3d11(AVHWFramesContext *dst_fc, 2588cabdff1aSopenharmony_ci AVHWFramesContext *src_fc, int flags) 2589cabdff1aSopenharmony_ci{ 2590cabdff1aSopenharmony_ci AVOpenCLDeviceContext *dst_dev = dst_fc->device_ctx->hwctx; 2591cabdff1aSopenharmony_ci AVD3D11VAFramesContext *src_hwctx = src_fc->hwctx; 2592cabdff1aSopenharmony_ci OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv; 2593cabdff1aSopenharmony_ci OpenCLFramesContext *frames_priv = dst_fc->internal->priv; 2594cabdff1aSopenharmony_ci cl_mem_flags cl_flags; 2595cabdff1aSopenharmony_ci cl_int cle; 2596cabdff1aSopenharmony_ci int err, i, p, nb_planes; 2597cabdff1aSopenharmony_ci 2598cabdff1aSopenharmony_ci if (src_fc->sw_format != AV_PIX_FMT_NV12) { 2599cabdff1aSopenharmony_ci av_log(dst_fc, AV_LOG_ERROR, "Only NV12 textures are supported " 2600cabdff1aSopenharmony_ci "for D3D11 to OpenCL mapping.\n"); 2601cabdff1aSopenharmony_ci return AVERROR(EINVAL); 2602cabdff1aSopenharmony_ci } 2603cabdff1aSopenharmony_ci nb_planes = 2; 2604cabdff1aSopenharmony_ci 2605cabdff1aSopenharmony_ci if (src_fc->initial_pool_size == 0) { 2606cabdff1aSopenharmony_ci av_log(dst_fc, AV_LOG_ERROR, "Only fixed-size pools are supported " 2607cabdff1aSopenharmony_ci "for D3D11 to OpenCL mapping.\n"); 2608cabdff1aSopenharmony_ci return AVERROR(EINVAL); 2609cabdff1aSopenharmony_ci } 2610cabdff1aSopenharmony_ci 2611cabdff1aSopenharmony_ci cl_flags = opencl_mem_flags_for_mapping(flags); 2612cabdff1aSopenharmony_ci if (!cl_flags) 2613cabdff1aSopenharmony_ci return AVERROR(EINVAL); 2614cabdff1aSopenharmony_ci 2615cabdff1aSopenharmony_ci frames_priv->nb_mapped_frames = src_fc->initial_pool_size; 2616cabdff1aSopenharmony_ci 2617cabdff1aSopenharmony_ci frames_priv->mapped_frames = 2618cabdff1aSopenharmony_ci av_calloc(frames_priv->nb_mapped_frames, 2619cabdff1aSopenharmony_ci sizeof(*frames_priv->mapped_frames)); 2620cabdff1aSopenharmony_ci if (!frames_priv->mapped_frames) 2621cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 2622cabdff1aSopenharmony_ci 2623cabdff1aSopenharmony_ci for (i = 0; i < frames_priv->nb_mapped_frames; i++) { 2624cabdff1aSopenharmony_ci AVOpenCLFrameDescriptor *desc = &frames_priv->mapped_frames[i]; 2625cabdff1aSopenharmony_ci desc->nb_planes = nb_planes; 2626cabdff1aSopenharmony_ci for (p = 0; p < nb_planes; p++) { 2627cabdff1aSopenharmony_ci UINT subresource = 2 * i + p; 2628cabdff1aSopenharmony_ci 2629cabdff1aSopenharmony_ci desc->planes[p] = 2630cabdff1aSopenharmony_ci device_priv->clCreateFromD3D11Texture2DKHR( 2631cabdff1aSopenharmony_ci dst_dev->context, cl_flags, src_hwctx->texture, 2632cabdff1aSopenharmony_ci subresource, &cle); 2633cabdff1aSopenharmony_ci if (!desc->planes[p]) { 2634cabdff1aSopenharmony_ci av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL " 2635cabdff1aSopenharmony_ci "image from plane %d of D3D texture " 2636cabdff1aSopenharmony_ci "index %d (subresource %u): %d.\n", 2637cabdff1aSopenharmony_ci p, i, (unsigned int)subresource, cle); 2638cabdff1aSopenharmony_ci err = AVERROR(EIO); 2639cabdff1aSopenharmony_ci goto fail; 2640cabdff1aSopenharmony_ci } 2641cabdff1aSopenharmony_ci } 2642cabdff1aSopenharmony_ci } 2643cabdff1aSopenharmony_ci 2644cabdff1aSopenharmony_ci return 0; 2645cabdff1aSopenharmony_ci 2646cabdff1aSopenharmony_cifail: 2647cabdff1aSopenharmony_ci for (i = 0; i < frames_priv->nb_mapped_frames; i++) { 2648cabdff1aSopenharmony_ci AVOpenCLFrameDescriptor *desc = &frames_priv->mapped_frames[i]; 2649cabdff1aSopenharmony_ci for (p = 0; p < desc->nb_planes; p++) { 2650cabdff1aSopenharmony_ci if (desc->planes[p]) 2651cabdff1aSopenharmony_ci clReleaseMemObject(desc->planes[p]); 2652cabdff1aSopenharmony_ci } 2653cabdff1aSopenharmony_ci } 2654cabdff1aSopenharmony_ci av_freep(&frames_priv->mapped_frames); 2655cabdff1aSopenharmony_ci frames_priv->nb_mapped_frames = 0; 2656cabdff1aSopenharmony_ci return err; 2657cabdff1aSopenharmony_ci} 2658cabdff1aSopenharmony_ci 2659cabdff1aSopenharmony_ci#endif 2660cabdff1aSopenharmony_ci 2661cabdff1aSopenharmony_ci#if HAVE_OPENCL_DRM_ARM 2662cabdff1aSopenharmony_ci 2663cabdff1aSopenharmony_citypedef struct DRMARMtoOpenCLMapping { 2664cabdff1aSopenharmony_ci int nb_objects; 2665cabdff1aSopenharmony_ci cl_mem object_buffers[AV_DRM_MAX_PLANES]; 2666cabdff1aSopenharmony_ci int nb_planes; 2667cabdff1aSopenharmony_ci cl_mem plane_images[AV_DRM_MAX_PLANES]; 2668cabdff1aSopenharmony_ci} DRMARMtoOpenCLMapping; 2669cabdff1aSopenharmony_ci 2670cabdff1aSopenharmony_cistatic void opencl_unmap_from_drm_arm(AVHWFramesContext *dst_fc, 2671cabdff1aSopenharmony_ci HWMapDescriptor *hwmap) 2672cabdff1aSopenharmony_ci{ 2673cabdff1aSopenharmony_ci DRMARMtoOpenCLMapping *mapping = hwmap->priv; 2674cabdff1aSopenharmony_ci int i; 2675cabdff1aSopenharmony_ci 2676cabdff1aSopenharmony_ci for (i = 0; i < mapping->nb_planes; i++) 2677cabdff1aSopenharmony_ci clReleaseMemObject(mapping->plane_images[i]); 2678cabdff1aSopenharmony_ci 2679cabdff1aSopenharmony_ci for (i = 0; i < mapping->nb_objects; i++) 2680cabdff1aSopenharmony_ci clReleaseMemObject(mapping->object_buffers[i]); 2681cabdff1aSopenharmony_ci 2682cabdff1aSopenharmony_ci av_free(mapping); 2683cabdff1aSopenharmony_ci} 2684cabdff1aSopenharmony_ci 2685cabdff1aSopenharmony_cistatic int opencl_map_from_drm_arm(AVHWFramesContext *dst_fc, AVFrame *dst, 2686cabdff1aSopenharmony_ci const AVFrame *src, int flags) 2687cabdff1aSopenharmony_ci{ 2688cabdff1aSopenharmony_ci AVHWFramesContext *src_fc = 2689cabdff1aSopenharmony_ci (AVHWFramesContext*)src->hw_frames_ctx->data; 2690cabdff1aSopenharmony_ci AVOpenCLDeviceContext *dst_dev = dst_fc->device_ctx->hwctx; 2691cabdff1aSopenharmony_ci const AVDRMFrameDescriptor *desc; 2692cabdff1aSopenharmony_ci DRMARMtoOpenCLMapping *mapping = NULL; 2693cabdff1aSopenharmony_ci cl_mem_flags cl_flags; 2694cabdff1aSopenharmony_ci const cl_import_properties_arm props[3] = { 2695cabdff1aSopenharmony_ci CL_IMPORT_TYPE_ARM, CL_IMPORT_TYPE_DMA_BUF_ARM, 0, 2696cabdff1aSopenharmony_ci }; 2697cabdff1aSopenharmony_ci cl_int cle; 2698cabdff1aSopenharmony_ci int err, i, j; 2699cabdff1aSopenharmony_ci 2700cabdff1aSopenharmony_ci desc = (const AVDRMFrameDescriptor*)src->data[0]; 2701cabdff1aSopenharmony_ci 2702cabdff1aSopenharmony_ci cl_flags = opencl_mem_flags_for_mapping(flags); 2703cabdff1aSopenharmony_ci if (!cl_flags) 2704cabdff1aSopenharmony_ci return AVERROR(EINVAL); 2705cabdff1aSopenharmony_ci 2706cabdff1aSopenharmony_ci mapping = av_mallocz(sizeof(*mapping)); 2707cabdff1aSopenharmony_ci if (!mapping) 2708cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 2709cabdff1aSopenharmony_ci 2710cabdff1aSopenharmony_ci mapping->nb_objects = desc->nb_objects; 2711cabdff1aSopenharmony_ci for (i = 0; i < desc->nb_objects; i++) { 2712cabdff1aSopenharmony_ci int fd = desc->objects[i].fd; 2713cabdff1aSopenharmony_ci 2714cabdff1aSopenharmony_ci av_log(dst_fc, AV_LOG_DEBUG, "Map DRM PRIME fd %d to OpenCL.\n", fd); 2715cabdff1aSopenharmony_ci 2716cabdff1aSopenharmony_ci if (desc->objects[i].format_modifier) { 2717cabdff1aSopenharmony_ci av_log(dst_fc, AV_LOG_DEBUG, "Warning: object %d fd %d has " 2718cabdff1aSopenharmony_ci "nonzero format modifier %"PRId64", result may not " 2719cabdff1aSopenharmony_ci "be as expected.\n", i, fd, 2720cabdff1aSopenharmony_ci desc->objects[i].format_modifier); 2721cabdff1aSopenharmony_ci } 2722cabdff1aSopenharmony_ci 2723cabdff1aSopenharmony_ci mapping->object_buffers[i] = 2724cabdff1aSopenharmony_ci clImportMemoryARM(dst_dev->context, cl_flags, props, 2725cabdff1aSopenharmony_ci &fd, desc->objects[i].size, &cle); 2726cabdff1aSopenharmony_ci if (!mapping->object_buffers[i]) { 2727cabdff1aSopenharmony_ci av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL buffer " 2728cabdff1aSopenharmony_ci "from object %d (fd %d, size %"SIZE_SPECIFIER") of DRM frame: %d.\n", 2729cabdff1aSopenharmony_ci i, fd, desc->objects[i].size, cle); 2730cabdff1aSopenharmony_ci err = AVERROR(EIO); 2731cabdff1aSopenharmony_ci goto fail; 2732cabdff1aSopenharmony_ci } 2733cabdff1aSopenharmony_ci } 2734cabdff1aSopenharmony_ci 2735cabdff1aSopenharmony_ci mapping->nb_planes = 0; 2736cabdff1aSopenharmony_ci for (i = 0; i < desc->nb_layers; i++) { 2737cabdff1aSopenharmony_ci const AVDRMLayerDescriptor *layer = &desc->layers[i]; 2738cabdff1aSopenharmony_ci 2739cabdff1aSopenharmony_ci for (j = 0; j < layer->nb_planes; j++) { 2740cabdff1aSopenharmony_ci const AVDRMPlaneDescriptor *plane = &layer->planes[j]; 2741cabdff1aSopenharmony_ci cl_mem plane_buffer; 2742cabdff1aSopenharmony_ci cl_image_format image_format; 2743cabdff1aSopenharmony_ci cl_image_desc image_desc; 2744cabdff1aSopenharmony_ci cl_buffer_region region; 2745cabdff1aSopenharmony_ci int p = mapping->nb_planes; 2746cabdff1aSopenharmony_ci 2747cabdff1aSopenharmony_ci err = opencl_get_plane_format(src_fc->sw_format, p, 2748cabdff1aSopenharmony_ci src_fc->width, src_fc->height, 2749cabdff1aSopenharmony_ci &image_format, &image_desc); 2750cabdff1aSopenharmony_ci if (err < 0) { 2751cabdff1aSopenharmony_ci av_log(dst_fc, AV_LOG_ERROR, "Invalid plane %d (DRM " 2752cabdff1aSopenharmony_ci "layer %d plane %d): %d.\n", p, i, j, err); 2753cabdff1aSopenharmony_ci goto fail; 2754cabdff1aSopenharmony_ci } 2755cabdff1aSopenharmony_ci 2756cabdff1aSopenharmony_ci region.origin = plane->offset; 2757cabdff1aSopenharmony_ci region.size = image_desc.image_row_pitch * 2758cabdff1aSopenharmony_ci image_desc.image_height; 2759cabdff1aSopenharmony_ci 2760cabdff1aSopenharmony_ci plane_buffer = 2761cabdff1aSopenharmony_ci clCreateSubBuffer(mapping->object_buffers[plane->object_index], 2762cabdff1aSopenharmony_ci cl_flags, 2763cabdff1aSopenharmony_ci CL_BUFFER_CREATE_TYPE_REGION, 2764cabdff1aSopenharmony_ci ®ion, &cle); 2765cabdff1aSopenharmony_ci if (!plane_buffer) { 2766cabdff1aSopenharmony_ci av_log(dst_fc, AV_LOG_ERROR, "Failed to create sub-buffer " 2767cabdff1aSopenharmony_ci "for plane %d: %d.\n", p, cle); 2768cabdff1aSopenharmony_ci err = AVERROR(EIO); 2769cabdff1aSopenharmony_ci goto fail; 2770cabdff1aSopenharmony_ci } 2771cabdff1aSopenharmony_ci 2772cabdff1aSopenharmony_ci image_desc.buffer = plane_buffer; 2773cabdff1aSopenharmony_ci 2774cabdff1aSopenharmony_ci mapping->plane_images[p] = 2775cabdff1aSopenharmony_ci clCreateImage(dst_dev->context, cl_flags, 2776cabdff1aSopenharmony_ci &image_format, &image_desc, NULL, &cle); 2777cabdff1aSopenharmony_ci 2778cabdff1aSopenharmony_ci // Unreference the sub-buffer immediately - we don't need it 2779cabdff1aSopenharmony_ci // directly and a reference is held by the image. 2780cabdff1aSopenharmony_ci clReleaseMemObject(plane_buffer); 2781cabdff1aSopenharmony_ci 2782cabdff1aSopenharmony_ci if (!mapping->plane_images[p]) { 2783cabdff1aSopenharmony_ci av_log(dst_fc, AV_LOG_ERROR, "Failed to create image " 2784cabdff1aSopenharmony_ci "for plane %d: %d.\n", p, cle); 2785cabdff1aSopenharmony_ci err = AVERROR(EIO); 2786cabdff1aSopenharmony_ci goto fail; 2787cabdff1aSopenharmony_ci } 2788cabdff1aSopenharmony_ci 2789cabdff1aSopenharmony_ci ++mapping->nb_planes; 2790cabdff1aSopenharmony_ci } 2791cabdff1aSopenharmony_ci } 2792cabdff1aSopenharmony_ci 2793cabdff1aSopenharmony_ci for (i = 0; i < mapping->nb_planes; i++) 2794cabdff1aSopenharmony_ci dst->data[i] = (uint8_t*)mapping->plane_images[i]; 2795cabdff1aSopenharmony_ci 2796cabdff1aSopenharmony_ci err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src, 2797cabdff1aSopenharmony_ci &opencl_unmap_from_drm_arm, mapping); 2798cabdff1aSopenharmony_ci if (err < 0) 2799cabdff1aSopenharmony_ci goto fail; 2800cabdff1aSopenharmony_ci 2801cabdff1aSopenharmony_ci dst->width = src->width; 2802cabdff1aSopenharmony_ci dst->height = src->height; 2803cabdff1aSopenharmony_ci 2804cabdff1aSopenharmony_ci return 0; 2805cabdff1aSopenharmony_ci 2806cabdff1aSopenharmony_cifail: 2807cabdff1aSopenharmony_ci for (i = 0; i < mapping->nb_planes; i++) { 2808cabdff1aSopenharmony_ci clReleaseMemObject(mapping->plane_images[i]); 2809cabdff1aSopenharmony_ci } 2810cabdff1aSopenharmony_ci for (i = 0; i < mapping->nb_objects; i++) { 2811cabdff1aSopenharmony_ci if (mapping->object_buffers[i]) 2812cabdff1aSopenharmony_ci clReleaseMemObject(mapping->object_buffers[i]); 2813cabdff1aSopenharmony_ci } 2814cabdff1aSopenharmony_ci av_free(mapping); 2815cabdff1aSopenharmony_ci memset(dst->data, 0, sizeof(dst->data)); 2816cabdff1aSopenharmony_ci return err; 2817cabdff1aSopenharmony_ci} 2818cabdff1aSopenharmony_ci 2819cabdff1aSopenharmony_ci#endif 2820cabdff1aSopenharmony_ci 2821cabdff1aSopenharmony_cistatic int opencl_map_from(AVHWFramesContext *hwfc, AVFrame *dst, 2822cabdff1aSopenharmony_ci const AVFrame *src, int flags) 2823cabdff1aSopenharmony_ci{ 2824cabdff1aSopenharmony_ci av_assert0(src->format == AV_PIX_FMT_OPENCL); 2825cabdff1aSopenharmony_ci if (hwfc->sw_format != dst->format) 2826cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 2827cabdff1aSopenharmony_ci return opencl_map_frame(hwfc, dst, src, flags); 2828cabdff1aSopenharmony_ci} 2829cabdff1aSopenharmony_ci 2830cabdff1aSopenharmony_cistatic int opencl_map_to(AVHWFramesContext *hwfc, AVFrame *dst, 2831cabdff1aSopenharmony_ci const AVFrame *src, int flags) 2832cabdff1aSopenharmony_ci{ 2833cabdff1aSopenharmony_ci av_unused OpenCLDeviceContext *priv = hwfc->device_ctx->internal->priv; 2834cabdff1aSopenharmony_ci av_assert0(dst->format == AV_PIX_FMT_OPENCL); 2835cabdff1aSopenharmony_ci switch (src->format) { 2836cabdff1aSopenharmony_ci#if HAVE_OPENCL_DRM_BEIGNET 2837cabdff1aSopenharmony_ci case AV_PIX_FMT_DRM_PRIME: 2838cabdff1aSopenharmony_ci if (priv->beignet_drm_mapping_usable) 2839cabdff1aSopenharmony_ci return opencl_map_from_drm_beignet(hwfc, dst, src, flags); 2840cabdff1aSopenharmony_ci#endif 2841cabdff1aSopenharmony_ci#if HAVE_OPENCL_VAAPI_BEIGNET 2842cabdff1aSopenharmony_ci case AV_PIX_FMT_VAAPI: 2843cabdff1aSopenharmony_ci if (priv->beignet_drm_mapping_usable) 2844cabdff1aSopenharmony_ci return opencl_map_from_vaapi(hwfc, dst, src, flags); 2845cabdff1aSopenharmony_ci#endif 2846cabdff1aSopenharmony_ci#if HAVE_OPENCL_VAAPI_INTEL_MEDIA 2847cabdff1aSopenharmony_ci case AV_PIX_FMT_QSV: 2848cabdff1aSopenharmony_ci case AV_PIX_FMT_VAAPI: 2849cabdff1aSopenharmony_ci if (priv->qsv_mapping_usable) 2850cabdff1aSopenharmony_ci return opencl_map_from_qsv(hwfc, dst, src, flags); 2851cabdff1aSopenharmony_ci#endif 2852cabdff1aSopenharmony_ci#if HAVE_OPENCL_DXVA2 2853cabdff1aSopenharmony_ci case AV_PIX_FMT_DXVA2_VLD: 2854cabdff1aSopenharmony_ci if (priv->dxva2_mapping_usable) 2855cabdff1aSopenharmony_ci return opencl_map_from_dxva2(hwfc, dst, src, flags); 2856cabdff1aSopenharmony_ci#endif 2857cabdff1aSopenharmony_ci#if HAVE_OPENCL_D3D11 2858cabdff1aSopenharmony_ci case AV_PIX_FMT_D3D11: 2859cabdff1aSopenharmony_ci if (priv->d3d11_mapping_usable) 2860cabdff1aSopenharmony_ci return opencl_map_from_d3d11(hwfc, dst, src, flags); 2861cabdff1aSopenharmony_ci#endif 2862cabdff1aSopenharmony_ci#if HAVE_OPENCL_DRM_ARM 2863cabdff1aSopenharmony_ci case AV_PIX_FMT_DRM_PRIME: 2864cabdff1aSopenharmony_ci if (priv->drm_arm_mapping_usable) 2865cabdff1aSopenharmony_ci return opencl_map_from_drm_arm(hwfc, dst, src, flags); 2866cabdff1aSopenharmony_ci#endif 2867cabdff1aSopenharmony_ci } 2868cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 2869cabdff1aSopenharmony_ci} 2870cabdff1aSopenharmony_ci 2871cabdff1aSopenharmony_cistatic int opencl_frames_derive_to(AVHWFramesContext *dst_fc, 2872cabdff1aSopenharmony_ci AVHWFramesContext *src_fc, int flags) 2873cabdff1aSopenharmony_ci{ 2874cabdff1aSopenharmony_ci av_unused OpenCLDeviceContext *priv = dst_fc->device_ctx->internal->priv; 2875cabdff1aSopenharmony_ci switch (src_fc->device_ctx->type) { 2876cabdff1aSopenharmony_ci#if HAVE_OPENCL_DRM_BEIGNET 2877cabdff1aSopenharmony_ci case AV_HWDEVICE_TYPE_DRM: 2878cabdff1aSopenharmony_ci if (!priv->beignet_drm_mapping_usable) 2879cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 2880cabdff1aSopenharmony_ci break; 2881cabdff1aSopenharmony_ci#endif 2882cabdff1aSopenharmony_ci#if HAVE_OPENCL_VAAPI_BEIGNET 2883cabdff1aSopenharmony_ci case AV_HWDEVICE_TYPE_VAAPI: 2884cabdff1aSopenharmony_ci if (!priv->beignet_drm_mapping_usable) 2885cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 2886cabdff1aSopenharmony_ci break; 2887cabdff1aSopenharmony_ci#endif 2888cabdff1aSopenharmony_ci#if HAVE_OPENCL_VAAPI_INTEL_MEDIA 2889cabdff1aSopenharmony_ci case AV_HWDEVICE_TYPE_QSV: 2890cabdff1aSopenharmony_ci case AV_HWDEVICE_TYPE_VAAPI: 2891cabdff1aSopenharmony_ci if (!priv->qsv_mapping_usable) 2892cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 2893cabdff1aSopenharmony_ci break; 2894cabdff1aSopenharmony_ci#endif 2895cabdff1aSopenharmony_ci#if HAVE_OPENCL_DXVA2 2896cabdff1aSopenharmony_ci case AV_HWDEVICE_TYPE_DXVA2: 2897cabdff1aSopenharmony_ci if (!priv->dxva2_mapping_usable) 2898cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 2899cabdff1aSopenharmony_ci { 2900cabdff1aSopenharmony_ci int err; 2901cabdff1aSopenharmony_ci err = opencl_frames_derive_from_dxva2(dst_fc, src_fc, flags); 2902cabdff1aSopenharmony_ci if (err < 0) 2903cabdff1aSopenharmony_ci return err; 2904cabdff1aSopenharmony_ci } 2905cabdff1aSopenharmony_ci break; 2906cabdff1aSopenharmony_ci#endif 2907cabdff1aSopenharmony_ci#if HAVE_OPENCL_D3D11 2908cabdff1aSopenharmony_ci case AV_HWDEVICE_TYPE_D3D11VA: 2909cabdff1aSopenharmony_ci if (!priv->d3d11_mapping_usable) 2910cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 2911cabdff1aSopenharmony_ci { 2912cabdff1aSopenharmony_ci int err; 2913cabdff1aSopenharmony_ci err = opencl_frames_derive_from_d3d11(dst_fc, src_fc, flags); 2914cabdff1aSopenharmony_ci if (err < 0) 2915cabdff1aSopenharmony_ci return err; 2916cabdff1aSopenharmony_ci } 2917cabdff1aSopenharmony_ci break; 2918cabdff1aSopenharmony_ci#endif 2919cabdff1aSopenharmony_ci#if HAVE_OPENCL_DRM_ARM 2920cabdff1aSopenharmony_ci case AV_HWDEVICE_TYPE_DRM: 2921cabdff1aSopenharmony_ci if (!priv->drm_arm_mapping_usable) 2922cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 2923cabdff1aSopenharmony_ci break; 2924cabdff1aSopenharmony_ci#endif 2925cabdff1aSopenharmony_ci default: 2926cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 2927cabdff1aSopenharmony_ci } 2928cabdff1aSopenharmony_ci return opencl_frames_init_command_queue(dst_fc); 2929cabdff1aSopenharmony_ci} 2930cabdff1aSopenharmony_ci 2931cabdff1aSopenharmony_ciconst HWContextType ff_hwcontext_type_opencl = { 2932cabdff1aSopenharmony_ci .type = AV_HWDEVICE_TYPE_OPENCL, 2933cabdff1aSopenharmony_ci .name = "OpenCL", 2934cabdff1aSopenharmony_ci 2935cabdff1aSopenharmony_ci .device_hwctx_size = sizeof(AVOpenCLDeviceContext), 2936cabdff1aSopenharmony_ci .device_priv_size = sizeof(OpenCLDeviceContext), 2937cabdff1aSopenharmony_ci .frames_hwctx_size = sizeof(AVOpenCLFramesContext), 2938cabdff1aSopenharmony_ci .frames_priv_size = sizeof(OpenCLFramesContext), 2939cabdff1aSopenharmony_ci 2940cabdff1aSopenharmony_ci .device_create = &opencl_device_create, 2941cabdff1aSopenharmony_ci .device_derive = &opencl_device_derive, 2942cabdff1aSopenharmony_ci .device_init = &opencl_device_init, 2943cabdff1aSopenharmony_ci .device_uninit = &opencl_device_uninit, 2944cabdff1aSopenharmony_ci 2945cabdff1aSopenharmony_ci .frames_get_constraints = &opencl_frames_get_constraints, 2946cabdff1aSopenharmony_ci .frames_init = &opencl_frames_init, 2947cabdff1aSopenharmony_ci .frames_uninit = &opencl_frames_uninit, 2948cabdff1aSopenharmony_ci .frames_get_buffer = &opencl_get_buffer, 2949cabdff1aSopenharmony_ci 2950cabdff1aSopenharmony_ci .transfer_get_formats = &opencl_transfer_get_formats, 2951cabdff1aSopenharmony_ci .transfer_data_to = &opencl_transfer_data_to, 2952cabdff1aSopenharmony_ci .transfer_data_from = &opencl_transfer_data_from, 2953cabdff1aSopenharmony_ci 2954cabdff1aSopenharmony_ci .map_from = &opencl_map_from, 2955cabdff1aSopenharmony_ci .map_to = &opencl_map_to, 2956cabdff1aSopenharmony_ci .frames_derive_to = &opencl_frames_derive_to, 2957cabdff1aSopenharmony_ci 2958cabdff1aSopenharmony_ci .pix_fmts = (const enum AVPixelFormat[]) { 2959cabdff1aSopenharmony_ci AV_PIX_FMT_OPENCL, 2960cabdff1aSopenharmony_ci AV_PIX_FMT_NONE 2961cabdff1aSopenharmony_ci }, 2962cabdff1aSopenharmony_ci}; 2963