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