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