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                                  &region, &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