FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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/va_ext.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 
244 static int opencl_check_platform_extension(cl_platform_id platform_id,
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;
468  cl_uint *nb_platforms,
469  cl_platform_id **platforms,
470  void *context);
472  cl_platform_id platform_id,
473  const char *platform_name,
474  void *context);
476  cl_platform_id platform_id,
477  const char *platform_name,
478  cl_uint *nb_devices,
479  cl_device_id **devices,
480  void *context);
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  err = selector->enumerate_platforms(hwdev, &nb_platforms, &platforms,
504  selector->context);
505  if (err)
506  return err;
507 
508  found = 0;
509  for (p = 0; p < nb_platforms; p++) {
510  const char *platform_name;
511 
512  if (selector->platform_index >= 0 &&
513  selector->platform_index != p)
514  continue;
515 
516  av_freep(&platform_name_src);
517  platform_name_src = opencl_get_platform_string(platforms[p],
518  CL_PLATFORM_NAME);
519  if (platform_name_src)
520  platform_name = platform_name_src;
521  else
522  platform_name = "Unknown Platform";
523 
524  if (selector->filter_platform) {
525  err = selector->filter_platform(hwdev, platforms[p],
526  platform_name,
527  selector->context);
528  if (err < 0)
529  goto fail;
530  if (err > 0)
531  continue;
532  }
533 
534  err = opencl_enumerate_devices(hwdev, platforms[p], platform_name,
535  &nb_devices, &devices,
536  selector->context);
537  if (err < 0)
538  continue;
539 
540  for (d = 0; d < nb_devices; d++) {
541  const char *device_name;
542 
543  if (selector->device_index >= 0 &&
544  selector->device_index != d)
545  continue;
546 
547  av_freep(&device_name_src);
548  device_name_src = opencl_get_device_string(devices[d],
549  CL_DEVICE_NAME);
550  if (device_name_src)
551  device_name = device_name_src;
552  else
553  device_name = "Unknown Device";
554 
555  if (selector->filter_device) {
556  err = selector->filter_device(hwdev, devices[d],
557  device_name,
558  selector->context);
559  if (err < 0)
560  goto fail;
561  if (err > 0)
562  continue;
563  }
564 
565  av_log(hwdev, AV_LOG_VERBOSE, "%d.%d: %s / %s\n", p, d,
566  platform_name, device_name);
567 
568  ++found;
569  platform_id = platforms[p];
570  hwctx->device_id = devices[d];
571  }
572 
573  av_freep(&devices);
574  }
575 
576  if (found == 0) {
577  av_log(hwdev, AV_LOG_ERROR, "No matching devices found.\n");
578  err = AVERROR(ENODEV);
579  goto fail;
580  }
581  if (found > 1) {
582  av_log(hwdev, AV_LOG_ERROR, "More than one matching device found.\n");
583  err = AVERROR(ENODEV);
584  goto fail;
585  }
586 
587  if (!props) {
588  props = default_props;
589  default_props[0] = CL_CONTEXT_PLATFORM;
590  default_props[1] = (intptr_t)platform_id;
591  default_props[2] = 0;
592  } else {
593  if (props[0] == CL_CONTEXT_PLATFORM && props[1] == 0)
594  props[1] = (intptr_t)platform_id;
595  }
596 
597  hwctx->context = clCreateContext(props, 1, &hwctx->device_id,
598  &opencl_error_callback, hwdev, &cle);
599  if (!hwctx->context) {
600  av_log(hwdev, AV_LOG_ERROR, "Failed to create OpenCL context: "
601  "%d.\n", cle);
602  err = AVERROR(ENODEV);
603  goto fail;
604  }
605 
606  hwdev->free = &opencl_device_free;
607 
608  err = 0;
609 fail:
610  av_freep(&platform_name_src);
611  av_freep(&device_name_src);
612  av_freep(&platforms);
613  av_freep(&devices);
614  return err;
615 }
616 
617 static int opencl_device_create(AVHWDeviceContext *hwdev, const char *device,
618  AVDictionary *opts, int flags)
619 {
620  OpenCLDeviceSelector selector = {
621  .context = opts,
622  .enumerate_platforms = &opencl_enumerate_platforms,
623  .filter_platform = &opencl_filter_platform,
624  .enumerate_devices = &opencl_enumerate_devices,
625  .filter_device = &opencl_filter_device,
626  };
627 
628  if (device && device[0]) {
629  // Match one or both indices for platform and device.
630  int d = -1, p = -1, ret;
631  if (device[0] == '.')
632  ret = sscanf(device, ".%d", &d);
633  else
634  ret = sscanf(device, "%d.%d", &p, &d);
635  if (ret < 1) {
636  av_log(hwdev, AV_LOG_ERROR, "Invalid OpenCL platform/device "
637  "index specification \"%s\".\n", device);
638  return AVERROR(EINVAL);
639  }
640  selector.platform_index = p;
641  selector.device_index = d;
642  } else {
643  selector.platform_index = -1;
644  selector.device_index = -1;
645  }
646 
647  return opencl_device_create_internal(hwdev, &selector, NULL);
648 }
649 
651 {
652  AVOpenCLDeviceContext *hwctx = hwdev->hwctx;
653  OpenCLDeviceContext *priv = hwdev->internal->priv;
654  cl_int cle;
655 
656  if (hwctx->command_queue) {
657  cle = clRetainCommandQueue(hwctx->command_queue);
658  if (cle != CL_SUCCESS) {
659  av_log(hwdev, AV_LOG_ERROR, "Failed to retain external "
660  "command queue: %d.\n", cle);
661  return AVERROR(EIO);
662  }
663  priv->command_queue = hwctx->command_queue;
664  } else {
665  priv->command_queue = clCreateCommandQueue(hwctx->context,
666  hwctx->device_id,
667  0, &cle);
668  if (!priv->command_queue) {
669  av_log(hwdev, AV_LOG_ERROR, "Failed to create internal "
670  "command queue: %d.\n", cle);
671  return AVERROR(EIO);
672  }
673  }
674 
675  cle = clGetDeviceInfo(hwctx->device_id, CL_DEVICE_PLATFORM,
676  sizeof(priv->platform_id), &priv->platform_id,
677  NULL);
678  if (cle != CL_SUCCESS) {
679  av_log(hwdev, AV_LOG_ERROR, "Failed to determine the OpenCL "
680  "platform containing the device.\n");
681  return AVERROR(EIO);
682  }
683 
684 #define CL_FUNC(name, desc) do { \
685  if (fail) \
686  break; \
687  priv->name = clGetExtensionFunctionAddressForPlatform( \
688  priv->platform_id, #name); \
689  if (!priv->name) { \
690  av_log(hwdev, AV_LOG_VERBOSE, \
691  desc " function not found (%s).\n", #name); \
692  fail = 1; \
693  } else { \
694  av_log(hwdev, AV_LOG_VERBOSE, \
695  desc " function found (%s).\n", #name); \
696  } \
697  } while (0)
698 
699 #if HAVE_OPENCL_DRM_BEIGNET
700  {
701  int fail = 0;
702 
703  CL_FUNC(clCreateImageFromFdINTEL,
704  "Beignet DRM to OpenCL image mapping");
705 
706  if (fail) {
707  av_log(hwdev, AV_LOG_WARNING, "Beignet DRM to OpenCL "
708  "mapping not usable.\n");
709  priv->beignet_drm_mapping_usable = 0;
710  } else {
711  priv->beignet_drm_mapping_usable = 1;
712  }
713  }
714 #endif
715 
716 #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
717  {
718  size_t props_size;
719  cl_context_properties *props = NULL;
720  VADisplay va_display;
721  const char *va_ext = "cl_intel_va_api_media_sharing";
722  int i, fail = 0;
723 
724  if (!opencl_check_extension(hwdev, va_ext)) {
725  av_log(hwdev, AV_LOG_VERBOSE, "The %s extension is "
726  "required for QSV to OpenCL mapping.\n", va_ext);
727  goto no_qsv;
728  }
729 
730  cle = clGetContextInfo(hwctx->context, CL_CONTEXT_PROPERTIES,
731  0, NULL, &props_size);
732  if (cle != CL_SUCCESS) {
733  av_log(hwdev, AV_LOG_VERBOSE, "Failed to get context "
734  "properties: %d.\n", cle);
735  goto no_qsv;
736  }
737  if (props_size == 0) {
738  av_log(hwdev, AV_LOG_VERBOSE, "Media sharing must be "
739  "enabled on context creation to use QSV to "
740  "OpenCL mapping.\n");
741  goto no_qsv;
742  }
743 
744  props = av_malloc(props_size);
745  if (!props)
746  return AVERROR(ENOMEM);
747 
748  cle = clGetContextInfo(hwctx->context, CL_CONTEXT_PROPERTIES,
749  props_size, props, NULL);
750  if (cle != CL_SUCCESS) {
751  av_log(hwdev, AV_LOG_VERBOSE, "Failed to get context "
752  "properties: %d.\n", cle);
753  goto no_qsv;
754  }
755 
756  va_display = NULL;
757  for (i = 0; i < (props_size / sizeof(*props) - 1); i++) {
758  if (props[i] == CL_CONTEXT_VA_API_DISPLAY_INTEL) {
759  va_display = (VADisplay)(intptr_t)props[i+1];
760  break;
761  }
762  }
763  if (!va_display) {
764  av_log(hwdev, AV_LOG_VERBOSE, "Media sharing must be "
765  "enabled on context creation to use QSV to "
766  "OpenCL mapping.\n");
767  goto no_qsv;
768  }
769  if (!vaDisplayIsValid(va_display)) {
770  av_log(hwdev, AV_LOG_VERBOSE, "A valid VADisplay is "
771  "required on context creation to use QSV to "
772  "OpenCL mapping.\n");
773  goto no_qsv;
774  }
775 
776  CL_FUNC(clCreateFromVA_APIMediaSurfaceINTEL,
777  "Intel QSV to OpenCL mapping");
778  CL_FUNC(clEnqueueAcquireVA_APIMediaSurfacesINTEL,
779  "Intel QSV in OpenCL acquire");
780  CL_FUNC(clEnqueueReleaseVA_APIMediaSurfacesINTEL,
781  "Intel QSV in OpenCL release");
782 
783  if (fail) {
784  no_qsv:
785  av_log(hwdev, AV_LOG_WARNING, "QSV to OpenCL mapping "
786  "not usable.\n");
787  priv->qsv_mapping_usable = 0;
788  } else {
789  priv->qsv_mapping_usable = 1;
790  }
791  av_free(props);
792  }
793 #endif
794 
795 #if HAVE_OPENCL_DXVA2
796  {
797  int fail = 0;
798 
799  CL_FUNC(clCreateFromDX9MediaSurfaceKHR,
800  "DXVA2 to OpenCL mapping");
801  CL_FUNC(clEnqueueAcquireDX9MediaSurfacesKHR,
802  "DXVA2 in OpenCL acquire");
803  CL_FUNC(clEnqueueReleaseDX9MediaSurfacesKHR,
804  "DXVA2 in OpenCL release");
805 
806  if (fail) {
807  av_log(hwdev, AV_LOG_WARNING, "DXVA2 to OpenCL mapping "
808  "not usable.\n");
809  priv->dxva2_mapping_usable = 0;
810  } else {
811  priv->dx9_media_adapter_type = CL_ADAPTER_D3D9EX_KHR;
812  priv->dxva2_mapping_usable = 1;
813  }
814  }
815 #endif
816 
817 #if HAVE_OPENCL_D3D11
818  {
819  const char *d3d11_ext = "cl_khr_d3d11_sharing";
820  const char *nv12_ext = "cl_intel_d3d11_nv12_media_sharing";
821  int fail = 0;
822 
823  if (!opencl_check_extension(hwdev, d3d11_ext)) {
824  av_log(hwdev, AV_LOG_VERBOSE, "The %s extension is "
825  "required for D3D11 to OpenCL mapping.\n", d3d11_ext);
826  fail = 1;
827  } else if (!opencl_check_extension(hwdev, nv12_ext)) {
828  av_log(hwdev, AV_LOG_VERBOSE, "The %s extension may be "
829  "required for D3D11 to OpenCL mapping.\n", nv12_ext);
830  // Not fatal.
831  }
832 
833  CL_FUNC(clCreateFromD3D11Texture2DKHR,
834  "D3D11 to OpenCL mapping");
835  CL_FUNC(clEnqueueAcquireD3D11ObjectsKHR,
836  "D3D11 in OpenCL acquire");
837  CL_FUNC(clEnqueueReleaseD3D11ObjectsKHR,
838  "D3D11 in OpenCL release");
839 
840  if (fail) {
841  av_log(hwdev, AV_LOG_WARNING, "D3D11 to OpenCL mapping "
842  "not usable.\n");
843  priv->d3d11_mapping_usable = 0;
844  } else {
845  priv->d3d11_mapping_usable = 1;
846  }
847  }
848 #endif
849 
850 #if HAVE_OPENCL_DRM_ARM
851  {
852  const char *drm_arm_ext = "cl_arm_import_memory";
853  const char *image_ext = "cl_khr_image2d_from_buffer";
854  int fail = 0;
855 
856  if (!opencl_check_extension(hwdev, drm_arm_ext)) {
857  av_log(hwdev, AV_LOG_VERBOSE, "The %s extension is "
858  "required for DRM to OpenCL mapping on ARM.\n",
859  drm_arm_ext);
860  fail = 1;
861  }
862  if (!opencl_check_extension(hwdev, image_ext)) {
863  av_log(hwdev, AV_LOG_VERBOSE, "The %s extension is "
864  "required for DRM to OpenCL mapping on ARM.\n",
865  image_ext);
866  fail = 1;
867  }
868 
869  // clImportMemoryARM() is linked statically.
870 
871  if (fail) {
872  av_log(hwdev, AV_LOG_WARNING, "DRM to OpenCL mapping on ARM "
873  "not usable.\n");
874  priv->drm_arm_mapping_usable = 0;
875  } else {
876  priv->drm_arm_mapping_usable = 1;
877  }
878  }
879 #endif
880 
881 #undef CL_FUNC
882 
883  return 0;
884 }
885 
887 {
888  OpenCLDeviceContext *priv = hwdev->internal->priv;
889  cl_int cle;
890 
891  if (priv->command_queue) {
892  cle = clReleaseCommandQueue(priv->command_queue);
893  if (cle != CL_SUCCESS) {
894  av_log(hwdev, AV_LOG_ERROR, "Failed to release internal "
895  "command queue reference: %d.\n", cle);
896  }
897  priv->command_queue = NULL;
898  }
899 }
900 
901 #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
902 static int opencl_filter_intel_media_vaapi_platform(AVHWDeviceContext *hwdev,
903  cl_platform_id platform_id,
904  const char *platform_name,
905  void *context)
906 {
907  // This doesn't exist as a platform extension, so just test whether
908  // the function we will use for device enumeration exists.
909 
910  if (!clGetExtensionFunctionAddressForPlatform(platform_id,
911  "clGetDeviceIDsFromVA_APIMediaAdapterINTEL")) {
912  av_log(hwdev, AV_LOG_DEBUG, "Platform %s does not export the "
913  "VAAPI device enumeration function.\n", platform_name);
914  return 1;
915  } else {
916  return 0;
917  }
918 }
919 
920 static int opencl_enumerate_intel_media_vaapi_devices(AVHWDeviceContext *hwdev,
921  cl_platform_id platform_id,
922  const char *platform_name,
923  cl_uint *nb_devices,
924  cl_device_id **devices,
925  void *context)
926 {
927  VADisplay va_display = context;
928  clGetDeviceIDsFromVA_APIMediaAdapterINTEL_fn
929  clGetDeviceIDsFromVA_APIMediaAdapterINTEL;
930  cl_int cle;
931 
932  clGetDeviceIDsFromVA_APIMediaAdapterINTEL =
933  clGetExtensionFunctionAddressForPlatform(platform_id,
934  "clGetDeviceIDsFromVA_APIMediaAdapterINTEL");
935  if (!clGetDeviceIDsFromVA_APIMediaAdapterINTEL) {
936  av_log(hwdev, AV_LOG_ERROR, "Failed to get address of "
937  "clGetDeviceIDsFromVA_APIMediaAdapterINTEL().\n");
938  return AVERROR_UNKNOWN;
939  }
940 
941  cle = clGetDeviceIDsFromVA_APIMediaAdapterINTEL(
942  platform_id, CL_VA_API_DISPLAY_INTEL, va_display,
943  CL_PREFERRED_DEVICES_FOR_VA_API_INTEL, 0, NULL, nb_devices);
944  if (cle == CL_DEVICE_NOT_FOUND) {
945  av_log(hwdev, AV_LOG_DEBUG, "No VAAPI-supporting devices found "
946  "on platform \"%s\".\n", platform_name);
947  *nb_devices = 0;
948  return 0;
949  } else if (cle != CL_SUCCESS) {
950  av_log(hwdev, AV_LOG_ERROR, "Failed to get number of devices "
951  "on platform \"%s\": %d.\n", platform_name, cle);
952  return AVERROR_UNKNOWN;
953  }
954 
955  *devices = av_malloc_array(*nb_devices, sizeof(**devices));
956  if (!*devices)
957  return AVERROR(ENOMEM);
958 
959  cle = clGetDeviceIDsFromVA_APIMediaAdapterINTEL(
960  platform_id, CL_VA_API_DISPLAY_INTEL, va_display,
961  CL_PREFERRED_DEVICES_FOR_VA_API_INTEL, *nb_devices, *devices, NULL);
962  if (cle != CL_SUCCESS) {
963  av_log(hwdev, AV_LOG_ERROR, "Failed to get list of VAAPI-supporting "
964  "devices on platform \"%s\": %d.\n", platform_name, cle);
965  av_freep(devices);
966  return AVERROR_UNKNOWN;
967  }
968 
969  return 0;
970 }
971 
972 static int opencl_filter_intel_media_vaapi_device(AVHWDeviceContext *hwdev,
973  cl_device_id device_id,
974  const char *device_name,
975  void *context)
976 {
977  const char *va_ext = "cl_intel_va_api_media_sharing";
978 
979  if (opencl_check_device_extension(device_id, va_ext)) {
980  return 0;
981  } else {
982  av_log(hwdev, AV_LOG_DEBUG, "Device %s does not support the "
983  "%s extension.\n", device_name, va_ext);
984  return 1;
985  }
986 }
987 #endif
988 
989 #if HAVE_OPENCL_DXVA2
990 static int opencl_filter_dxva2_platform(AVHWDeviceContext *hwdev,
991  cl_platform_id platform_id,
992  const char *platform_name,
993  void *context)
994 {
995  const char *dx9_ext = "cl_khr_dx9_media_sharing";
996 
997  if (opencl_check_platform_extension(platform_id, dx9_ext)) {
998  return 0;
999  } else {
1000  av_log(hwdev, AV_LOG_DEBUG, "Platform %s does not support the "
1001  "%s extension.\n", platform_name, dx9_ext);
1002  return 1;
1003  }
1004 }
1005 
1006 static int opencl_enumerate_dxva2_devices(AVHWDeviceContext *hwdev,
1007  cl_platform_id platform_id,
1008  const char *platform_name,
1009  cl_uint *nb_devices,
1010  cl_device_id **devices,
1011  void *context)
1012 {
1013  IDirect3DDevice9 *device = context;
1014  clGetDeviceIDsFromDX9MediaAdapterKHR_fn
1015  clGetDeviceIDsFromDX9MediaAdapterKHR;
1016  cl_dx9_media_adapter_type_khr media_adapter_type = CL_ADAPTER_D3D9EX_KHR;
1017  cl_int cle;
1018 
1019  clGetDeviceIDsFromDX9MediaAdapterKHR =
1020  clGetExtensionFunctionAddressForPlatform(platform_id,
1021  "clGetDeviceIDsFromDX9MediaAdapterKHR");
1022  if (!clGetDeviceIDsFromDX9MediaAdapterKHR) {
1023  av_log(hwdev, AV_LOG_ERROR, "Failed to get address of "
1024  "clGetDeviceIDsFromDX9MediaAdapterKHR().\n");
1025  return AVERROR_UNKNOWN;
1026  }
1027 
1028  cle = clGetDeviceIDsFromDX9MediaAdapterKHR(
1029  platform_id, 1, &media_adapter_type, (void**)&device,
1030  CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR,
1031  0, NULL, nb_devices);
1032  if (cle == CL_DEVICE_NOT_FOUND) {
1033  av_log(hwdev, AV_LOG_DEBUG, "No DXVA2-supporting devices found "
1034  "on platform \"%s\".\n", platform_name);
1035  *nb_devices = 0;
1036  return 0;
1037  } else if (cle != CL_SUCCESS) {
1038  av_log(hwdev, AV_LOG_ERROR, "Failed to get number of devices "
1039  "on platform \"%s\": %d.\n", platform_name, cle);
1040  return AVERROR_UNKNOWN;
1041  }
1042 
1043  *devices = av_malloc_array(*nb_devices, sizeof(**devices));
1044  if (!*devices)
1045  return AVERROR(ENOMEM);
1046 
1047  cle = clGetDeviceIDsFromDX9MediaAdapterKHR(
1048  platform_id, 1, &media_adapter_type, (void**)&device,
1049  CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR,
1050  *nb_devices, *devices, NULL);
1051  if (cle != CL_SUCCESS) {
1052  av_log(hwdev, AV_LOG_ERROR, "Failed to get list of DXVA2-supporting "
1053  "devices on platform \"%s\": %d.\n", platform_name, cle);
1054  av_freep(devices);
1055  return AVERROR_UNKNOWN;
1056  }
1057 
1058  return 0;
1059 }
1060 #endif
1061 
1062 #if HAVE_OPENCL_D3D11
1063 static int opencl_filter_d3d11_platform(AVHWDeviceContext *hwdev,
1064  cl_platform_id platform_id,
1065  const char *platform_name,
1066  void *context)
1067 {
1068  const char *d3d11_ext = "cl_khr_d3d11_sharing";
1069 
1070  if (opencl_check_platform_extension(platform_id, d3d11_ext)) {
1071  return 0;
1072  } else {
1073  av_log(hwdev, AV_LOG_DEBUG, "Platform %s does not support the "
1074  "%s extension.\n", platform_name, d3d11_ext);
1075  return 1;
1076  }
1077 }
1078 
1079 static int opencl_enumerate_d3d11_devices(AVHWDeviceContext *hwdev,
1080  cl_platform_id platform_id,
1081  const char *platform_name,
1082  cl_uint *nb_devices,
1083  cl_device_id **devices,
1084  void *context)
1085 {
1086  ID3D11Device *device = context;
1087  clGetDeviceIDsFromD3D11KHR_fn clGetDeviceIDsFromD3D11KHR;
1088  cl_int cle;
1089 
1090  clGetDeviceIDsFromD3D11KHR =
1091  clGetExtensionFunctionAddressForPlatform(platform_id,
1092  "clGetDeviceIDsFromD3D11KHR");
1093  if (!clGetDeviceIDsFromD3D11KHR) {
1094  av_log(hwdev, AV_LOG_ERROR, "Failed to get address of "
1095  "clGetDeviceIDsFromD3D11KHR().\n");
1096  return AVERROR_UNKNOWN;
1097  }
1098 
1099  cle = clGetDeviceIDsFromD3D11KHR(platform_id,
1100  CL_D3D11_DEVICE_KHR, device,
1101  CL_PREFERRED_DEVICES_FOR_D3D11_KHR,
1102  0, NULL, nb_devices);
1103  if (cle == CL_DEVICE_NOT_FOUND) {
1104  av_log(hwdev, AV_LOG_DEBUG, "No D3D11-supporting devices found "
1105  "on platform \"%s\".\n", platform_name);
1106  *nb_devices = 0;
1107  return 0;
1108  } else if (cle != CL_SUCCESS) {
1109  av_log(hwdev, AV_LOG_ERROR, "Failed to get number of devices "
1110  "on platform \"%s\": %d.\n", platform_name, cle);
1111  return AVERROR_UNKNOWN;
1112  }
1113 
1114  *devices = av_malloc_array(*nb_devices, sizeof(**devices));
1115  if (!*devices)
1116  return AVERROR(ENOMEM);
1117 
1118  cle = clGetDeviceIDsFromD3D11KHR(platform_id,
1119  CL_D3D11_DEVICE_KHR, device,
1120  CL_PREFERRED_DEVICES_FOR_D3D11_KHR,
1121  *nb_devices, *devices, NULL);
1122  if (cle != CL_SUCCESS) {
1123  av_log(hwdev, AV_LOG_ERROR, "Failed to get list of D3D11-supporting "
1124  "devices on platform \"%s\": %d.\n", platform_name, cle);
1125  av_freep(devices);
1126  return AVERROR_UNKNOWN;
1127  }
1128 
1129  return 0;
1130 }
1131 #endif
1132 
1133 #if HAVE_OPENCL_DXVA2 || HAVE_OPENCL_D3D11
1134 static int opencl_filter_gpu_device(AVHWDeviceContext *hwdev,
1135  cl_device_id device_id,
1136  const char *device_name,
1137  void *context)
1138 {
1139  cl_device_type device_type;
1140  cl_int cle;
1141 
1142  cle = clGetDeviceInfo(device_id, CL_DEVICE_TYPE,
1143  sizeof(device_type), &device_type, NULL);
1144  if (cle != CL_SUCCESS) {
1145  av_log(hwdev, AV_LOG_ERROR, "Failed to query device type "
1146  "of device \"%s\".\n", device_name);
1147  return AVERROR_UNKNOWN;
1148  }
1149  if (!(device_type & CL_DEVICE_TYPE_GPU)) {
1150  av_log(hwdev, AV_LOG_DEBUG, "Device %s skipped (not GPU).\n",
1151  device_name);
1152  return 1;
1153  }
1154 
1155  return 0;
1156 }
1157 #endif
1158 
1159 #if HAVE_OPENCL_DRM_ARM
1160 static int opencl_filter_drm_arm_platform(AVHWDeviceContext *hwdev,
1161  cl_platform_id platform_id,
1162  const char *platform_name,
1163  void *context)
1164 {
1165  const char *drm_arm_ext = "cl_arm_import_memory";
1166 
1167  if (opencl_check_platform_extension(platform_id, drm_arm_ext)) {
1168  return 0;
1169  } else {
1170  av_log(hwdev, AV_LOG_DEBUG, "Platform %s does not support the "
1171  "%s extension.\n", platform_name, drm_arm_ext);
1172  return 1;
1173  }
1174 }
1175 
1176 static int opencl_filter_drm_arm_device(AVHWDeviceContext *hwdev,
1177  cl_device_id device_id,
1178  const char *device_name,
1179  void *context)
1180 {
1181  const char *drm_arm_ext = "cl_arm_import_memory";
1182 
1183  if (opencl_check_device_extension(device_id, drm_arm_ext)) {
1184  return 0;
1185  } else {
1186  av_log(hwdev, AV_LOG_DEBUG, "Device %s does not support the "
1187  "%s extension.\n", device_name, drm_arm_ext);
1188  return 1;
1189  }
1190 }
1191 #endif
1192 
1194  AVHWDeviceContext *src_ctx,
1195  int flags)
1196 {
1197  int err;
1198  switch (src_ctx->type) {
1199 
1200 #if HAVE_OPENCL_DRM_BEIGNET
1201  case AV_HWDEVICE_TYPE_DRM:
1203  {
1204  // Surface mapping works via DRM PRIME fds with no special
1205  // initialisation required in advance. This just finds the
1206  // Beignet ICD by name.
1207  AVDictionary *opts = NULL;
1208 
1209  err = av_dict_set(&opts, "platform_vendor", "Intel", 0);
1210  if (err >= 0)
1211  err = av_dict_set(&opts, "platform_version", "beignet", 0);
1212  if (err >= 0) {
1213  OpenCLDeviceSelector selector = {
1214  .platform_index = -1,
1215  .device_index = 0,
1216  .context = opts,
1217  .enumerate_platforms = &opencl_enumerate_platforms,
1218  .filter_platform = &opencl_filter_platform,
1219  .enumerate_devices = &opencl_enumerate_devices,
1220  .filter_device = NULL,
1221  };
1222  err = opencl_device_create_internal(hwdev, &selector, NULL);
1223  }
1224  av_dict_free(&opts);
1225  }
1226  break;
1227 #endif
1228 
1229 #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
1230  // The generic code automatically attempts to derive from all
1231  // ancestors of the given device, so we can ignore QSV devices here
1232  // and just consider the inner VAAPI device it was derived from.
1234  {
1235  AVVAAPIDeviceContext *src_hwctx = src_ctx->hwctx;
1236  cl_context_properties props[7] = {
1237  CL_CONTEXT_PLATFORM,
1238  0,
1239  CL_CONTEXT_VA_API_DISPLAY_INTEL,
1240  (intptr_t)src_hwctx->display,
1241  CL_CONTEXT_INTEROP_USER_SYNC,
1242  CL_FALSE,
1243  0,
1244  };
1245  OpenCLDeviceSelector selector = {
1246  .platform_index = -1,
1247  .device_index = -1,
1248  .context = src_hwctx->display,
1249  .enumerate_platforms = &opencl_enumerate_platforms,
1250  .filter_platform = &opencl_filter_intel_media_vaapi_platform,
1251  .enumerate_devices = &opencl_enumerate_intel_media_vaapi_devices,
1252  .filter_device = &opencl_filter_intel_media_vaapi_device,
1253  };
1254 
1255  err = opencl_device_create_internal(hwdev, &selector, props);
1256  }
1257  break;
1258 #endif
1259 
1260 #if HAVE_OPENCL_DXVA2
1262  {
1263  AVDXVA2DeviceContext *src_hwctx = src_ctx->hwctx;
1264  IDirect3DDevice9 *device;
1265  HANDLE device_handle;
1266  HRESULT hr;
1267 
1268  hr = IDirect3DDeviceManager9_OpenDeviceHandle(src_hwctx->devmgr,
1269  &device_handle);
1270  if (FAILED(hr)) {
1271  av_log(hwdev, AV_LOG_ERROR, "Failed to open device handle "
1272  "for Direct3D9 device: %lx.\n", (unsigned long)hr);
1273  err = AVERROR_UNKNOWN;
1274  break;
1275  }
1276 
1277  hr = IDirect3DDeviceManager9_LockDevice(src_hwctx->devmgr,
1278  device_handle,
1279  &device, FALSE);
1280  if (SUCCEEDED(hr)) {
1281  cl_context_properties props[5] = {
1282  CL_CONTEXT_PLATFORM,
1283  0,
1284  CL_CONTEXT_ADAPTER_D3D9EX_KHR,
1285  (intptr_t)device,
1286  0,
1287  };
1288  OpenCLDeviceSelector selector = {
1289  .platform_index = -1,
1290  .device_index = -1,
1291  .context = device,
1292  .enumerate_platforms = &opencl_enumerate_platforms,
1293  .filter_platform = &opencl_filter_dxva2_platform,
1294  .enumerate_devices = &opencl_enumerate_dxva2_devices,
1295  .filter_device = &opencl_filter_gpu_device,
1296  };
1297 
1298  err = opencl_device_create_internal(hwdev, &selector, props);
1299 
1300  IDirect3DDeviceManager9_UnlockDevice(src_hwctx->devmgr,
1301  device_handle, FALSE);
1302  } else {
1303  av_log(hwdev, AV_LOG_ERROR, "Failed to lock device handle "
1304  "for Direct3D9 device: %lx.\n", (unsigned long)hr);
1305  err = AVERROR_UNKNOWN;
1306  }
1307 
1308  IDirect3DDeviceManager9_CloseDeviceHandle(src_hwctx->devmgr,
1309  device_handle);
1310  }
1311  break;
1312 #endif
1313 
1314 #if HAVE_OPENCL_D3D11
1316  {
1317  AVD3D11VADeviceContext *src_hwctx = src_ctx->hwctx;
1318  cl_context_properties props[5] = {
1319  CL_CONTEXT_PLATFORM,
1320  0,
1321  CL_CONTEXT_D3D11_DEVICE_KHR,
1322  (intptr_t)src_hwctx->device,
1323  0,
1324  };
1325  OpenCLDeviceSelector selector = {
1326  .platform_index = -1,
1327  .device_index = -1,
1328  .context = src_hwctx->device,
1329  .enumerate_platforms = &opencl_enumerate_platforms,
1330  .filter_platform = &opencl_filter_d3d11_platform,
1331  .enumerate_devices = &opencl_enumerate_d3d11_devices,
1332  .filter_device = &opencl_filter_gpu_device,
1333  };
1334 
1335  err = opencl_device_create_internal(hwdev, &selector, props);
1336  }
1337  break;
1338 #endif
1339 
1340 #if HAVE_OPENCL_DRM_ARM
1341  case AV_HWDEVICE_TYPE_DRM:
1342  {
1343  OpenCLDeviceSelector selector = {
1344  .platform_index = -1,
1345  .device_index = -1,
1346  .context = NULL,
1347  .enumerate_platforms = &opencl_enumerate_platforms,
1348  .filter_platform = &opencl_filter_drm_arm_platform,
1349  .enumerate_devices = &opencl_enumerate_devices,
1350  .filter_device = &opencl_filter_drm_arm_device,
1351  };
1352 
1353  err = opencl_device_create_internal(hwdev, &selector, NULL);
1354  }
1355  break;
1356 #endif
1357 
1358  default:
1359  err = AVERROR(ENOSYS);
1360  break;
1361  }
1362 
1363  return err;
1364 }
1365 
1367  int plane, int width, int height,
1368  cl_image_format *image_format,
1369  cl_image_desc *image_desc)
1370 {
1371  const AVPixFmtDescriptor *desc;
1372  const AVComponentDescriptor *comp;
1373  int channels = 0, order = 0, depth = 0, step = 0;
1374  int wsub, hsub, alpha;
1375  int c;
1376 
1377  if (plane >= AV_NUM_DATA_POINTERS)
1378  return AVERROR(ENOENT);
1379 
1380  desc = av_pix_fmt_desc_get(pixfmt);
1381 
1382  // Only normal images are allowed.
1383  if (desc->flags & (AV_PIX_FMT_FLAG_BITSTREAM |
1386  return AVERROR(EINVAL);
1387 
1388  wsub = 1 << desc->log2_chroma_w;
1389  hsub = 1 << desc->log2_chroma_h;
1390  // Subsampled components must be exact.
1391  if (width & wsub - 1 || height & hsub - 1)
1392  return AVERROR(EINVAL);
1393 
1394  for (c = 0; c < desc->nb_components; c++) {
1395  comp = &desc->comp[c];
1396  if (comp->plane != plane)
1397  continue;
1398  // The step size must be a power of two.
1399  if (comp->step != 1 && comp->step != 2 &&
1400  comp->step != 4 && comp->step != 8)
1401  return AVERROR(EINVAL);
1402  // The bits in each component must be packed in the
1403  // most-significant-bits of the relevant bytes.
1404  if (comp->shift + comp->depth != 8 &&
1405  comp->shift + comp->depth != 16)
1406  return AVERROR(EINVAL);
1407  // The depth must not vary between components.
1408  if (depth && comp->depth != depth)
1409  return AVERROR(EINVAL);
1410  // If a single data element crosses multiple bytes then
1411  // it must match the native endianness.
1412  if (comp->depth > 8 &&
1413  HAVE_BIGENDIAN == !(desc->flags & AV_PIX_FMT_FLAG_BE))
1414  return AVERROR(EINVAL);
1415  // A single data element must not contain multiple samples
1416  // from the same component.
1417  if (step && comp->step != step)
1418  return AVERROR(EINVAL);
1419  order = order * 10 + c + 1;
1420  depth = comp->depth;
1421  step = comp->step;
1422  alpha = (desc->flags & AV_PIX_FMT_FLAG_ALPHA &&
1423  c == desc->nb_components - 1);
1424  ++channels;
1425  }
1426  if (channels == 0)
1427  return AVERROR(ENOENT);
1428 
1429  memset(image_format, 0, sizeof(*image_format));
1430  memset(image_desc, 0, sizeof(*image_desc));
1431  image_desc->image_type = CL_MEM_OBJECT_IMAGE2D;
1432 
1433  if (plane == 0 || alpha) {
1434  image_desc->image_width = width;
1435  image_desc->image_height = height;
1436  image_desc->image_row_pitch = step * width;
1437  } else {
1438  image_desc->image_width = width / wsub;
1439  image_desc->image_height = height / hsub;
1440  image_desc->image_row_pitch = step * width / wsub;
1441  }
1442 
1443  if (depth <= 8) {
1444  image_format->image_channel_data_type = CL_UNORM_INT8;
1445  } else {
1446  if (depth <= 16)
1447  image_format->image_channel_data_type = CL_UNORM_INT16;
1448  else
1449  return AVERROR(EINVAL);
1450  }
1451 
1452 #define CHANNEL_ORDER(order, type) \
1453  case order: image_format->image_channel_order = type; break;
1454  switch (order) {
1455  CHANNEL_ORDER(1, CL_R);
1456  CHANNEL_ORDER(2, CL_R);
1457  CHANNEL_ORDER(3, CL_R);
1458  CHANNEL_ORDER(4, CL_R);
1459  CHANNEL_ORDER(12, CL_RG);
1460  CHANNEL_ORDER(23, CL_RG);
1461  CHANNEL_ORDER(1234, CL_RGBA);
1462  CHANNEL_ORDER(3214, CL_BGRA);
1463  CHANNEL_ORDER(4123, CL_ARGB);
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  cle = clReleaseCommandQueue(priv->command_queue);
1730  if (cle != CL_SUCCESS) {
1731  av_log(hwfc, AV_LOG_ERROR, "Failed to release frame "
1732  "command queue: %d.\n", cle);
1733  }
1734 }
1735 
1737 {
1739  int p;
1740 
1741  frame->buf[0] = av_buffer_pool_get(hwfc->pool);
1742  if (!frame->buf[0])
1743  return AVERROR(ENOMEM);
1744 
1745  desc = (AVOpenCLFrameDescriptor*)frame->buf[0]->data;
1746 
1747  for (p = 0; p < desc->nb_planes; p++)
1748  frame->data[p] = (uint8_t*)desc->planes[p];
1749 
1750  frame->format = AV_PIX_FMT_OPENCL;
1751  frame->width = hwfc->width;
1752  frame->height = hwfc->height;
1753 
1754  return 0;
1755 }
1756 
1758  enum AVHWFrameTransferDirection dir,
1759  enum AVPixelFormat **formats)
1760 {
1761  enum AVPixelFormat *fmts;
1762 
1763  fmts = av_malloc_array(2, sizeof(*fmts));
1764  if (!fmts)
1765  return AVERROR(ENOMEM);
1766 
1767  fmts[0] = hwfc->sw_format;
1768  fmts[1] = AV_PIX_FMT_NONE;
1769 
1770  *formats = fmts;
1771  return 0;
1772 }
1773 
1775  cl_event *events, int nb_events)
1776 {
1777  cl_int cle;
1778  int i;
1779 
1780  cle = clWaitForEvents(nb_events, events);
1781  if (cle != CL_SUCCESS) {
1782  av_log(hwfc, AV_LOG_ERROR, "Failed to wait for event "
1783  "completion: %d.\n", cle);
1784  return AVERROR(EIO);
1785  }
1786 
1787  for (i = 0; i < nb_events; i++) {
1788  cle = clReleaseEvent(events[i]);
1789  if (cle != CL_SUCCESS) {
1790  av_log(hwfc, AV_LOG_ERROR, "Failed to release "
1791  "event: %d.\n", cle);
1792  }
1793  }
1794 
1795  return 0;
1796 }
1797 
1799  AVFrame *dst, const AVFrame *src)
1800 {
1801  OpenCLFramesContext *priv = hwfc->internal->priv;
1802  cl_image_format image_format;
1803  cl_image_desc image_desc;
1804  cl_int cle;
1805  size_t origin[3] = { 0, 0, 0 };
1806  size_t region[3];
1807  cl_event events[AV_NUM_DATA_POINTERS];
1808  int err, p;
1809 
1810  if (dst->format != hwfc->sw_format)
1811  return AVERROR(EINVAL);
1812 
1813  for (p = 0;; p++) {
1814  err = opencl_get_plane_format(hwfc->sw_format, p,
1815  src->width, src->height,
1816  &image_format, &image_desc);
1817  if (err < 0) {
1818  if (err == AVERROR(ENOENT))
1819  err = 0;
1820  break;
1821  }
1822 
1823  if (!dst->data[p]) {
1824  av_log(hwfc, AV_LOG_ERROR, "Plane %d missing on "
1825  "destination frame for transfer.\n", p);
1826  err = AVERROR(EINVAL);
1827  break;
1828  }
1829 
1830  region[0] = image_desc.image_width;
1831  region[1] = image_desc.image_height;
1832  region[2] = 1;
1833 
1834  cle = clEnqueueReadImage(priv->command_queue,
1835  (cl_mem)src->data[p],
1836  CL_FALSE, origin, region,
1837  dst->linesize[p], 0,
1838  dst->data[p],
1839  0, NULL, &events[p]);
1840  if (cle != CL_SUCCESS) {
1841  av_log(hwfc, AV_LOG_ERROR, "Failed to enqueue read of "
1842  "OpenCL image plane %d: %d.\n", p, cle);
1843  err = AVERROR(EIO);
1844  break;
1845  }
1846  }
1847 
1848  opencl_wait_events(hwfc, events, p);
1849 
1850  return err;
1851 }
1852 
1854  AVFrame *dst, const AVFrame *src)
1855 {
1856  OpenCLFramesContext *priv = hwfc->internal->priv;
1857  cl_image_format image_format;
1858  cl_image_desc image_desc;
1859  cl_int cle;
1860  size_t origin[3] = { 0, 0, 0 };
1861  size_t region[3];
1862  cl_event events[AV_NUM_DATA_POINTERS];
1863  int err, p;
1864 
1865  if (src->format != hwfc->sw_format)
1866  return AVERROR(EINVAL);
1867 
1868  for (p = 0;; p++) {
1869  err = opencl_get_plane_format(hwfc->sw_format, p,
1870  src->width, src->height,
1871  &image_format, &image_desc);
1872  if (err < 0) {
1873  if (err == AVERROR(ENOENT))
1874  err = 0;
1875  break;
1876  }
1877 
1878  if (!src->data[p]) {
1879  av_log(hwfc, AV_LOG_ERROR, "Plane %d missing on "
1880  "source frame for transfer.\n", p);
1881  err = AVERROR(EINVAL);
1882  break;
1883  }
1884 
1885  region[0] = image_desc.image_width;
1886  region[1] = image_desc.image_height;
1887  region[2] = 1;
1888 
1889  cle = clEnqueueWriteImage(priv->command_queue,
1890  (cl_mem)dst->data[p],
1891  CL_FALSE, origin, region,
1892  src->linesize[p], 0,
1893  src->data[p],
1894  0, NULL, &events[p]);
1895  if (cle != CL_SUCCESS) {
1896  av_log(hwfc, AV_LOG_ERROR, "Failed to enqueue write of "
1897  "OpenCL image plane %d: %d.\n", p, cle);
1898  err = AVERROR(EIO);
1899  break;
1900  }
1901  }
1902 
1903  opencl_wait_events(hwfc, events, p);
1904 
1905  return err;
1906 }
1907 
1908 typedef struct OpenCLMapping {
1909  // The mapped addresses for each plane.
1910  // The destination frame is not available when we unmap, so these
1911  // need to be stored separately.
1913 } OpenCLMapping;
1914 
1916  HWMapDescriptor *hwmap)
1917 {
1918  OpenCLFramesContext *priv = hwfc->internal->priv;
1919  OpenCLMapping *map = hwmap->priv;
1920  cl_event events[AV_NUM_DATA_POINTERS];
1921  int p, e;
1922  cl_int cle;
1923 
1924  for (p = e = 0; p < FF_ARRAY_ELEMS(map->address); p++) {
1925  if (!map->address[p])
1926  break;
1927 
1928  cle = clEnqueueUnmapMemObject(priv->command_queue,
1929  (cl_mem)hwmap->source->data[p],
1930  map->address[p],
1931  0, NULL, &events[e]);
1932  if (cle != CL_SUCCESS) {
1933  av_log(hwfc, AV_LOG_ERROR, "Failed to unmap OpenCL "
1934  "image plane %d: %d.\n", p, cle);
1935  }
1936  ++e;
1937  }
1938 
1939  opencl_wait_events(hwfc, events, e);
1940 
1941  av_free(map);
1942 }
1943 
1945  const AVFrame *src, int flags)
1946 {
1947  OpenCLFramesContext *priv = hwfc->internal->priv;
1948  cl_map_flags map_flags;
1949  cl_image_format image_format;
1950  cl_image_desc image_desc;
1951  cl_int cle;
1952  OpenCLMapping *map;
1953  size_t origin[3] = { 0, 0, 0 };
1954  size_t region[3];
1955  size_t row_pitch;
1956  cl_event events[AV_NUM_DATA_POINTERS];
1957  int err, p;
1958 
1959  av_assert0(hwfc->sw_format == dst->format);
1960 
1961  if (flags & AV_HWFRAME_MAP_OVERWRITE &&
1962  !(flags & AV_HWFRAME_MAP_READ)) {
1963  // This is mutually exclusive with the read/write flags, so
1964  // there is no way to map with read here.
1965  map_flags = CL_MAP_WRITE_INVALIDATE_REGION;
1966  } else {
1967  map_flags = 0;
1968  if (flags & AV_HWFRAME_MAP_READ)
1969  map_flags |= CL_MAP_READ;
1970  if (flags & AV_HWFRAME_MAP_WRITE)
1971  map_flags |= CL_MAP_WRITE;
1972  }
1973 
1974  map = av_mallocz(sizeof(*map));
1975  if (!map)
1976  return AVERROR(ENOMEM);
1977 
1978  for (p = 0;; p++) {
1979  err = opencl_get_plane_format(hwfc->sw_format, p,
1980  src->width, src->height,
1981  &image_format, &image_desc);
1982  if (err == AVERROR(ENOENT))
1983  break;
1984  if (err < 0)
1985  goto fail;
1986 
1987  region[0] = image_desc.image_width;
1988  region[1] = image_desc.image_height;
1989  region[2] = 1;
1990 
1991  map->address[p] =
1992  clEnqueueMapImage(priv->command_queue,
1993  (cl_mem)src->data[p],
1994  CL_FALSE, map_flags, origin, region,
1995  &row_pitch, NULL, 0, NULL,
1996  &events[p], &cle);
1997  if (!map->address[p]) {
1998  av_log(hwfc, AV_LOG_ERROR, "Failed to map OpenCL "
1999  "image plane %d: %d.\n", p, cle);
2000  err = AVERROR(EIO);
2001  goto fail;
2002  }
2003 
2004  dst->data[p] = map->address[p];
2005 
2006  av_log(hwfc, AV_LOG_DEBUG, "Map plane %d (%p -> %p).\n",
2007  p, src->data[p], dst->data[p]);
2008  }
2009 
2010  err = opencl_wait_events(hwfc, events, p);
2011  if (err < 0)
2012  goto fail;
2013 
2014  err = ff_hwframe_map_create(src->hw_frames_ctx, dst, src,
2015  &opencl_unmap_frame, map);
2016  if (err < 0)
2017  goto fail;
2018 
2019  dst->width = src->width;
2020  dst->height = src->height;
2021 
2022  return 0;
2023 
2024 fail:
2025  for (p = 0; p < AV_NUM_DATA_POINTERS; p++) {
2026  if (!map->address[p])
2027  break;
2028  clEnqueueUnmapMemObject(priv->command_queue,
2029  (cl_mem)src->data[p],
2030  map->address[p],
2031  0, NULL, &events[p]);
2032  }
2033  if (p > 0)
2034  opencl_wait_events(hwfc, events, p);
2035  av_freep(&map);
2036  return err;
2037 }
2038 
2039 #if HAVE_OPENCL_DRM_BEIGNET
2040 
2041 typedef struct DRMBeignetToOpenCLMapping {
2042  AVFrame *drm_frame;
2043  AVDRMFrameDescriptor *drm_desc;
2044 
2046 } DRMBeignetToOpenCLMapping;
2047 
2048 static void opencl_unmap_from_drm_beignet(AVHWFramesContext *dst_fc,
2049  HWMapDescriptor *hwmap)
2050 {
2051  DRMBeignetToOpenCLMapping *mapping = hwmap->priv;
2052  cl_int cle;
2053  int i;
2054 
2055  for (i = 0; i < mapping->frame.nb_planes; i++) {
2056  cle = clReleaseMemObject(mapping->frame.planes[i]);
2057  if (cle != CL_SUCCESS) {
2058  av_log(dst_fc, AV_LOG_ERROR, "Failed to release CL image "
2059  "of plane %d of DRM frame: %d.\n", i, cle);
2060  }
2061  }
2062 
2063  av_free(mapping);
2064 }
2065 
2066 static int opencl_map_from_drm_beignet(AVHWFramesContext *dst_fc,
2067  AVFrame *dst, const AVFrame *src,
2068  int flags)
2069 {
2070  AVOpenCLDeviceContext *hwctx = dst_fc->device_ctx->hwctx;
2071  OpenCLDeviceContext *priv = dst_fc->device_ctx->internal->priv;
2072  DRMBeignetToOpenCLMapping *mapping;
2073  const AVDRMFrameDescriptor *desc;
2074  cl_int cle;
2075  int err, i, j, p;
2076 
2077  desc = (const AVDRMFrameDescriptor*)src->data[0];
2078 
2079  mapping = av_mallocz(sizeof(*mapping));
2080  if (!mapping)
2081  return AVERROR(ENOMEM);
2082 
2083  p = 0;
2084  for (i = 0; i < desc->nb_layers; i++) {
2085  const AVDRMLayerDescriptor *layer = &desc->layers[i];
2086  for (j = 0; j < layer->nb_planes; j++) {
2087  const AVDRMPlaneDescriptor *plane = &layer->planes[j];
2088  const AVDRMObjectDescriptor *object =
2089  &desc->objects[plane->object_index];
2090 
2091  cl_import_image_info_intel image_info = {
2092  .fd = object->fd,
2093  .size = object->size,
2094  .type = CL_MEM_OBJECT_IMAGE2D,
2095  .offset = plane->offset,
2096  .row_pitch = plane->pitch,
2097  };
2098  cl_image_desc image_desc;
2099 
2100  err = opencl_get_plane_format(dst_fc->sw_format, p,
2101  src->width, src->height,
2102  &image_info.fmt,
2103  &image_desc);
2104  if (err < 0) {
2105  av_log(dst_fc, AV_LOG_ERROR, "DRM frame layer %d "
2106  "plane %d is not representable in OpenCL: %d.\n",
2107  i, j, err);
2108  goto fail;
2109  }
2110  image_info.width = image_desc.image_width;
2111  image_info.height = image_desc.image_height;
2112 
2113  mapping->frame.planes[p] =
2114  priv->clCreateImageFromFdINTEL(hwctx->context,
2115  &image_info, &cle);
2116  if (!mapping->frame.planes[p]) {
2117  av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL image "
2118  "from layer %d plane %d of DRM frame: %d.\n",
2119  i, j, cle);
2120  err = AVERROR(EIO);
2121  goto fail;
2122  }
2123 
2124  dst->data[p] = (uint8_t*)mapping->frame.planes[p];
2125  mapping->frame.nb_planes = ++p;
2126  }
2127  }
2128 
2129  err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src,
2130  &opencl_unmap_from_drm_beignet,
2131  mapping);
2132  if (err < 0)
2133  goto fail;
2134 
2135  dst->width = src->width;
2136  dst->height = src->height;
2137 
2138  return 0;
2139 
2140 fail:
2141  for (p = 0; p < mapping->frame.nb_planes; p++) {
2142  if (mapping->frame.planes[p])
2143  clReleaseMemObject(mapping->frame.planes[p]);
2144  }
2145  av_free(mapping);
2146  return err;
2147 }
2148 
2149 #if HAVE_OPENCL_VAAPI_BEIGNET
2150 
2151 static int opencl_map_from_vaapi(AVHWFramesContext *dst_fc,
2152  AVFrame *dst, const AVFrame *src,
2153  int flags)
2154 {
2155  AVFrame *tmp;
2156  int err;
2157 
2158  tmp = av_frame_alloc();
2159  if (!tmp)
2160  return AVERROR(ENOMEM);
2161 
2163 
2164  err = av_hwframe_map(tmp, src, flags);
2165  if (err < 0)
2166  goto fail;
2167 
2168  err = opencl_map_from_drm_beignet(dst_fc, dst, tmp, flags);
2169  if (err < 0)
2170  goto fail;
2171 
2172  err = ff_hwframe_map_replace(dst, src);
2173 
2174 fail:
2175  av_frame_free(&tmp);
2176  return err;
2177 }
2178 
2179 #endif /* HAVE_OPENCL_VAAPI_BEIGNET */
2180 #endif /* HAVE_OPENCL_DRM_BEIGNET */
2181 
2182 static inline cl_mem_flags opencl_mem_flags_for_mapping(int map_flags)
2183 {
2184  if ((map_flags & AV_HWFRAME_MAP_READ) &&
2185  (map_flags & AV_HWFRAME_MAP_WRITE))
2186  return CL_MEM_READ_WRITE;
2187  else if (map_flags & AV_HWFRAME_MAP_READ)
2188  return CL_MEM_READ_ONLY;
2189  else if (map_flags & AV_HWFRAME_MAP_WRITE)
2190  return CL_MEM_WRITE_ONLY;
2191  else
2192  return 0;
2193 }
2194 
2195 #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
2196 
2197 static void opencl_unmap_from_qsv(AVHWFramesContext *dst_fc,
2198  HWMapDescriptor *hwmap)
2199 {
2200  AVOpenCLFrameDescriptor *desc = hwmap->priv;
2201  OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv;
2202  OpenCLFramesContext *frames_priv = dst_fc->internal->priv;
2203  cl_event event;
2204  cl_int cle;
2205  int p;
2206 
2207  av_log(dst_fc, AV_LOG_DEBUG, "Unmap QSV/VAAPI surface from OpenCL.\n");
2208 
2209  cle = device_priv->clEnqueueReleaseVA_APIMediaSurfacesINTEL(
2210  frames_priv->command_queue, desc->nb_planes, desc->planes,
2211  0, NULL, &event);
2212  if (cle != CL_SUCCESS) {
2213  av_log(dst_fc, AV_LOG_ERROR, "Failed to release surface "
2214  "handles: %d.\n", cle);
2215  }
2216 
2217  opencl_wait_events(dst_fc, &event, 1);
2218 
2219  for (p = 0; p < desc->nb_planes; p++) {
2220  cle = clReleaseMemObject(desc->planes[p]);
2221  if (cle != CL_SUCCESS) {
2222  av_log(dst_fc, AV_LOG_ERROR, "Failed to release CL "
2223  "image of plane %d of QSV/VAAPI surface: %d\n",
2224  p, cle);
2225  }
2226  }
2227 
2228  av_free(desc);
2229 }
2230 
2231 static int opencl_map_from_qsv(AVHWFramesContext *dst_fc, AVFrame *dst,
2232  const AVFrame *src, int flags)
2233 {
2234  AVHWFramesContext *src_fc =
2236  AVOpenCLDeviceContext *dst_dev = dst_fc->device_ctx->hwctx;
2237  OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv;
2238  OpenCLFramesContext *frames_priv = dst_fc->internal->priv;
2240  VASurfaceID va_surface;
2241  cl_mem_flags cl_flags;
2242  cl_event event;
2243  cl_int cle;
2244  int err, p;
2245 
2246 #if CONFIG_LIBMFX
2247  if (src->format == AV_PIX_FMT_QSV) {
2248  mfxFrameSurface1 *mfx_surface = (mfxFrameSurface1*)src->data[3];
2249  va_surface = *(VASurfaceID*)mfx_surface->Data.MemId;
2250  } else
2251 #endif
2252  if (src->format == AV_PIX_FMT_VAAPI) {
2253  va_surface = (VASurfaceID)(uintptr_t)src->data[3];
2254  } else {
2255  return AVERROR(ENOSYS);
2256  }
2257 
2258  cl_flags = opencl_mem_flags_for_mapping(flags);
2259  if (!cl_flags)
2260  return AVERROR(EINVAL);
2261 
2262  av_log(src_fc, AV_LOG_DEBUG, "Map QSV/VAAPI surface %#x to "
2263  "OpenCL.\n", va_surface);
2264 
2265  desc = av_mallocz(sizeof(*desc));
2266  if (!desc)
2267  return AVERROR(ENOMEM);
2268 
2269  // The cl_intel_va_api_media_sharing extension only supports NV12
2270  // surfaces, so for now there are always exactly two planes.
2271  desc->nb_planes = 2;
2272 
2273  for (p = 0; p < desc->nb_planes; p++) {
2274  desc->planes[p] =
2275  device_priv->clCreateFromVA_APIMediaSurfaceINTEL(
2276  dst_dev->context, cl_flags, &va_surface, p, &cle);
2277  if (!desc->planes[p]) {
2278  av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL "
2279  "image from plane %d of QSV/VAAPI surface "
2280  "%#x: %d.\n", p, va_surface, cle);
2281  err = AVERROR(EIO);
2282  goto fail;
2283  }
2284 
2285  dst->data[p] = (uint8_t*)desc->planes[p];
2286  }
2287 
2288  cle = device_priv->clEnqueueAcquireVA_APIMediaSurfacesINTEL(
2289  frames_priv->command_queue, desc->nb_planes, desc->planes,
2290  0, NULL, &event);
2291  if (cle != CL_SUCCESS) {
2292  av_log(dst_fc, AV_LOG_ERROR, "Failed to acquire surface "
2293  "handles: %d.\n", cle);
2294  err = AVERROR(EIO);
2295  goto fail;
2296  }
2297 
2298  err = opencl_wait_events(dst_fc, &event, 1);
2299  if (err < 0)
2300  goto fail;
2301 
2302  err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src,
2303  &opencl_unmap_from_qsv, desc);
2304  if (err < 0)
2305  goto fail;
2306 
2307  dst->width = src->width;
2308  dst->height = src->height;
2309 
2310  return 0;
2311 
2312 fail:
2313  for (p = 0; p < desc->nb_planes; p++)
2314  if (desc->planes[p])
2315  clReleaseMemObject(desc->planes[p]);
2316  av_freep(&desc);
2317  return err;
2318 }
2319 
2320 #endif
2321 
2322 #if HAVE_OPENCL_DXVA2
2323 
2324 static void opencl_unmap_from_dxva2(AVHWFramesContext *dst_fc,
2325  HWMapDescriptor *hwmap)
2326 {
2327  AVOpenCLFrameDescriptor *desc = hwmap->priv;
2328  OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv;
2329  OpenCLFramesContext *frames_priv = dst_fc->device_ctx->internal->priv;
2330  cl_event event;
2331  cl_int cle;
2332 
2333  av_log(dst_fc, AV_LOG_DEBUG, "Unmap DXVA2 surface from OpenCL.\n");
2334 
2335  cle = device_priv->clEnqueueReleaseDX9MediaSurfacesKHR(
2336  frames_priv->command_queue, desc->nb_planes, desc->planes,
2337  0, NULL, &event);
2338  if (cle != CL_SUCCESS) {
2339  av_log(dst_fc, AV_LOG_ERROR, "Failed to release surface "
2340  "handle: %d.\n", cle);
2341  return;
2342  }
2343 
2344  opencl_wait_events(dst_fc, &event, 1);
2345 }
2346 
2347 static int opencl_map_from_dxva2(AVHWFramesContext *dst_fc, AVFrame *dst,
2348  const AVFrame *src, int flags)
2349 {
2350  AVHWFramesContext *src_fc =
2352  AVDXVA2FramesContext *src_hwctx = src_fc->hwctx;
2353  OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv;
2354  OpenCLFramesContext *frames_priv = dst_fc->internal->priv;
2356  cl_event event;
2357  cl_int cle;
2358  int err, i;
2359 
2360  av_log(dst_fc, AV_LOG_DEBUG, "Map DXVA2 surface %p to "
2361  "OpenCL.\n", src->data[3]);
2362 
2363  for (i = 0; i < src_hwctx->nb_surfaces; i++) {
2364  if (src_hwctx->surfaces[i] == (IDirect3DSurface9*)src->data[3])
2365  break;
2366  }
2367  if (i >= src_hwctx->nb_surfaces) {
2368  av_log(dst_fc, AV_LOG_ERROR, "Trying to map from a surface which "
2369  "is not in the mapped frames context.\n");
2370  return AVERROR(EINVAL);
2371  }
2372 
2373  desc = &frames_priv->mapped_frames[i];
2374 
2375  cle = device_priv->clEnqueueAcquireDX9MediaSurfacesKHR(
2376  frames_priv->command_queue, desc->nb_planes, desc->planes,
2377  0, NULL, &event);
2378  if (cle != CL_SUCCESS) {
2379  av_log(dst_fc, AV_LOG_ERROR, "Failed to acquire surface "
2380  "handle: %d.\n", cle);
2381  return AVERROR(EIO);
2382  }
2383 
2384  err = opencl_wait_events(dst_fc, &event, 1);
2385  if (err < 0)
2386  goto fail;
2387 
2388  for (i = 0; i < desc->nb_planes; i++)
2389  dst->data[i] = (uint8_t*)desc->planes[i];
2390 
2391  err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src,
2392  &opencl_unmap_from_dxva2, desc);
2393  if (err < 0)
2394  goto fail;
2395 
2396  dst->width = src->width;
2397  dst->height = src->height;
2398 
2399  return 0;
2400 
2401 fail:
2402  cle = device_priv->clEnqueueReleaseDX9MediaSurfacesKHR(
2403  frames_priv->command_queue, desc->nb_planes, desc->planes,
2404  0, NULL, &event);
2405  if (cle == CL_SUCCESS)
2406  opencl_wait_events(dst_fc, &event, 1);
2407  return err;
2408 }
2409 
2410 static int opencl_frames_derive_from_dxva2(AVHWFramesContext *dst_fc,
2411  AVHWFramesContext *src_fc, int flags)
2412 {
2413  AVOpenCLDeviceContext *dst_dev = dst_fc->device_ctx->hwctx;
2414  AVDXVA2FramesContext *src_hwctx = src_fc->hwctx;
2415  OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv;
2416  OpenCLFramesContext *frames_priv = dst_fc->internal->priv;
2417  cl_mem_flags cl_flags;
2418  cl_int cle;
2419  int err, i, p, nb_planes;
2420 
2421  if (src_fc->sw_format != AV_PIX_FMT_NV12) {
2422  av_log(dst_fc, AV_LOG_ERROR, "Only NV12 textures are supported "
2423  "for DXVA2 to OpenCL mapping.\n");
2424  return AVERROR(EINVAL);
2425  }
2426  nb_planes = 2;
2427 
2428  if (src_fc->initial_pool_size == 0) {
2429  av_log(dst_fc, AV_LOG_ERROR, "Only fixed-size pools are supported "
2430  "for DXVA2 to OpenCL mapping.\n");
2431  return AVERROR(EINVAL);
2432  }
2433 
2434  cl_flags = opencl_mem_flags_for_mapping(flags);
2435  if (!cl_flags)
2436  return AVERROR(EINVAL);
2437 
2438  frames_priv->nb_mapped_frames = src_hwctx->nb_surfaces;
2439 
2440  frames_priv->mapped_frames =
2441  av_mallocz_array(frames_priv->nb_mapped_frames,
2442  sizeof(*frames_priv->mapped_frames));
2443  if (!frames_priv->mapped_frames)
2444  return AVERROR(ENOMEM);
2445 
2446  for (i = 0; i < frames_priv->nb_mapped_frames; i++) {
2447  AVOpenCLFrameDescriptor *desc = &frames_priv->mapped_frames[i];
2448  cl_dx9_surface_info_khr surface_info = {
2449  .resource = src_hwctx->surfaces[i],
2450  .shared_handle = NULL,
2451  };
2452  desc->nb_planes = nb_planes;
2453  for (p = 0; p < nb_planes; p++) {
2454  desc->planes[p] =
2455  device_priv->clCreateFromDX9MediaSurfaceKHR(
2456  dst_dev->context, cl_flags,
2457  device_priv->dx9_media_adapter_type,
2458  &surface_info, p, &cle);
2459  if (!desc->planes[p]) {
2460  av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL "
2461  "image from plane %d of DXVA2 surface %d: %d.\n",
2462  p, i, cle);
2463  err = AVERROR(EIO);
2464  goto fail;
2465  }
2466  }
2467  }
2468 
2469  return 0;
2470 
2471 fail:
2472  for (i = 0; i < frames_priv->nb_mapped_frames; i++) {
2473  AVOpenCLFrameDescriptor *desc = &frames_priv->mapped_frames[i];
2474  for (p = 0; p < desc->nb_planes; p++) {
2475  if (desc->planes[p])
2476  clReleaseMemObject(desc->planes[p]);
2477  }
2478  }
2479  av_freep(&frames_priv->mapped_frames);
2480  frames_priv->nb_mapped_frames = 0;
2481  return err;
2482 }
2483 
2484 #endif
2485 
2486 #if HAVE_OPENCL_D3D11
2487 
2488 static void opencl_unmap_from_d3d11(AVHWFramesContext *dst_fc,
2489  HWMapDescriptor *hwmap)
2490 {
2491  AVOpenCLFrameDescriptor *desc = hwmap->priv;
2492  OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv;
2493  OpenCLFramesContext *frames_priv = dst_fc->device_ctx->internal->priv;
2494  cl_event event;
2495  cl_int cle;
2496 
2497  cle = device_priv->clEnqueueReleaseD3D11ObjectsKHR(
2498  frames_priv->command_queue, desc->nb_planes, desc->planes,
2499  0, NULL, &event);
2500  if (cle != CL_SUCCESS) {
2501  av_log(dst_fc, AV_LOG_ERROR, "Failed to release surface "
2502  "handle: %d.\n", cle);
2503  }
2504 
2505  opencl_wait_events(dst_fc, &event, 1);
2506 }
2507 
2508 static int opencl_map_from_d3d11(AVHWFramesContext *dst_fc, AVFrame *dst,
2509  const AVFrame *src, int flags)
2510 {
2511  OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv;
2512  OpenCLFramesContext *frames_priv = dst_fc->internal->priv;
2514  cl_event event;
2515  cl_int cle;
2516  int err, index, i;
2517 
2518  index = (intptr_t)src->data[1];
2519  if (index >= frames_priv->nb_mapped_frames) {
2520  av_log(dst_fc, AV_LOG_ERROR, "Texture array index out of range for "
2521  "mapping: %d >= %d.\n", index, frames_priv->nb_mapped_frames);
2522  return AVERROR(EINVAL);
2523  }
2524 
2525  av_log(dst_fc, AV_LOG_DEBUG, "Map D3D11 texture %d to OpenCL.\n",
2526  index);
2527 
2528  desc = &frames_priv->mapped_frames[index];
2529 
2530  cle = device_priv->clEnqueueAcquireD3D11ObjectsKHR(
2531  frames_priv->command_queue, desc->nb_planes, desc->planes,
2532  0, NULL, &event);
2533  if (cle != CL_SUCCESS) {
2534  av_log(dst_fc, AV_LOG_ERROR, "Failed to acquire surface "
2535  "handle: %d.\n", cle);
2536  return AVERROR(EIO);
2537  }
2538 
2539  err = opencl_wait_events(dst_fc, &event, 1);
2540  if (err < 0)
2541  goto fail;
2542 
2543  for (i = 0; i < desc->nb_planes; i++)
2544  dst->data[i] = (uint8_t*)desc->planes[i];
2545 
2546  err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src,
2547  &opencl_unmap_from_d3d11, desc);
2548  if (err < 0)
2549  goto fail;
2550 
2551  dst->width = src->width;
2552  dst->height = src->height;
2553 
2554  return 0;
2555 
2556 fail:
2557  cle = device_priv->clEnqueueReleaseD3D11ObjectsKHR(
2558  frames_priv->command_queue, desc->nb_planes, desc->planes,
2559  0, NULL, &event);
2560  if (cle == CL_SUCCESS)
2561  opencl_wait_events(dst_fc, &event, 1);
2562  return err;
2563 }
2564 
2565 static int opencl_frames_derive_from_d3d11(AVHWFramesContext *dst_fc,
2566  AVHWFramesContext *src_fc, int flags)
2567 {
2568  AVOpenCLDeviceContext *dst_dev = dst_fc->device_ctx->hwctx;
2569  AVD3D11VAFramesContext *src_hwctx = src_fc->hwctx;
2570  OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv;
2571  OpenCLFramesContext *frames_priv = dst_fc->internal->priv;
2572  cl_mem_flags cl_flags;
2573  cl_int cle;
2574  int err, i, p, nb_planes;
2575 
2576  if (src_fc->sw_format != AV_PIX_FMT_NV12) {
2577  av_log(dst_fc, AV_LOG_ERROR, "Only NV12 textures are supported "
2578  "for D3D11 to OpenCL mapping.\n");
2579  return AVERROR(EINVAL);
2580  }
2581  nb_planes = 2;
2582 
2583  if (src_fc->initial_pool_size == 0) {
2584  av_log(dst_fc, AV_LOG_ERROR, "Only fixed-size pools are supported "
2585  "for D3D11 to OpenCL mapping.\n");
2586  return AVERROR(EINVAL);
2587  }
2588 
2589  cl_flags = opencl_mem_flags_for_mapping(flags);
2590  if (!cl_flags)
2591  return AVERROR(EINVAL);
2592 
2593  frames_priv->nb_mapped_frames = src_fc->initial_pool_size;
2594 
2595  frames_priv->mapped_frames =
2596  av_mallocz_array(frames_priv->nb_mapped_frames,
2597  sizeof(*frames_priv->mapped_frames));
2598  if (!frames_priv->mapped_frames)
2599  return AVERROR(ENOMEM);
2600 
2601  for (i = 0; i < frames_priv->nb_mapped_frames; i++) {
2602  AVOpenCLFrameDescriptor *desc = &frames_priv->mapped_frames[i];
2603  desc->nb_planes = nb_planes;
2604  for (p = 0; p < nb_planes; p++) {
2605  UINT subresource = 2 * i + p;
2606 
2607  desc->planes[p] =
2608  device_priv->clCreateFromD3D11Texture2DKHR(
2609  dst_dev->context, cl_flags, src_hwctx->texture,
2610  subresource, &cle);
2611  if (!desc->planes[p]) {
2612  av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL "
2613  "image from plane %d of D3D texture "
2614  "index %d (subresource %u): %d.\n",
2615  p, i, (unsigned int)subresource, cle);
2616  err = AVERROR(EIO);
2617  goto fail;
2618  }
2619  }
2620  }
2621 
2622  return 0;
2623 
2624 fail:
2625  for (i = 0; i < frames_priv->nb_mapped_frames; i++) {
2626  AVOpenCLFrameDescriptor *desc = &frames_priv->mapped_frames[i];
2627  for (p = 0; p < desc->nb_planes; p++) {
2628  if (desc->planes[p])
2629  clReleaseMemObject(desc->planes[p]);
2630  }
2631  }
2632  av_freep(&frames_priv->mapped_frames);
2633  frames_priv->nb_mapped_frames = 0;
2634  return err;
2635 }
2636 
2637 #endif
2638 
2639 #if HAVE_OPENCL_DRM_ARM
2640 
2641 typedef struct DRMARMtoOpenCLMapping {
2642  int nb_objects;
2643  cl_mem object_buffers[AV_DRM_MAX_PLANES];
2644  int nb_planes;
2645  cl_mem plane_images[AV_DRM_MAX_PLANES];
2646 } DRMARMtoOpenCLMapping;
2647 
2648 static void opencl_unmap_from_drm_arm(AVHWFramesContext *dst_fc,
2649  HWMapDescriptor *hwmap)
2650 {
2651  DRMARMtoOpenCLMapping *mapping = hwmap->priv;
2652  int i;
2653 
2654  for (i = 0; i < mapping->nb_planes; i++)
2655  clReleaseMemObject(mapping->plane_images[i]);
2656 
2657  for (i = 0; i < mapping->nb_objects; i++)
2658  clReleaseMemObject(mapping->object_buffers[i]);
2659 
2660  av_free(mapping);
2661 }
2662 
2663 static int opencl_map_from_drm_arm(AVHWFramesContext *dst_fc, AVFrame *dst,
2664  const AVFrame *src, int flags)
2665 {
2666  AVHWFramesContext *src_fc =
2668  AVOpenCLDeviceContext *dst_dev = dst_fc->device_ctx->hwctx;
2669  const AVDRMFrameDescriptor *desc;
2670  DRMARMtoOpenCLMapping *mapping = NULL;
2671  cl_mem_flags cl_flags;
2672  const cl_import_properties_arm props[3] = {
2673  CL_IMPORT_TYPE_ARM, CL_IMPORT_TYPE_DMA_BUF_ARM, 0,
2674  };
2675  cl_int cle;
2676  int err, i, j;
2677 
2678  desc = (const AVDRMFrameDescriptor*)src->data[0];
2679 
2680  cl_flags = opencl_mem_flags_for_mapping(flags);
2681  if (!cl_flags)
2682  return AVERROR(EINVAL);
2683 
2684  mapping = av_mallocz(sizeof(*mapping));
2685  if (!mapping)
2686  return AVERROR(ENOMEM);
2687 
2688  mapping->nb_objects = desc->nb_objects;
2689  for (i = 0; i < desc->nb_objects; i++) {
2690  int fd = desc->objects[i].fd;
2691 
2692  av_log(dst_fc, AV_LOG_DEBUG, "Map DRM PRIME fd %d to OpenCL.\n", fd);
2693 
2694  if (desc->objects[i].format_modifier) {
2695  av_log(dst_fc, AV_LOG_DEBUG, "Warning: object %d fd %d has "
2696  "nonzero format modifier %"PRId64", result may not "
2697  "be as expected.\n", i, fd,
2698  desc->objects[i].format_modifier);
2699  }
2700 
2701  mapping->object_buffers[i] =
2702  clImportMemoryARM(dst_dev->context, cl_flags, props,
2703  &fd, desc->objects[i].size, &cle);
2704  if (!mapping->object_buffers[i]) {
2705  av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL buffer "
2706  "from object %d (fd %d, size %"SIZE_SPECIFIER") of DRM frame: %d.\n",
2707  i, fd, desc->objects[i].size, cle);
2708  err = AVERROR(EIO);
2709  goto fail;
2710  }
2711  }
2712 
2713  mapping->nb_planes = 0;
2714  for (i = 0; i < desc->nb_layers; i++) {
2715  const AVDRMLayerDescriptor *layer = &desc->layers[i];
2716 
2717  for (j = 0; j < layer->nb_planes; j++) {
2718  const AVDRMPlaneDescriptor *plane = &layer->planes[j];
2719  cl_mem plane_buffer;
2720  cl_image_format image_format;
2721  cl_image_desc image_desc;
2722  cl_buffer_region region;
2723  int p = mapping->nb_planes;
2724 
2725  err = opencl_get_plane_format(src_fc->sw_format, p,
2726  src_fc->width, src_fc->height,
2727  &image_format, &image_desc);
2728  if (err < 0) {
2729  av_log(dst_fc, AV_LOG_ERROR, "Invalid plane %d (DRM "
2730  "layer %d plane %d): %d.\n", p, i, j, err);
2731  goto fail;
2732  }
2733 
2734  region.origin = plane->offset;
2735  region.size = image_desc.image_row_pitch *
2736  image_desc.image_height;
2737 
2738  plane_buffer =
2739  clCreateSubBuffer(mapping->object_buffers[plane->object_index],
2740  cl_flags,
2741  CL_BUFFER_CREATE_TYPE_REGION,
2742  &region, &cle);
2743  if (!plane_buffer) {
2744  av_log(dst_fc, AV_LOG_ERROR, "Failed to create sub-buffer "
2745  "for plane %d: %d.\n", p, cle);
2746  err = AVERROR(EIO);
2747  goto fail;
2748  }
2749 
2750  image_desc.buffer = plane_buffer;
2751 
2752  mapping->plane_images[p] =
2753  clCreateImage(dst_dev->context, cl_flags,
2754  &image_format, &image_desc, NULL, &cle);
2755 
2756  // Unreference the sub-buffer immediately - we don't need it
2757  // directly and a reference is held by the image.
2758  clReleaseMemObject(plane_buffer);
2759 
2760  if (!mapping->plane_images[p]) {
2761  av_log(dst_fc, AV_LOG_ERROR, "Failed to create image "
2762  "for plane %d: %d.\n", p, cle);
2763  err = AVERROR(EIO);
2764  goto fail;
2765  }
2766 
2767  ++mapping->nb_planes;
2768  }
2769  }
2770 
2771  for (i = 0; i < mapping->nb_planes; i++)
2772  dst->data[i] = (uint8_t*)mapping->plane_images[i];
2773 
2774  err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src,
2775  &opencl_unmap_from_drm_arm, mapping);
2776  if (err < 0)
2777  goto fail;
2778 
2779  dst->width = src->width;
2780  dst->height = src->height;
2781 
2782  return 0;
2783 
2784 fail:
2785  for (i = 0; i < mapping->nb_planes; i++) {
2786  clReleaseMemObject(mapping->plane_images[i]);
2787  }
2788  for (i = 0; i < mapping->nb_objects; i++) {
2789  if (mapping->object_buffers[i])
2790  clReleaseMemObject(mapping->object_buffers[i]);
2791  }
2792  av_free(mapping);
2793  return err;
2794 }
2795 
2796 #endif
2797 
2799  const AVFrame *src, int flags)
2800 {
2802  if (hwfc->sw_format != dst->format)
2803  return AVERROR(ENOSYS);
2804  return opencl_map_frame(hwfc, dst, src, flags);
2805 }
2806 
2807 static int opencl_map_to(AVHWFramesContext *hwfc, AVFrame *dst,
2808  const AVFrame *src, int flags)
2809 {
2812  switch (src->format) {
2813 #if HAVE_OPENCL_DRM_BEIGNET
2814  case AV_PIX_FMT_DRM_PRIME:
2815  if (priv->beignet_drm_mapping_usable)
2816  return opencl_map_from_drm_beignet(hwfc, dst, src, flags);
2817 #endif
2818 #if HAVE_OPENCL_VAAPI_BEIGNET
2819  case AV_PIX_FMT_VAAPI:
2820  if (priv->beignet_drm_mapping_usable)
2821  return opencl_map_from_vaapi(hwfc, dst, src, flags);
2822 #endif
2823 #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
2824  case AV_PIX_FMT_QSV:
2825  case AV_PIX_FMT_VAAPI:
2826  if (priv->qsv_mapping_usable)
2827  return opencl_map_from_qsv(hwfc, dst, src, flags);
2828 #endif
2829 #if HAVE_OPENCL_DXVA2
2830  case AV_PIX_FMT_DXVA2_VLD:
2831  if (priv->dxva2_mapping_usable)
2832  return opencl_map_from_dxva2(hwfc, dst, src, flags);
2833 #endif
2834 #if HAVE_OPENCL_D3D11
2835  case AV_PIX_FMT_D3D11:
2836  if (priv->d3d11_mapping_usable)
2837  return opencl_map_from_d3d11(hwfc, dst, src, flags);
2838 #endif
2839 #if HAVE_OPENCL_DRM_ARM
2840  case AV_PIX_FMT_DRM_PRIME:
2841  if (priv->drm_arm_mapping_usable)
2842  return opencl_map_from_drm_arm(hwfc, dst, src, flags);
2843 #endif
2844  }
2845  return AVERROR(ENOSYS);
2846 }
2847 
2849  AVHWFramesContext *src_fc, int flags)
2850 {
2852  switch (src_fc->device_ctx->type) {
2853 #if HAVE_OPENCL_DRM_BEIGNET
2854  case AV_HWDEVICE_TYPE_DRM:
2855  if (!priv->beignet_drm_mapping_usable)
2856  return AVERROR(ENOSYS);
2857  break;
2858 #endif
2859 #if HAVE_OPENCL_VAAPI_BEIGNET
2861  if (!priv->beignet_drm_mapping_usable)
2862  return AVERROR(ENOSYS);
2863  break;
2864 #endif
2865 #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
2866  case AV_HWDEVICE_TYPE_QSV:
2868  if (!priv->qsv_mapping_usable)
2869  return AVERROR(ENOSYS);
2870  break;
2871 #endif
2872 #if HAVE_OPENCL_DXVA2
2874  if (!priv->dxva2_mapping_usable)
2875  return AVERROR(ENOSYS);
2876  {
2877  int err;
2878  err = opencl_frames_derive_from_dxva2(dst_fc, src_fc, flags);
2879  if (err < 0)
2880  return err;
2881  }
2882  break;
2883 #endif
2884 #if HAVE_OPENCL_D3D11
2886  if (!priv->d3d11_mapping_usable)
2887  return AVERROR(ENOSYS);
2888  {
2889  int err;
2890  err = opencl_frames_derive_from_d3d11(dst_fc, src_fc, flags);
2891  if (err < 0)
2892  return err;
2893  }
2894  break;
2895 #endif
2896 #if HAVE_OPENCL_DRM_ARM
2897  case AV_HWDEVICE_TYPE_DRM:
2898  if (!priv->drm_arm_mapping_usable)
2899  return AVERROR(ENOSYS);
2900  break;
2901 #endif
2902  default:
2903  return AVERROR(ENOSYS);
2904  }
2905  return opencl_frames_init_command_queue(dst_fc);
2906 }
2907 
2910  .name = "OpenCL",
2911 
2912  .device_hwctx_size = sizeof(AVOpenCLDeviceContext),
2913  .device_priv_size = sizeof(OpenCLDeviceContext),
2914  .frames_hwctx_size = sizeof(AVOpenCLFramesContext),
2915  .frames_priv_size = sizeof(OpenCLFramesContext),
2916 
2917  .device_create = &opencl_device_create,
2918  .device_derive = &opencl_device_derive,
2919  .device_init = &opencl_device_init,
2920  .device_uninit = &opencl_device_uninit,
2921 
2922  .frames_get_constraints = &opencl_frames_get_constraints,
2923  .frames_init = &opencl_frames_init,
2924  .frames_uninit = &opencl_frames_uninit,
2925  .frames_get_buffer = &opencl_get_buffer,
2926 
2927  .transfer_get_formats = &opencl_transfer_get_formats,
2928  .transfer_data_to = &opencl_transfer_data_to,
2929  .transfer_data_from = &opencl_transfer_data_from,
2930 
2931  .map_from = &opencl_map_from,
2932  .map_to = &opencl_map_to,
2933  .frames_derive_to = &opencl_frames_derive_to,
2934 
2935  .pix_fmts = (const enum AVPixelFormat[]) {
2938  },
2939 };
#define AV_PIX_FMT_FLAG_PAL
Pixel format has a palette in data[1], values are indexes in this palette.
Definition: pixdesc.h:132
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:60
int plane
Definition: avisynth_c.h:422
API-specific header for AV_HWDEVICE_TYPE_OPENCL.
static void opencl_device_free(AVHWDeviceContext *hwdev)
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:227
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2446
This structure describes decoded (raw) audio or video data.
Definition: frame.h:226
cl_command_queue command_queue
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:101
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:418
const char * desc
Definition: nvenc.c:65
char * av_stristr(const char *s1, const char *s2)
Locate the first case-independent occurrence in the string haystack of the string needle...
Definition: avstring.c:56
An API-specific header for AV_HWDEVICE_TYPE_DXVA2.
channels
Definition: aptx.c:30
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:228
static int opencl_frames_init_command_queue(AVHWFramesContext *hwfc)
void * address[AV_NUM_DATA_POINTERS]
const char * key
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_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)
int(* filter_platform)(AVHWDeviceContext *hwdev, cl_platform_id platform_id, const char *platform_name, void *context)
static int opencl_transfer_data_to(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src)
API-specific header for AV_HWDEVICE_TYPE_VAAPI.
int(* enumerate_platforms)(AVHWDeviceContext *hwdev, cl_uint *nb_platforms, cl_platform_id **platforms, void *context)
AVBufferRef * hw_frames_ctx
For hwaccel-format frames, this should be a reference to the AVHWFramesContext describing the frame...
Definition: frame.h:564
static int opencl_map_to(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
static int opencl_enumerate_devices(AVHWDeviceContext *hwdev, cl_platform_id platform_id, const char *platform_name, cl_uint *nb_devices, cl_device_id **devices, void *context)
DRM frame descriptor.
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
AVBufferPool * pool_internal
static double cb(void *priv, double x, double y)
Definition: vf_geq.c:112
enum AVHWDeviceType type
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
Definition: pixdesc.h:117
uint8_t
#define AV_PIX_FMT_FLAG_ALPHA
The pixel format has an alpha channel.
Definition: pixdesc.h: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.
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
#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.
AVDRMLayerDescriptor layers[AV_DRM_MAX_PLANES]
Array of layers in the frame.
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
ptrdiff_t size
Definition: opengl_enc.c:101
cl_platform_id platform_id
#define av_log(a,...)
int fd
DRM PRIME fd for the object.
Definition: hwcontext_drm.h:52
int nb_layers
Number of layers in the frame.
DRM layer descriptor.
Definition: hwcontext_drm.h:96
static int opencl_wait_events(AVHWFramesContext *hwfc, cl_event *events, int nb_events)
int object_index
Index of the object containing this plane in the objects array of the enclosing frame descriptor...
Definition: hwcontext_drm.h:79
int width
Definition: frame.h:284
#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
void(* free)(struct AVHWDeviceContext *ctx)
This field may be set by the caller before calling av_hwdevice_ctx_init().
Definition: hwcontext.h:103
#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)
ptrdiff_t pitch
Pitch (linesize) of this plane.
Definition: hwcontext_drm.h:87
#define FALSE
Definition: windows2linux.h:37
AVS_Value void * user_data
Definition: avisynth_c.h:699
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().
static int opencl_get_plane_format(enum AVPixelFormat pixfmt, int plane, int width, int height, cl_image_format *image_format, cl_image_desc *image_desc)
cl_command_queue command_queue
The command queue used for internal asynchronous operations on this device (av_hwframe_transfer_data(...
int nb_planes
Number of planes in the layer.
IDirect3DDeviceManager9 * devmgr
AVBufferRef * av_buffer_create(uint8_t *data, int size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition: buffer.c:28
enum AVHWDeviceType type
This field identifies the underlying API used for hardware access.
Definition: hwcontext.h:78
#define fail()
Definition: checkasm.h:117
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)
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 struct @287 opencl_device_types[]
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
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.
The mapping must be writeable.
Definition: hwcontext.h:507
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
#define FF_ARRAY_ELEMS(a)
int(* filter_device)(AVHWDeviceContext *hwdev, cl_device_id device_id, const char *device_name, void *context)
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.
The mapped frame will be overwritten completely in subsequent operations, so the current frame data n...
Definition: hwcontext.h:513
int(* enumerate_devices)(AVHWDeviceContext *hwdev, cl_platform_id platform_id, const char *platform_name, cl_uint *nb_devices, cl_device_id **devices, void *context)
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
Definition: frame.h:299
The mapping must be readable.
Definition: hwcontext.h:503
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:257
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
The maximum number of layers/planes in a DRM frame.
Definition: hwcontext_drm.h:39
static struct @286 opencl_device_params[]
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.
#define SIZE_SPECIFIER
Definition: internal.h:262
#define flags(name, subs,...)
Definition: cbs_av1.c:596
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:240
cl_command_queue command_queue
Hardware surfaces for Direct3D11.
Definition: pixfmt.h:313
#define SUCCEEDED(hr)
Definition: windows2linux.h:49
static AVBufferRef * opencl_pool_alloc(void *opaque, int size)
A reference to a data buffer.
Definition: buffer.h:81
int
static int opencl_filter_device(AVHWDeviceContext *hwdev, cl_device_id device_id, const char *device_name, void *context)
static int opencl_check_platform_extension(cl_platform_id platform_id, const char *name)
common internal and external API header
if(ret< 0)
Definition: vf_mcdeint.c:279
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 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:343
This struct is allocated as AVHWDeviceContext.hwctx.
int height
Definition: frame.h:284
#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)
static struct @285 opencl_platform_params[]
formats
Definition: signature.h:48
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:2362
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)
Definition: mem.c:191
const char * name
Definition: opengl_enc.c:103
cl_platform_info name
static uint8_t tmp[11]
Definition: aes_ctr.c:26