FFmpeg
hwcontext_opencl.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #define CL_USE_DEPRECATED_OPENCL_1_2_APIS
20 
21 #include <string.h>
22 
23 #include "config.h"
24 
25 #include "avassert.h"
26 #include "avstring.h"
27 #include "common.h"
28 #include "hwcontext.h"
29 #include "hwcontext_internal.h"
30 #include "hwcontext_opencl.h"
31 #include "mem.h"
32 #include "pixdesc.h"
33 
34 #if HAVE_OPENCL_VAAPI_BEIGNET
35 #include <unistd.h>
36 #include <va/va.h>
37 #include <va/va_drmcommon.h>
38 #include <CL/cl_intel.h>
39 #include "hwcontext_vaapi.h"
40 #endif
41 
42 #if HAVE_OPENCL_DRM_BEIGNET
43 #include <unistd.h>
44 #include <CL/cl_intel.h>
45 #include "hwcontext_drm.h"
46 #endif
47 
48 #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
49 #if CONFIG_LIBMFX
50 #include <mfx/mfxstructures.h>
51 #endif
52 #include <va/va.h>
53 #include <CL/cl_va_api_media_sharing_intel.h>
54 #include "hwcontext_vaapi.h"
55 #endif
56 
57 #if HAVE_OPENCL_DXVA2
58 #define COBJMACROS
59 #include <CL/cl_dx9_media_sharing.h>
60 #include <dxva2api.h>
61 #include "hwcontext_dxva2.h"
62 #endif
63 
64 #if HAVE_OPENCL_D3D11
65 #include <CL/cl_d3d11.h>
66 #include "hwcontext_d3d11va.h"
67 #endif
68 
69 #if HAVE_OPENCL_DRM_ARM
70 #include <CL/cl_ext.h>
71 #include <drm_fourcc.h>
72 #include "hwcontext_drm.h"
73 #endif
74 
75 #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  return AVERROR(EINVAL);
1416  // The depth must not vary between components.
1417  if (depth && comp->depth != depth)
1418  return AVERROR(EINVAL);
1419  // If a single data element crosses multiple bytes then
1420  // it must match the native endianness.
1421  if (comp->depth > 8 &&
1422  HAVE_BIGENDIAN == !(desc->flags & AV_PIX_FMT_FLAG_BE))
1423  return AVERROR(EINVAL);
1424  // A single data element must not contain multiple samples
1425  // from the same component.
1426  if (step && comp->step != step)
1427  return AVERROR(EINVAL);
1428 
1429  depth = comp->depth;
1430  order = order * 10 + comp->offset / ((depth + 7) / 8) + 1;
1431  step = comp->step;
1432  alpha = (desc->flags & AV_PIX_FMT_FLAG_ALPHA &&
1433  c == desc->nb_components - 1);
1434  ++channels;
1435  }
1436  if (channels == 0)
1437  return AVERROR(ENOENT);
1438 
1439  memset(image_format, 0, sizeof(*image_format));
1440  memset(image_desc, 0, sizeof(*image_desc));
1441  image_desc->image_type = CL_MEM_OBJECT_IMAGE2D;
1442 
1443  if (plane == 0 || alpha) {
1444  image_desc->image_width = width;
1445  image_desc->image_height = height;
1446  image_desc->image_row_pitch = step * width;
1447  } else {
1448  image_desc->image_width = width / wsub;
1449  image_desc->image_height = height / hsub;
1450  image_desc->image_row_pitch = step * width / wsub;
1451  }
1452 
1453  if (depth <= 8) {
1454  image_format->image_channel_data_type = CL_UNORM_INT8;
1455  } else {
1456  if (depth <= 16)
1457  image_format->image_channel_data_type = CL_UNORM_INT16;
1458  else
1459  return AVERROR(EINVAL);
1460  }
1461 
1462 #define CHANNEL_ORDER(order, type) \
1463  case order: image_format->image_channel_order = type; break;
1464  switch (order) {
1465  CHANNEL_ORDER(1, CL_R);
1466  CHANNEL_ORDER(12, CL_RG);
1467  CHANNEL_ORDER(1234, CL_RGBA);
1468  CHANNEL_ORDER(2341, CL_ARGB);
1469  CHANNEL_ORDER(3214, CL_BGRA);
1470 #ifdef CL_ABGR
1471  CHANNEL_ORDER(4321, CL_ABGR);
1472 #endif
1473  default:
1474  return AVERROR(EINVAL);
1475  }
1476 #undef CHANNEL_ORDER
1477 
1478  return 0;
1479 }
1480 
1482  const void *hwconfig,
1483  AVHWFramesConstraints *constraints)
1484 {
1485  AVOpenCLDeviceContext *hwctx = hwdev->hwctx;
1486  cl_uint nb_image_formats;
1487  cl_image_format *image_formats = NULL;
1488  cl_int cle;
1489  enum AVPixelFormat pix_fmt;
1490  int err, pix_fmts_found;
1491  size_t max_width, max_height;
1492 
1493  cle = clGetDeviceInfo(hwctx->device_id, CL_DEVICE_IMAGE2D_MAX_WIDTH,
1494  sizeof(max_width), &max_width, NULL);
1495  if (cle != CL_SUCCESS) {
1496  av_log(hwdev, AV_LOG_ERROR, "Failed to query maximum "
1497  "supported image width: %d.\n", cle);
1498  } else {
1499  constraints->max_width = max_width;
1500  }
1501  cle = clGetDeviceInfo(hwctx->device_id, CL_DEVICE_IMAGE2D_MAX_HEIGHT,
1502  sizeof(max_height), &max_height, NULL);
1503  if (cle != CL_SUCCESS) {
1504  av_log(hwdev, AV_LOG_ERROR, "Failed to query maximum "
1505  "supported image height: %d.\n", cle);
1506  } else {
1507  constraints->max_height = max_height;
1508  }
1509  av_log(hwdev, AV_LOG_DEBUG, "Maximum supported image size %dx%d.\n",
1510  constraints->max_width, constraints->max_height);
1511 
1512  cle = clGetSupportedImageFormats(hwctx->context,
1513  CL_MEM_READ_WRITE,
1514  CL_MEM_OBJECT_IMAGE2D,
1515  0, NULL, &nb_image_formats);
1516  if (cle != CL_SUCCESS) {
1517  av_log(hwdev, AV_LOG_ERROR, "Failed to query supported "
1518  "image formats: %d.\n", cle);
1519  err = AVERROR(ENOSYS);
1520  goto fail;
1521  }
1522  if (nb_image_formats == 0) {
1523  av_log(hwdev, AV_LOG_ERROR, "No image support in OpenCL "
1524  "driver (zero supported image formats).\n");
1525  err = AVERROR(ENOSYS);
1526  goto fail;
1527  }
1528 
1529  image_formats =
1530  av_malloc_array(nb_image_formats, sizeof(*image_formats));
1531  if (!image_formats) {
1532  err = AVERROR(ENOMEM);
1533  goto fail;
1534  }
1535 
1536  cle = clGetSupportedImageFormats(hwctx->context,
1537  CL_MEM_READ_WRITE,
1538  CL_MEM_OBJECT_IMAGE2D,
1539  nb_image_formats,
1540  image_formats, NULL);
1541  if (cle != CL_SUCCESS) {
1542  av_log(hwdev, AV_LOG_ERROR, "Failed to query supported "
1543  "image formats: %d.\n", cle);
1544  err = AVERROR(ENOSYS);
1545  goto fail;
1546  }
1547 
1548  pix_fmts_found = 0;
1549  for (pix_fmt = 0; pix_fmt < AV_PIX_FMT_NB; pix_fmt++) {
1550  cl_image_format image_format;
1551  cl_image_desc image_desc;
1552  int plane, i;
1553 
1554  for (plane = 0;; plane++) {
1555  err = opencl_get_plane_format(pix_fmt, plane, 0, 0,
1556  &image_format,
1557  &image_desc);
1558  if (err < 0)
1559  break;
1560 
1561  for (i = 0; i < nb_image_formats; i++) {
1562  if (image_formats[i].image_channel_order ==
1563  image_format.image_channel_order &&
1564  image_formats[i].image_channel_data_type ==
1565  image_format.image_channel_data_type)
1566  break;
1567  }
1568  if (i == nb_image_formats) {
1569  err = AVERROR(EINVAL);
1570  break;
1571  }
1572  }
1573  if (err != AVERROR(ENOENT))
1574  continue;
1575 
1576  av_log(hwdev, AV_LOG_DEBUG, "Format %s supported.\n",
1578 
1579  err = av_reallocp_array(&constraints->valid_sw_formats,
1580  pix_fmts_found + 2,
1581  sizeof(*constraints->valid_sw_formats));
1582  if (err < 0)
1583  goto fail;
1584  constraints->valid_sw_formats[pix_fmts_found] = pix_fmt;
1585  constraints->valid_sw_formats[pix_fmts_found + 1] =
1587  ++pix_fmts_found;
1588  }
1589 
1590  av_freep(&image_formats);
1591 
1592  constraints->valid_hw_formats =
1593  av_malloc_array(2, sizeof(*constraints->valid_hw_formats));
1594  if (!constraints->valid_hw_formats) {
1595  err = AVERROR(ENOMEM);
1596  goto fail;
1597  }
1598  constraints->valid_hw_formats[0] = AV_PIX_FMT_OPENCL;
1599  constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE;
1600 
1601  return 0;
1602 
1603 fail:
1604  av_freep(&image_formats);
1605  return err;
1606 }
1607 
1608 static void opencl_pool_free(void *opaque, uint8_t *data)
1609 {
1610  AVHWFramesContext *hwfc = opaque;
1612  cl_int cle;
1613  int p;
1614 
1615  for (p = 0; p < desc->nb_planes; p++) {
1616  cle = clReleaseMemObject(desc->planes[p]);
1617  if (cle != CL_SUCCESS) {
1618  av_log(hwfc, AV_LOG_ERROR, "Failed to release plane %d: "
1619  "%d.\n", p, cle);
1620  }
1621  }
1622 
1623  av_free(desc);
1624 }
1625 
1626 static AVBufferRef *opencl_pool_alloc(void *opaque, size_t size)
1627 {
1628  AVHWFramesContext *hwfc = opaque;
1629  AVOpenCLDeviceContext *hwctx = hwfc->device_ctx->hwctx;
1631  cl_int cle;
1632  cl_mem image;
1633  cl_image_format image_format;
1634  cl_image_desc image_desc;
1635  int err, p;
1636  AVBufferRef *ref;
1637 
1638  desc = av_mallocz(sizeof(*desc));
1639  if (!desc)
1640  return NULL;
1641 
1642  for (p = 0;; p++) {
1643  err = opencl_get_plane_format(hwfc->sw_format, p,
1644  hwfc->width, hwfc->height,
1645  &image_format, &image_desc);
1646  if (err == AVERROR(ENOENT))
1647  break;
1648  if (err < 0)
1649  goto fail;
1650 
1651  // For generic image objects, the pitch is determined by the
1652  // implementation.
1653  image_desc.image_row_pitch = 0;
1654 
1655  image = clCreateImage(hwctx->context, CL_MEM_READ_WRITE,
1656  &image_format, &image_desc, NULL, &cle);
1657  if (!image) {
1658  av_log(hwfc, AV_LOG_ERROR, "Failed to create image for "
1659  "plane %d: %d.\n", p, cle);
1660  goto fail;
1661  }
1662 
1663  desc->planes[p] = image;
1664  }
1665 
1666  desc->nb_planes = p;
1667 
1668  ref = av_buffer_create((uint8_t*)desc, sizeof(*desc),
1669  &opencl_pool_free, hwfc, 0);
1670  if (!ref)
1671  goto fail;
1672 
1673  return ref;
1674 
1675 fail:
1676  for (p = 0; desc->planes[p]; p++)
1677  clReleaseMemObject(desc->planes[p]);
1678  av_free(desc);
1679  return NULL;
1680 }
1681 
1683 {
1684  AVOpenCLFramesContext *hwctx = hwfc->hwctx;
1685  OpenCLDeviceContext *devpriv = hwfc->device_ctx->internal->priv;
1686  OpenCLFramesContext *priv = hwfc->internal->priv;
1687  cl_int cle;
1688 
1689  priv->command_queue = hwctx->command_queue ? hwctx->command_queue
1690  : devpriv->command_queue;
1691  cle = clRetainCommandQueue(priv->command_queue);
1692  if (cle != CL_SUCCESS) {
1693  av_log(hwfc, AV_LOG_ERROR, "Failed to retain frame "
1694  "command queue: %d.\n", cle);
1695  return AVERROR(EIO);
1696  }
1697 
1698  return 0;
1699 }
1700 
1702 {
1703  if (!hwfc->pool) {
1704  hwfc->internal->pool_internal =
1705  av_buffer_pool_init2(sizeof(cl_mem), hwfc,
1707  if (!hwfc->internal->pool_internal)
1708  return AVERROR(ENOMEM);
1709  }
1710 
1711  return opencl_frames_init_command_queue(hwfc);
1712 }
1713 
1715 {
1716  OpenCLFramesContext *priv = hwfc->internal->priv;
1717  cl_int cle;
1718 
1719 #if HAVE_OPENCL_DXVA2 || HAVE_OPENCL_D3D11
1720  int i, p;
1721  for (i = 0; i < priv->nb_mapped_frames; i++) {
1722  AVOpenCLFrameDescriptor *desc = &priv->mapped_frames[i];
1723  for (p = 0; p < desc->nb_planes; p++) {
1724  cle = clReleaseMemObject(desc->planes[p]);
1725  if (cle != CL_SUCCESS) {
1726  av_log(hwfc, AV_LOG_ERROR, "Failed to release mapped "
1727  "frame object (frame %d plane %d): %d.\n",
1728  i, p, cle);
1729  }
1730  }
1731  }
1732  av_freep(&priv->mapped_frames);
1733 #endif
1734 
1735  if (priv->command_queue) {
1736  cle = clReleaseCommandQueue(priv->command_queue);
1737  if (cle != CL_SUCCESS) {
1738  av_log(hwfc, AV_LOG_ERROR, "Failed to release frame "
1739  "command queue: %d.\n", cle);
1740  }
1741  priv->command_queue = NULL;
1742  }
1743 }
1744 
1746 {
1748  int p;
1749 
1750  frame->buf[0] = av_buffer_pool_get(hwfc->pool);
1751  if (!frame->buf[0])
1752  return AVERROR(ENOMEM);
1753 
1754  desc = (AVOpenCLFrameDescriptor*)frame->buf[0]->data;
1755 
1756  for (p = 0; p < desc->nb_planes; p++)
1757  frame->data[p] = (uint8_t*)desc->planes[p];
1758 
1759  frame->format = AV_PIX_FMT_OPENCL;
1760  frame->width = hwfc->width;
1761  frame->height = hwfc->height;
1762 
1763  return 0;
1764 }
1765 
1767  enum AVHWFrameTransferDirection dir,
1768  enum AVPixelFormat **formats)
1769 {
1770  enum AVPixelFormat *fmts;
1771 
1772  fmts = av_malloc_array(2, sizeof(*fmts));
1773  if (!fmts)
1774  return AVERROR(ENOMEM);
1775 
1776  fmts[0] = hwfc->sw_format;
1777  fmts[1] = AV_PIX_FMT_NONE;
1778 
1779  *formats = fmts;
1780  return 0;
1781 }
1782 
1784  cl_event *events, int nb_events)
1785 {
1786  cl_int cle;
1787  int i;
1788 
1789  cle = clWaitForEvents(nb_events, events);
1790  if (cle != CL_SUCCESS) {
1791  av_log(hwfc, AV_LOG_ERROR, "Failed to wait for event "
1792  "completion: %d.\n", cle);
1793  return AVERROR(EIO);
1794  }
1795 
1796  for (i = 0; i < nb_events; i++) {
1797  cle = clReleaseEvent(events[i]);
1798  if (cle != CL_SUCCESS) {
1799  av_log(hwfc, AV_LOG_ERROR, "Failed to release "
1800  "event: %d.\n", cle);
1801  }
1802  }
1803 
1804  return 0;
1805 }
1806 
1808  AVFrame *dst, const AVFrame *src)
1809 {
1810  OpenCLFramesContext *priv = hwfc->internal->priv;
1811  cl_image_format image_format;
1812  cl_image_desc image_desc;
1813  cl_int cle;
1814  size_t origin[3] = { 0, 0, 0 };
1815  size_t region[3];
1816  cl_event events[AV_NUM_DATA_POINTERS];
1817  int err, p;
1818 
1819  if (dst->format != hwfc->sw_format)
1820  return AVERROR(EINVAL);
1821 
1822  for (p = 0;; p++) {
1823  err = opencl_get_plane_format(hwfc->sw_format, p,
1824  src->width, src->height,
1825  &image_format, &image_desc);
1826  if (err < 0) {
1827  if (err == AVERROR(ENOENT))
1828  err = 0;
1829  break;
1830  }
1831 
1832  if (!dst->data[p]) {
1833  av_log(hwfc, AV_LOG_ERROR, "Plane %d missing on "
1834  "destination frame for transfer.\n", p);
1835  err = AVERROR(EINVAL);
1836  break;
1837  }
1838 
1839  region[0] = image_desc.image_width;
1840  region[1] = image_desc.image_height;
1841  region[2] = 1;
1842 
1843  cle = clEnqueueReadImage(priv->command_queue,
1844  (cl_mem)src->data[p],
1845  CL_FALSE, origin, region,
1846  dst->linesize[p], 0,
1847  dst->data[p],
1848  0, NULL, &events[p]);
1849  if (cle != CL_SUCCESS) {
1850  av_log(hwfc, AV_LOG_ERROR, "Failed to enqueue read of "
1851  "OpenCL image plane %d: %d.\n", p, cle);
1852  err = AVERROR(EIO);
1853  break;
1854  }
1855  }
1856 
1857  opencl_wait_events(hwfc, events, p);
1858 
1859  return err;
1860 }
1861 
1863  AVFrame *dst, const AVFrame *src)
1864 {
1865  OpenCLFramesContext *priv = hwfc->internal->priv;
1866  cl_image_format image_format;
1867  cl_image_desc image_desc;
1868  cl_int cle;
1869  size_t origin[3] = { 0, 0, 0 };
1870  size_t region[3];
1871  cl_event events[AV_NUM_DATA_POINTERS];
1872  int err, p;
1873 
1874  if (src->format != hwfc->sw_format)
1875  return AVERROR(EINVAL);
1876 
1877  for (p = 0;; p++) {
1878  err = opencl_get_plane_format(hwfc->sw_format, p,
1879  src->width, src->height,
1880  &image_format, &image_desc);
1881  if (err < 0) {
1882  if (err == AVERROR(ENOENT))
1883  err = 0;
1884  break;
1885  }
1886 
1887  if (!src->data[p]) {
1888  av_log(hwfc, AV_LOG_ERROR, "Plane %d missing on "
1889  "source frame for transfer.\n", p);
1890  err = AVERROR(EINVAL);
1891  break;
1892  }
1893 
1894  region[0] = image_desc.image_width;
1895  region[1] = image_desc.image_height;
1896  region[2] = 1;
1897 
1898  cle = clEnqueueWriteImage(priv->command_queue,
1899  (cl_mem)dst->data[p],
1900  CL_FALSE, origin, region,
1901  src->linesize[p], 0,
1902  src->data[p],
1903  0, NULL, &events[p]);
1904  if (cle != CL_SUCCESS) {
1905  av_log(hwfc, AV_LOG_ERROR, "Failed to enqueue write of "
1906  "OpenCL image plane %d: %d.\n", p, cle);
1907  err = AVERROR(EIO);
1908  break;
1909  }
1910  }
1911 
1912  opencl_wait_events(hwfc, events, p);
1913 
1914  return err;
1915 }
1916 
1917 typedef struct OpenCLMapping {
1918  // The mapped addresses for each plane.
1919  // The destination frame is not available when we unmap, so these
1920  // need to be stored separately.
1922 } OpenCLMapping;
1923 
1925  HWMapDescriptor *hwmap)
1926 {
1927  OpenCLFramesContext *priv = hwfc->internal->priv;
1928  OpenCLMapping *map = hwmap->priv;
1929  cl_event events[AV_NUM_DATA_POINTERS];
1930  int p, e;
1931  cl_int cle;
1932 
1933  for (p = e = 0; p < FF_ARRAY_ELEMS(map->address); p++) {
1934  if (!map->address[p])
1935  break;
1936 
1937  cle = clEnqueueUnmapMemObject(priv->command_queue,
1938  (cl_mem)hwmap->source->data[p],
1939  map->address[p],
1940  0, NULL, &events[e]);
1941  if (cle != CL_SUCCESS) {
1942  av_log(hwfc, AV_LOG_ERROR, "Failed to unmap OpenCL "
1943  "image plane %d: %d.\n", p, cle);
1944  }
1945  ++e;
1946  }
1947 
1948  opencl_wait_events(hwfc, events, e);
1949 
1950  av_free(map);
1951 }
1952 
1954  const AVFrame *src, int flags)
1955 {
1956  OpenCLFramesContext *priv = hwfc->internal->priv;
1957  cl_map_flags map_flags;
1958  cl_image_format image_format;
1959  cl_image_desc image_desc;
1960  cl_int cle;
1961  OpenCLMapping *map;
1962  size_t origin[3] = { 0, 0, 0 };
1963  size_t region[3];
1964  size_t row_pitch;
1965  cl_event events[AV_NUM_DATA_POINTERS];
1966  int err, p;
1967 
1968  av_assert0(hwfc->sw_format == dst->format);
1969 
1971  !(flags & AV_HWFRAME_MAP_READ)) {
1972  // This is mutually exclusive with the read/write flags, so
1973  // there is no way to map with read here.
1974  map_flags = CL_MAP_WRITE_INVALIDATE_REGION;
1975  } else {
1976  map_flags = 0;
1977  if (flags & AV_HWFRAME_MAP_READ)
1978  map_flags |= CL_MAP_READ;
1980  map_flags |= CL_MAP_WRITE;
1981  }
1982 
1983  map = av_mallocz(sizeof(*map));
1984  if (!map)
1985  return AVERROR(ENOMEM);
1986 
1987  for (p = 0;; p++) {
1988  err = opencl_get_plane_format(hwfc->sw_format, p,
1989  src->width, src->height,
1990  &image_format, &image_desc);
1991  if (err == AVERROR(ENOENT))
1992  break;
1993  if (err < 0)
1994  goto fail;
1995 
1996  region[0] = image_desc.image_width;
1997  region[1] = image_desc.image_height;
1998  region[2] = 1;
1999 
2000  map->address[p] =
2001  clEnqueueMapImage(priv->command_queue,
2002  (cl_mem)src->data[p],
2003  CL_FALSE, map_flags, origin, region,
2004  &row_pitch, NULL, 0, NULL,
2005  &events[p], &cle);
2006  if (!map->address[p]) {
2007  av_log(hwfc, AV_LOG_ERROR, "Failed to map OpenCL "
2008  "image plane %d: %d.\n", p, cle);
2009  err = AVERROR(EIO);
2010  goto fail;
2011  }
2012 
2013  dst->data[p] = map->address[p];
2014 
2015  av_log(hwfc, AV_LOG_DEBUG, "Map plane %d (%p -> %p).\n",
2016  p, src->data[p], dst->data[p]);
2017  }
2018 
2019  err = opencl_wait_events(hwfc, events, p);
2020  if (err < 0)
2021  goto fail;
2022 
2023  err = ff_hwframe_map_create(src->hw_frames_ctx, dst, src,
2025  if (err < 0)
2026  goto fail;
2027 
2028  dst->width = src->width;
2029  dst->height = src->height;
2030 
2031  return 0;
2032 
2033 fail:
2034  for (p = 0; p < AV_NUM_DATA_POINTERS; p++) {
2035  if (!map->address[p])
2036  break;
2037  clEnqueueUnmapMemObject(priv->command_queue,
2038  (cl_mem)src->data[p],
2039  map->address[p],
2040  0, NULL, &events[p]);
2041  }
2042  if (p > 0)
2043  opencl_wait_events(hwfc, events, p);
2044  av_freep(&map);
2045  return err;
2046 }
2047 
2048 #if HAVE_OPENCL_DRM_BEIGNET
2049 
2050 typedef struct DRMBeignetToOpenCLMapping {
2051  AVFrame *drm_frame;
2052  AVDRMFrameDescriptor *drm_desc;
2053 
2055 } DRMBeignetToOpenCLMapping;
2056 
2057 static void opencl_unmap_from_drm_beignet(AVHWFramesContext *dst_fc,
2058  HWMapDescriptor *hwmap)
2059 {
2060  DRMBeignetToOpenCLMapping *mapping = hwmap->priv;
2061  cl_int cle;
2062  int i;
2063 
2064  for (i = 0; i < mapping->frame.nb_planes; i++) {
2065  cle = clReleaseMemObject(mapping->frame.planes[i]);
2066  if (cle != CL_SUCCESS) {
2067  av_log(dst_fc, AV_LOG_ERROR, "Failed to release CL image "
2068  "of plane %d of DRM frame: %d.\n", i, cle);
2069  }
2070  }
2071 
2072  av_free(mapping);
2073 }
2074 
2075 static int opencl_map_from_drm_beignet(AVHWFramesContext *dst_fc,
2076  AVFrame *dst, const AVFrame *src,
2077  int flags)
2078 {
2079  AVOpenCLDeviceContext *hwctx = dst_fc->device_ctx->hwctx;
2080  OpenCLDeviceContext *priv = dst_fc->device_ctx->internal->priv;
2081  DRMBeignetToOpenCLMapping *mapping;
2082  const AVDRMFrameDescriptor *desc;
2083  cl_int cle;
2084  int err, i, j, p;
2085 
2086  desc = (const AVDRMFrameDescriptor*)src->data[0];
2087 
2088  mapping = av_mallocz(sizeof(*mapping));
2089  if (!mapping)
2090  return AVERROR(ENOMEM);
2091 
2092  p = 0;
2093  for (i = 0; i < desc->nb_layers; i++) {
2094  const AVDRMLayerDescriptor *layer = &desc->layers[i];
2095  for (j = 0; j < layer->nb_planes; j++) {
2096  const AVDRMPlaneDescriptor *plane = &layer->planes[j];
2097  const AVDRMObjectDescriptor *object =
2098  &desc->objects[plane->object_index];
2099 
2100  cl_import_image_info_intel image_info = {
2101  .fd = object->fd,
2102  .size = object->size,
2103  .type = CL_MEM_OBJECT_IMAGE2D,
2104  .offset = plane->offset,
2105  .row_pitch = plane->pitch,
2106  };
2107  cl_image_desc image_desc;
2108 
2109  err = opencl_get_plane_format(dst_fc->sw_format, p,
2110  src->width, src->height,
2111  &image_info.fmt,
2112  &image_desc);
2113  if (err < 0) {
2114  av_log(dst_fc, AV_LOG_ERROR, "DRM frame layer %d "
2115  "plane %d is not representable in OpenCL: %d.\n",
2116  i, j, err);
2117  goto fail;
2118  }
2119  image_info.width = image_desc.image_width;
2120  image_info.height = image_desc.image_height;
2121 
2122  mapping->frame.planes[p] =
2123  priv->clCreateImageFromFdINTEL(hwctx->context,
2124  &image_info, &cle);
2125  if (!mapping->frame.planes[p]) {
2126  av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL image "
2127  "from layer %d plane %d of DRM frame: %d.\n",
2128  i, j, cle);
2129  err = AVERROR(EIO);
2130  goto fail;
2131  }
2132 
2133  dst->data[p] = (uint8_t*)mapping->frame.planes[p];
2134  mapping->frame.nb_planes = ++p;
2135  }
2136  }
2137 
2138  err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src,
2139  &opencl_unmap_from_drm_beignet,
2140  mapping);
2141  if (err < 0)
2142  goto fail;
2143 
2144  dst->width = src->width;
2145  dst->height = src->height;
2146 
2147  return 0;
2148 
2149 fail:
2150  for (p = 0; p < mapping->frame.nb_planes; p++) {
2151  if (mapping->frame.planes[p])
2152  clReleaseMemObject(mapping->frame.planes[p]);
2153  }
2154  av_free(mapping);
2155  memset(dst->data, 0, sizeof(dst->data));
2156  return err;
2157 }
2158 
2159 #if HAVE_OPENCL_VAAPI_BEIGNET
2160 
2161 static int opencl_map_from_vaapi(AVHWFramesContext *dst_fc,
2162  AVFrame *dst, const AVFrame *src,
2163  int flags)
2164 {
2165  AVFrame *tmp;
2166  int err;
2167 
2168  tmp = av_frame_alloc();
2169  if (!tmp)
2170  return AVERROR(ENOMEM);
2171 
2172  tmp->format = AV_PIX_FMT_DRM_PRIME;
2173 
2174  err = av_hwframe_map(tmp, src, flags);
2175  if (err < 0)
2176  goto fail;
2177 
2178  err = opencl_map_from_drm_beignet(dst_fc, dst, tmp, flags);
2179  if (err < 0)
2180  goto fail;
2181 
2182  err = ff_hwframe_map_replace(dst, src);
2183 
2184 fail:
2185  av_frame_free(&tmp);
2186  return err;
2187 }
2188 
2189 #endif /* HAVE_OPENCL_VAAPI_BEIGNET */
2190 #endif /* HAVE_OPENCL_DRM_BEIGNET */
2191 
2192 static inline cl_mem_flags opencl_mem_flags_for_mapping(int map_flags)
2193 {
2194  if ((map_flags & AV_HWFRAME_MAP_READ) &&
2195  (map_flags & AV_HWFRAME_MAP_WRITE))
2196  return CL_MEM_READ_WRITE;
2197  else if (map_flags & AV_HWFRAME_MAP_READ)
2198  return CL_MEM_READ_ONLY;
2199  else if (map_flags & AV_HWFRAME_MAP_WRITE)
2200  return CL_MEM_WRITE_ONLY;
2201  else
2202  return 0;
2203 }
2204 
2205 #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
2206 
2207 static void opencl_unmap_from_qsv(AVHWFramesContext *dst_fc,
2208  HWMapDescriptor *hwmap)
2209 {
2210  AVOpenCLFrameDescriptor *desc = hwmap->priv;
2211  OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv;
2212  OpenCLFramesContext *frames_priv = dst_fc->internal->priv;
2213  cl_event event;
2214  cl_int cle;
2215  int p;
2216 
2217  av_log(dst_fc, AV_LOG_DEBUG, "Unmap QSV/VAAPI surface from OpenCL.\n");
2218 
2219  cle = device_priv->clEnqueueReleaseVA_APIMediaSurfacesINTEL(
2220  frames_priv->command_queue, desc->nb_planes, desc->planes,
2221  0, NULL, &event);
2222  if (cle != CL_SUCCESS) {
2223  av_log(dst_fc, AV_LOG_ERROR, "Failed to release surface "
2224  "handles: %d.\n", cle);
2225  }
2226 
2227  opencl_wait_events(dst_fc, &event, 1);
2228 
2229  for (p = 0; p < desc->nb_planes; p++) {
2230  cle = clReleaseMemObject(desc->planes[p]);
2231  if (cle != CL_SUCCESS) {
2232  av_log(dst_fc, AV_LOG_ERROR, "Failed to release CL "
2233  "image of plane %d of QSV/VAAPI surface: %d\n",
2234  p, cle);
2235  }
2236  }
2237 
2238  av_free(desc);
2239 }
2240 
2241 static int opencl_map_from_qsv(AVHWFramesContext *dst_fc, AVFrame *dst,
2242  const AVFrame *src, int flags)
2243 {
2244  AVHWFramesContext *src_fc =
2245  (AVHWFramesContext*)src->hw_frames_ctx->data;
2246  AVOpenCLDeviceContext *dst_dev = dst_fc->device_ctx->hwctx;
2247  OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv;
2248  OpenCLFramesContext *frames_priv = dst_fc->internal->priv;
2250  VASurfaceID va_surface;
2251  cl_mem_flags cl_flags;
2252  cl_event event;
2253  cl_int cle;
2254  int err, p;
2255 
2256 #if CONFIG_LIBMFX
2257  if (src->format == AV_PIX_FMT_QSV) {
2258  void *base_handle;
2259  mfxFrameSurface1 *mfx_surface = (mfxFrameSurface1*)src->data[3];
2260  err = ff_qsv_get_surface_base_handle(mfx_surface,
2262  &base_handle);
2263  if (err < 0)
2264  return err;
2265  va_surface = *(VASurfaceID *)base_handle;
2266  } else
2267 #endif
2268  if (src->format == AV_PIX_FMT_VAAPI) {
2269  va_surface = (VASurfaceID)(uintptr_t)src->data[3];
2270  } else {
2271  return AVERROR(ENOSYS);
2272  }
2273 
2274  cl_flags = opencl_mem_flags_for_mapping(flags);
2275  if (!cl_flags)
2276  return AVERROR(EINVAL);
2277 
2278  av_log(src_fc, AV_LOG_DEBUG, "Map QSV/VAAPI surface %#x to "
2279  "OpenCL.\n", va_surface);
2280 
2281  desc = av_mallocz(sizeof(*desc));
2282  if (!desc)
2283  return AVERROR(ENOMEM);
2284 
2285  // The cl_intel_va_api_media_sharing extension only supports NV12
2286  // surfaces, so for now there are always exactly two planes.
2287  desc->nb_planes = 2;
2288 
2289  for (p = 0; p < desc->nb_planes; p++) {
2290  desc->planes[p] =
2291  device_priv->clCreateFromVA_APIMediaSurfaceINTEL(
2292  dst_dev->context, cl_flags, &va_surface, p, &cle);
2293  if (!desc->planes[p]) {
2294  av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL "
2295  "image from plane %d of QSV/VAAPI surface "
2296  "%#x: %d.\n", p, va_surface, cle);
2297  err = AVERROR(EIO);
2298  goto fail;
2299  }
2300 
2301  dst->data[p] = (uint8_t*)desc->planes[p];
2302  }
2303 
2304  cle = device_priv->clEnqueueAcquireVA_APIMediaSurfacesINTEL(
2305  frames_priv->command_queue, desc->nb_planes, desc->planes,
2306  0, NULL, &event);
2307  if (cle != CL_SUCCESS) {
2308  av_log(dst_fc, AV_LOG_ERROR, "Failed to acquire surface "
2309  "handles: %d.\n", cle);
2310  err = AVERROR(EIO);
2311  goto fail;
2312  }
2313 
2314  err = opencl_wait_events(dst_fc, &event, 1);
2315  if (err < 0)
2316  goto fail;
2317 
2318  err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src,
2319  &opencl_unmap_from_qsv, desc);
2320  if (err < 0)
2321  goto fail;
2322 
2323  dst->width = src->width;
2324  dst->height = src->height;
2325 
2326  return 0;
2327 
2328 fail:
2329  for (p = 0; p < desc->nb_planes; p++)
2330  if (desc->planes[p])
2331  clReleaseMemObject(desc->planes[p]);
2332  av_freep(&desc);
2333  memset(dst->data, 0, sizeof(dst->data));
2334  return err;
2335 }
2336 
2337 #endif
2338 
2339 #if HAVE_OPENCL_DXVA2
2340 
2341 static void opencl_unmap_from_dxva2(AVHWFramesContext *dst_fc,
2342  HWMapDescriptor *hwmap)
2343 {
2344  AVOpenCLFrameDescriptor *desc = hwmap->priv;
2345  OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv;
2346  OpenCLFramesContext *frames_priv = dst_fc->device_ctx->internal->priv;
2347  cl_event event;
2348  cl_int cle;
2349 
2350  av_log(dst_fc, AV_LOG_DEBUG, "Unmap DXVA2 surface from OpenCL.\n");
2351 
2352  cle = device_priv->clEnqueueReleaseDX9MediaSurfacesKHR(
2353  frames_priv->command_queue, desc->nb_planes, desc->planes,
2354  0, NULL, &event);
2355  if (cle != CL_SUCCESS) {
2356  av_log(dst_fc, AV_LOG_ERROR, "Failed to release surface "
2357  "handle: %d.\n", cle);
2358  return;
2359  }
2360 
2361  opencl_wait_events(dst_fc, &event, 1);
2362 }
2363 
2364 static int opencl_map_from_dxva2(AVHWFramesContext *dst_fc, AVFrame *dst,
2365  const AVFrame *src, int flags)
2366 {
2367  AVHWFramesContext *src_fc =
2368  (AVHWFramesContext*)src->hw_frames_ctx->data;
2369  AVDXVA2FramesContext *src_hwctx = src_fc->hwctx;
2370  OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv;
2371  OpenCLFramesContext *frames_priv = dst_fc->internal->priv;
2373  cl_event event;
2374  cl_int cle;
2375  int err, i;
2376 
2377  av_log(dst_fc, AV_LOG_DEBUG, "Map DXVA2 surface %p to "
2378  "OpenCL.\n", src->data[3]);
2379 
2380  for (i = 0; i < src_hwctx->nb_surfaces; i++) {
2381  if (src_hwctx->surfaces[i] == (IDirect3DSurface9*)src->data[3])
2382  break;
2383  }
2384  if (i >= src_hwctx->nb_surfaces) {
2385  av_log(dst_fc, AV_LOG_ERROR, "Trying to map from a surface which "
2386  "is not in the mapped frames context.\n");
2387  return AVERROR(EINVAL);
2388  }
2389 
2390  desc = &frames_priv->mapped_frames[i];
2391 
2392  cle = device_priv->clEnqueueAcquireDX9MediaSurfacesKHR(
2393  frames_priv->command_queue, desc->nb_planes, desc->planes,
2394  0, NULL, &event);
2395  if (cle != CL_SUCCESS) {
2396  av_log(dst_fc, AV_LOG_ERROR, "Failed to acquire surface "
2397  "handle: %d.\n", cle);
2398  return AVERROR(EIO);
2399  }
2400 
2401  err = opencl_wait_events(dst_fc, &event, 1);
2402  if (err < 0)
2403  goto fail;
2404 
2405  for (i = 0; i < desc->nb_planes; i++)
2406  dst->data[i] = (uint8_t*)desc->planes[i];
2407 
2408  err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src,
2409  &opencl_unmap_from_dxva2, desc);
2410  if (err < 0)
2411  goto fail;
2412 
2413  dst->width = src->width;
2414  dst->height = src->height;
2415 
2416  return 0;
2417 
2418 fail:
2419  cle = device_priv->clEnqueueReleaseDX9MediaSurfacesKHR(
2420  frames_priv->command_queue, desc->nb_planes, desc->planes,
2421  0, NULL, &event);
2422  if (cle == CL_SUCCESS)
2423  opencl_wait_events(dst_fc, &event, 1);
2424  memset(dst->data, 0, sizeof(dst->data));
2425  return err;
2426 }
2427 
2428 static int opencl_frames_derive_from_dxva2(AVHWFramesContext *dst_fc,
2429  AVHWFramesContext *src_fc, int flags)
2430 {
2431  AVOpenCLDeviceContext *dst_dev = dst_fc->device_ctx->hwctx;
2432  AVDXVA2FramesContext *src_hwctx = src_fc->hwctx;
2433  OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv;
2434  OpenCLFramesContext *frames_priv = dst_fc->internal->priv;
2435  cl_mem_flags cl_flags;
2436  cl_int cle;
2437  int err, i, p, nb_planes;
2438 
2439  if (src_fc->sw_format != AV_PIX_FMT_NV12) {
2440  av_log(dst_fc, AV_LOG_ERROR, "Only NV12 textures are supported "
2441  "for DXVA2 to OpenCL mapping.\n");
2442  return AVERROR(EINVAL);
2443  }
2444  nb_planes = 2;
2445 
2446  if (src_fc->initial_pool_size == 0) {
2447  av_log(dst_fc, AV_LOG_ERROR, "Only fixed-size pools are supported "
2448  "for DXVA2 to OpenCL mapping.\n");
2449  return AVERROR(EINVAL);
2450  }
2451 
2452  cl_flags = opencl_mem_flags_for_mapping(flags);
2453  if (!cl_flags)
2454  return AVERROR(EINVAL);
2455 
2456  frames_priv->nb_mapped_frames = src_hwctx->nb_surfaces;
2457 
2458  frames_priv->mapped_frames =
2459  av_calloc(frames_priv->nb_mapped_frames,
2460  sizeof(*frames_priv->mapped_frames));
2461  if (!frames_priv->mapped_frames)
2462  return AVERROR(ENOMEM);
2463 
2464  for (i = 0; i < frames_priv->nb_mapped_frames; i++) {
2465  AVOpenCLFrameDescriptor *desc = &frames_priv->mapped_frames[i];
2466  cl_dx9_surface_info_khr surface_info = {
2467  .resource = src_hwctx->surfaces[i],
2468  .shared_handle = NULL,
2469  };
2470  desc->nb_planes = nb_planes;
2471  for (p = 0; p < nb_planes; p++) {
2472  desc->planes[p] =
2473  device_priv->clCreateFromDX9MediaSurfaceKHR(
2474  dst_dev->context, cl_flags,
2475  device_priv->dx9_media_adapter_type,
2476  &surface_info, p, &cle);
2477  if (!desc->planes[p]) {
2478  av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL "
2479  "image from plane %d of DXVA2 surface %d: %d.\n",
2480  p, i, cle);
2481  err = AVERROR(EIO);
2482  goto fail;
2483  }
2484  }
2485  }
2486 
2487  return 0;
2488 
2489 fail:
2490  for (i = 0; i < frames_priv->nb_mapped_frames; i++) {
2491  AVOpenCLFrameDescriptor *desc = &frames_priv->mapped_frames[i];
2492  for (p = 0; p < desc->nb_planes; p++) {
2493  if (desc->planes[p])
2494  clReleaseMemObject(desc->planes[p]);
2495  }
2496  }
2497  av_freep(&frames_priv->mapped_frames);
2498  frames_priv->nb_mapped_frames = 0;
2499  return err;
2500 }
2501 
2502 #endif
2503 
2504 #if HAVE_OPENCL_D3D11
2505 
2506 static void opencl_unmap_from_d3d11(AVHWFramesContext *dst_fc,
2507  HWMapDescriptor *hwmap)
2508 {
2509  AVOpenCLFrameDescriptor *desc = hwmap->priv;
2510  OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv;
2511  OpenCLFramesContext *frames_priv = dst_fc->device_ctx->internal->priv;
2512  cl_event event;
2513  cl_int cle;
2514 
2515  cle = device_priv->clEnqueueReleaseD3D11ObjectsKHR(
2516  frames_priv->command_queue, desc->nb_planes, desc->planes,
2517  0, NULL, &event);
2518  if (cle != CL_SUCCESS) {
2519  av_log(dst_fc, AV_LOG_ERROR, "Failed to release surface "
2520  "handle: %d.\n", cle);
2521  }
2522 
2523  opencl_wait_events(dst_fc, &event, 1);
2524 }
2525 
2526 static int opencl_map_from_d3d11(AVHWFramesContext *dst_fc, AVFrame *dst,
2527  const AVFrame *src, int flags)
2528 {
2529  OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv;
2530  OpenCLFramesContext *frames_priv = dst_fc->internal->priv;
2532  cl_event event;
2533  cl_int cle;
2534  int err, index, i;
2535 
2536  index = (intptr_t)src->data[1];
2537  if (index >= frames_priv->nb_mapped_frames) {
2538  av_log(dst_fc, AV_LOG_ERROR, "Texture array index out of range for "
2539  "mapping: %d >= %d.\n", index, frames_priv->nb_mapped_frames);
2540  return AVERROR(EINVAL);
2541  }
2542 
2543  av_log(dst_fc, AV_LOG_DEBUG, "Map D3D11 texture %d to OpenCL.\n",
2544  index);
2545 
2546  desc = &frames_priv->mapped_frames[index];
2547 
2548  cle = device_priv->clEnqueueAcquireD3D11ObjectsKHR(
2549  frames_priv->command_queue, desc->nb_planes, desc->planes,
2550  0, NULL, &event);
2551  if (cle != CL_SUCCESS) {
2552  av_log(dst_fc, AV_LOG_ERROR, "Failed to acquire surface "
2553  "handle: %d.\n", cle);
2554  return AVERROR(EIO);
2555  }
2556 
2557  err = opencl_wait_events(dst_fc, &event, 1);
2558  if (err < 0)
2559  goto fail;
2560 
2561  for (i = 0; i < desc->nb_planes; i++)
2562  dst->data[i] = (uint8_t*)desc->planes[i];
2563 
2564  err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src,
2565  &opencl_unmap_from_d3d11, desc);
2566  if (err < 0)
2567  goto fail;
2568 
2569  dst->width = src->width;
2570  dst->height = src->height;
2571 
2572  return 0;
2573 
2574 fail:
2575  cle = device_priv->clEnqueueReleaseD3D11ObjectsKHR(
2576  frames_priv->command_queue, desc->nb_planes, desc->planes,
2577  0, NULL, &event);
2578  if (cle == CL_SUCCESS)
2579  opencl_wait_events(dst_fc, &event, 1);
2580  memset(dst->data, 0, sizeof(dst->data));
2581  return err;
2582 }
2583 
2584 static int opencl_frames_derive_from_d3d11(AVHWFramesContext *dst_fc,
2585  AVHWFramesContext *src_fc, int flags)
2586 {
2587  AVOpenCLDeviceContext *dst_dev = dst_fc->device_ctx->hwctx;
2588  AVD3D11VAFramesContext *src_hwctx = src_fc->hwctx;
2589  OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv;
2590  OpenCLFramesContext *frames_priv = dst_fc->internal->priv;
2591  cl_mem_flags cl_flags;
2592  cl_int cle;
2593  int err, i, p, nb_planes;
2594 
2595  if (src_fc->sw_format != AV_PIX_FMT_NV12) {
2596  av_log(dst_fc, AV_LOG_ERROR, "Only NV12 textures are supported "
2597  "for D3D11 to OpenCL mapping.\n");
2598  return AVERROR(EINVAL);
2599  }
2600  nb_planes = 2;
2601 
2602  if (src_fc->initial_pool_size == 0) {
2603  av_log(dst_fc, AV_LOG_ERROR, "Only fixed-size pools are supported "
2604  "for D3D11 to OpenCL mapping.\n");
2605  return AVERROR(EINVAL);
2606  }
2607 
2608  cl_flags = opencl_mem_flags_for_mapping(flags);
2609  if (!cl_flags)
2610  return AVERROR(EINVAL);
2611 
2612  frames_priv->nb_mapped_frames = src_fc->initial_pool_size;
2613 
2614  frames_priv->mapped_frames =
2615  av_calloc(frames_priv->nb_mapped_frames,
2616  sizeof(*frames_priv->mapped_frames));
2617  if (!frames_priv->mapped_frames)
2618  return AVERROR(ENOMEM);
2619 
2620  for (i = 0; i < frames_priv->nb_mapped_frames; i++) {
2621  AVOpenCLFrameDescriptor *desc = &frames_priv->mapped_frames[i];
2622  desc->nb_planes = nb_planes;
2623  for (p = 0; p < nb_planes; p++) {
2624  UINT subresource = 2 * i + p;
2625 
2626  desc->planes[p] =
2627  device_priv->clCreateFromD3D11Texture2DKHR(
2628  dst_dev->context, cl_flags, src_hwctx->texture,
2629  subresource, &cle);
2630  if (!desc->planes[p]) {
2631  av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL "
2632  "image from plane %d of D3D texture "
2633  "index %d (subresource %u): %d.\n",
2634  p, i, (unsigned int)subresource, cle);
2635  err = AVERROR(EIO);
2636  goto fail;
2637  }
2638  }
2639  }
2640 
2641  return 0;
2642 
2643 fail:
2644  for (i = 0; i < frames_priv->nb_mapped_frames; i++) {
2645  AVOpenCLFrameDescriptor *desc = &frames_priv->mapped_frames[i];
2646  for (p = 0; p < desc->nb_planes; p++) {
2647  if (desc->planes[p])
2648  clReleaseMemObject(desc->planes[p]);
2649  }
2650  }
2651  av_freep(&frames_priv->mapped_frames);
2652  frames_priv->nb_mapped_frames = 0;
2653  return err;
2654 }
2655 
2656 #endif
2657 
2658 #if HAVE_OPENCL_DRM_ARM
2659 
2660 typedef struct DRMARMtoOpenCLMapping {
2661  int nb_objects;
2662  cl_mem object_buffers[AV_DRM_MAX_PLANES];
2663  int nb_planes;
2664  cl_mem plane_images[AV_DRM_MAX_PLANES];
2665 } DRMARMtoOpenCLMapping;
2666 
2667 static void opencl_unmap_from_drm_arm(AVHWFramesContext *dst_fc,
2668  HWMapDescriptor *hwmap)
2669 {
2670  DRMARMtoOpenCLMapping *mapping = hwmap->priv;
2671  int i;
2672 
2673  for (i = 0; i < mapping->nb_planes; i++)
2674  clReleaseMemObject(mapping->plane_images[i]);
2675 
2676  for (i = 0; i < mapping->nb_objects; i++)
2677  clReleaseMemObject(mapping->object_buffers[i]);
2678 
2679  av_free(mapping);
2680 }
2681 
2682 static int opencl_map_from_drm_arm(AVHWFramesContext *dst_fc, AVFrame *dst,
2683  const AVFrame *src, int flags)
2684 {
2685  AVHWFramesContext *src_fc =
2686  (AVHWFramesContext*)src->hw_frames_ctx->data;
2687  AVOpenCLDeviceContext *dst_dev = dst_fc->device_ctx->hwctx;
2688  const AVDRMFrameDescriptor *desc;
2689  DRMARMtoOpenCLMapping *mapping = NULL;
2690  cl_mem_flags cl_flags;
2691  const cl_import_properties_arm props[3] = {
2692  CL_IMPORT_TYPE_ARM, CL_IMPORT_TYPE_DMA_BUF_ARM, 0,
2693  };
2694  cl_int cle;
2695  int err, i, j;
2696 
2697  desc = (const AVDRMFrameDescriptor*)src->data[0];
2698 
2699  cl_flags = opencl_mem_flags_for_mapping(flags);
2700  if (!cl_flags)
2701  return AVERROR(EINVAL);
2702 
2703  mapping = av_mallocz(sizeof(*mapping));
2704  if (!mapping)
2705  return AVERROR(ENOMEM);
2706 
2707  mapping->nb_objects = desc->nb_objects;
2708  for (i = 0; i < desc->nb_objects; i++) {
2709  int fd = desc->objects[i].fd;
2710 
2711  av_log(dst_fc, AV_LOG_DEBUG, "Map DRM PRIME fd %d to OpenCL.\n", fd);
2712 
2713  if (desc->objects[i].format_modifier) {
2714  av_log(dst_fc, AV_LOG_DEBUG, "Warning: object %d fd %d has "
2715  "nonzero format modifier %"PRId64", result may not "
2716  "be as expected.\n", i, fd,
2717  desc->objects[i].format_modifier);
2718  }
2719 
2720  mapping->object_buffers[i] =
2721  clImportMemoryARM(dst_dev->context, cl_flags, props,
2722  &fd, desc->objects[i].size, &cle);
2723  if (!mapping->object_buffers[i]) {
2724  av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL buffer "
2725  "from object %d (fd %d, size %"SIZE_SPECIFIER") of DRM frame: %d.\n",
2726  i, fd, desc->objects[i].size, cle);
2727  err = AVERROR(EIO);
2728  goto fail;
2729  }
2730  }
2731 
2732  mapping->nb_planes = 0;
2733  for (i = 0; i < desc->nb_layers; i++) {
2734  const AVDRMLayerDescriptor *layer = &desc->layers[i];
2735 
2736  for (j = 0; j < layer->nb_planes; j++) {
2737  const AVDRMPlaneDescriptor *plane = &layer->planes[j];
2738  cl_mem plane_buffer;
2739  cl_image_format image_format;
2740  cl_image_desc image_desc;
2741  cl_buffer_region region;
2742  int p = mapping->nb_planes;
2743 
2744  err = opencl_get_plane_format(src_fc->sw_format, p,
2745  src_fc->width, src_fc->height,
2746  &image_format, &image_desc);
2747  if (err < 0) {
2748  av_log(dst_fc, AV_LOG_ERROR, "Invalid plane %d (DRM "
2749  "layer %d plane %d): %d.\n", p, i, j, err);
2750  goto fail;
2751  }
2752 
2753  region.origin = plane->offset;
2754  region.size = image_desc.image_row_pitch *
2755  image_desc.image_height;
2756 
2757  plane_buffer =
2758  clCreateSubBuffer(mapping->object_buffers[plane->object_index],
2759  cl_flags,
2760  CL_BUFFER_CREATE_TYPE_REGION,
2761  &region, &cle);
2762  if (!plane_buffer) {
2763  av_log(dst_fc, AV_LOG_ERROR, "Failed to create sub-buffer "
2764  "for plane %d: %d.\n", p, cle);
2765  err = AVERROR(EIO);
2766  goto fail;
2767  }
2768 
2769  image_desc.buffer = plane_buffer;
2770 
2771  mapping->plane_images[p] =
2772  clCreateImage(dst_dev->context, cl_flags,
2773  &image_format, &image_desc, NULL, &cle);
2774 
2775  // Unreference the sub-buffer immediately - we don't need it
2776  // directly and a reference is held by the image.
2777  clReleaseMemObject(plane_buffer);
2778 
2779  if (!mapping->plane_images[p]) {
2780  av_log(dst_fc, AV_LOG_ERROR, "Failed to create image "
2781  "for plane %d: %d.\n", p, cle);
2782  err = AVERROR(EIO);
2783  goto fail;
2784  }
2785 
2786  ++mapping->nb_planes;
2787  }
2788  }
2789 
2790  for (i = 0; i < mapping->nb_planes; i++)
2791  dst->data[i] = (uint8_t*)mapping->plane_images[i];
2792 
2793  err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src,
2794  &opencl_unmap_from_drm_arm, mapping);
2795  if (err < 0)
2796  goto fail;
2797 
2798  dst->width = src->width;
2799  dst->height = src->height;
2800 
2801  return 0;
2802 
2803 fail:
2804  for (i = 0; i < mapping->nb_planes; i++) {
2805  clReleaseMemObject(mapping->plane_images[i]);
2806  }
2807  for (i = 0; i < mapping->nb_objects; i++) {
2808  if (mapping->object_buffers[i])
2809  clReleaseMemObject(mapping->object_buffers[i]);
2810  }
2811  av_free(mapping);
2812  memset(dst->data, 0, sizeof(dst->data));
2813  return err;
2814 }
2815 
2816 #endif
2817 
2819  const AVFrame *src, int flags)
2820 {
2821  av_assert0(src->format == AV_PIX_FMT_OPENCL);
2822  if (hwfc->sw_format != dst->format)
2823  return AVERROR(ENOSYS);
2824  return opencl_map_frame(hwfc, dst, src, flags);
2825 }
2826 
2827 static int opencl_map_to(AVHWFramesContext *hwfc, AVFrame *dst,
2828  const AVFrame *src, int flags)
2829 {
2832  switch (src->format) {
2833 #if HAVE_OPENCL_DRM_BEIGNET
2834  case AV_PIX_FMT_DRM_PRIME:
2835  if (priv->beignet_drm_mapping_usable)
2836  return opencl_map_from_drm_beignet(hwfc, dst, src, flags);
2837 #endif
2838 #if HAVE_OPENCL_VAAPI_BEIGNET
2839  case AV_PIX_FMT_VAAPI:
2840  if (priv->beignet_drm_mapping_usable)
2841  return opencl_map_from_vaapi(hwfc, dst, src, flags);
2842 #endif
2843 #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
2844  case AV_PIX_FMT_QSV:
2845  case AV_PIX_FMT_VAAPI:
2846  if (priv->qsv_mapping_usable)
2847  return opencl_map_from_qsv(hwfc, dst, src, flags);
2848 #endif
2849 #if HAVE_OPENCL_DXVA2
2850  case AV_PIX_FMT_DXVA2_VLD:
2851  if (priv->dxva2_mapping_usable)
2852  return opencl_map_from_dxva2(hwfc, dst, src, flags);
2853 #endif
2854 #if HAVE_OPENCL_D3D11
2855  case AV_PIX_FMT_D3D11:
2856  if (priv->d3d11_mapping_usable)
2857  return opencl_map_from_d3d11(hwfc, dst, src, flags);
2858 #endif
2859 #if HAVE_OPENCL_DRM_ARM
2860  case AV_PIX_FMT_DRM_PRIME:
2861  if (priv->drm_arm_mapping_usable)
2862  return opencl_map_from_drm_arm(hwfc, dst, src, flags);
2863 #endif
2864  }
2865  return AVERROR(ENOSYS);
2866 }
2867 
2869  AVHWFramesContext *src_fc, int flags)
2870 {
2872  switch (src_fc->device_ctx->type) {
2873 #if HAVE_OPENCL_DRM_BEIGNET
2874  case AV_HWDEVICE_TYPE_DRM:
2875  if (!priv->beignet_drm_mapping_usable)
2876  return AVERROR(ENOSYS);
2877  break;
2878 #endif
2879 #if HAVE_OPENCL_VAAPI_BEIGNET
2881  if (!priv->beignet_drm_mapping_usable)
2882  return AVERROR(ENOSYS);
2883  break;
2884 #endif
2885 #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
2886  case AV_HWDEVICE_TYPE_QSV:
2888  if (!priv->qsv_mapping_usable)
2889  return AVERROR(ENOSYS);
2890  break;
2891 #endif
2892 #if HAVE_OPENCL_DXVA2
2894  if (!priv->dxva2_mapping_usable)
2895  return AVERROR(ENOSYS);
2896  {
2897  int err;
2898  err = opencl_frames_derive_from_dxva2(dst_fc, src_fc, flags);
2899  if (err < 0)
2900  return err;
2901  }
2902  break;
2903 #endif
2904 #if HAVE_OPENCL_D3D11
2906  if (!priv->d3d11_mapping_usable)
2907  return AVERROR(ENOSYS);
2908  {
2909  int err;
2910  err = opencl_frames_derive_from_d3d11(dst_fc, src_fc, flags);
2911  if (err < 0)
2912  return err;
2913  }
2914  break;
2915 #endif
2916 #if HAVE_OPENCL_DRM_ARM
2917  case AV_HWDEVICE_TYPE_DRM:
2918  if (!priv->drm_arm_mapping_usable)
2919  return AVERROR(ENOSYS);
2920  break;
2921 #endif
2922  default:
2923  return AVERROR(ENOSYS);
2924  }
2925  return opencl_frames_init_command_queue(dst_fc);
2926 }
2927 
2930  .name = "OpenCL",
2931 
2932  .device_hwctx_size = sizeof(AVOpenCLDeviceContext),
2933  .device_priv_size = sizeof(OpenCLDeviceContext),
2934  .frames_hwctx_size = sizeof(AVOpenCLFramesContext),
2935  .frames_priv_size = sizeof(OpenCLFramesContext),
2936 
2937  .device_create = &opencl_device_create,
2938  .device_derive = &opencl_device_derive,
2939  .device_init = &opencl_device_init,
2940  .device_uninit = &opencl_device_uninit,
2941 
2942  .frames_get_constraints = &opencl_frames_get_constraints,
2943  .frames_init = &opencl_frames_init,
2944  .frames_uninit = &opencl_frames_uninit,
2945  .frames_get_buffer = &opencl_get_buffer,
2946 
2947  .transfer_get_formats = &opencl_transfer_get_formats,
2948  .transfer_data_to = &opencl_transfer_data_to,
2949  .transfer_data_from = &opencl_transfer_data_from,
2950 
2951  .map_from = &opencl_map_from,
2952  .map_to = &opencl_map_to,
2953  .frames_derive_to = &opencl_frames_derive_to,
2954 
2955  .pix_fmts = (const enum AVPixelFormat[]) {
2958  },
2959 };
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:2928
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
opencl_platform_params
static struct @307 opencl_platform_params[]
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
AV_DRM_MAX_PLANES
@ AV_DRM_MAX_PLANES
The maximum number of layers/planes in a DRM frame.
Definition: hwcontext_drm.h:39
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:86
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:2662
OpenCLMapping
Definition: hwcontext_opencl.c:1917
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:111
type
cl_device_type type
Definition: hwcontext_opencl.c:198
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:325
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:397
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:320
av_hwframe_map
int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags)
Map a hardware frame.
Definition: hwcontext.c:790
opencl_map_from
static int opencl_map_from(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
Definition: hwcontext_opencl.c:2818
data
const char data[16]
Definition: mxf.c:143
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:30
ff_hwframe_map_create
int ff_hwframe_map_create(AVBufferRef *hwframe_ref, AVFrame *dst, const AVFrame *src, void(*unmap)(AVHWFramesContext *ctx, HWMapDescriptor *hwmap), void *priv)
Definition: hwcontext.c:738
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:346
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:370
AVOpenCLDeviceContext
OpenCL device details.
Definition: hwcontext_opencl.h:63
opencl_map_to
static int opencl_map_to(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
Definition: hwcontext_opencl.c:2827
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:130
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:1701
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:1953
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:99
OpenCLMapping::address
void * address[AV_NUM_DATA_POINTERS]
Definition: hwcontext_opencl.c:1921
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
opencl_device_types
static struct @309 opencl_device_types[]
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:40
av_buffer_pool_get
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
Definition: buffer.c:387
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
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:80
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:1481
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:32
CL_FUNC
#define CL_FUNC(name, desc)
pix_fmt
static enum AVPixelFormat pix_fmt
Definition: demuxing_decoding.c:41
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:1766
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:1714
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
opencl_device_params
static struct @308 opencl_device_params[]
AVHWDeviceInternal::priv
void * priv
Definition: hwcontext_internal.h:105
AV_HWDEVICE_TYPE_DXVA2
@ AV_HWDEVICE_TYPE_DXVA2
Definition: hwcontext.h:32
AV_HWFRAME_MAP_WRITE
@ AV_HWFRAME_MAP_WRITE
The mapping must be writeable.
Definition: hwcontext.h:528
opencl_transfer_data_from
static int opencl_transfer_data_from(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src)
Definition: hwcontext_opencl.c:1807
OpenCLDeviceSelector
Definition: hwcontext_opencl.c:469
AV_PIX_FMT_OPENCL
@ AV_PIX_FMT_OPENCL
Hardware surfaces for OpenCL.
Definition: pixfmt.h:327
AV_PIX_FMT_QSV
@ AV_PIX_FMT_QSV
HW acceleration through QSV, data[3] contains a pointer to the mfxFrameSurface1 structure.
Definition: pixfmt.h:212
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
opencl_wait_events
static int opencl_wait_events(AVHWFramesContext *hwfc, cl_event *events, int nb_events)
Definition: hwcontext_opencl.c:1783
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:326
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:412
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:123
AVD3D11VAFramesContext::texture
ID3D11Texture2D * texture
The canonical texture used for pool allocation.
Definition: hwcontext_d3d11va.h:152
height
#define height
AVOpenCLDeviceContext::context
cl_context context
The OpenCL context which will contain all operations and frames on this device.
Definition: hwcontext_opencl.h:74
av_reallocp_array
int av_reallocp_array(void *ptr, size_t nmemb, size_t size)
Allocate, reallocate, or free an array through a pointer to a pointer.
Definition: mem.c:233
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:305
av_dict_free
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition: dict.c:203
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
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
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:271
AV_HWFRAME_MAP_READ
@ AV_HWFRAME_MAP_READ
The mapping must be readable.
Definition: hwcontext.h:524
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:264
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:946
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:272
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:195
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:659
AV_HWDEVICE_TYPE_QSV
@ AV_HWDEVICE_TYPE_QSV
Definition: hwcontext.h:33
AVFrame::height
int height
Definition: frame.h:397
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_frames_init_command_queue
static int opencl_frames_init_command_queue(AVHWFramesContext *hwfc)
Definition: hwcontext_opencl.c:1682
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:1626
mem.h
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
opencl_transfer_data_to
static int opencl_transfer_data_to(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src)
Definition: hwcontext_opencl.c:1862
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:79
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:70
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:1745
AVOpenCLFramesContext
OpenCL-specific data associated with a frame pool.
Definition: hwcontext_opencl.h:89
d
d
Definition: ffmpeg_filter.c:153
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:370
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:1608
opencl_unmap_frame
static void opencl_unmap_frame(AVHWFramesContext *hwfc, HWMapDescriptor *hwmap)
Definition: hwcontext_opencl.c:1924
ID3D11Device
void ID3D11Device
Definition: nvenc.h:28
AVVAAPIDeviceContext
VAAPI connection details.
Definition: hwcontext_vaapi.h:68
AVDictionaryEntry::value
char * value
Definition: dict.h:81
avstring.h
opencl_frames_derive_to
static int opencl_frames_derive_to(AVHWFramesContext *dst_fc, AVHWFramesContext *src_fc, int flags)
Definition: hwcontext_opencl.c:2868
int
int
Definition: ffmpeg_filter.c:153
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:2192
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:2582
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