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