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