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