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