2 * This file is part of FFmpeg.
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.
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.
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
19 #define CL_USE_DEPRECATED_OPENCL_1_2_APIS
28 #include "hwcontext.h"
29 #include "hwcontext_internal.h"
30 #include "hwcontext_opencl.h"
34 #if HAVE_OPENCL_VAAPI_BEIGNET
37 #include <va/va_drmcommon.h>
38 #include <CL/cl_intel.h>
39 #include "hwcontext_vaapi.h"
42 #if HAVE_OPENCL_DRM_BEIGNET
44 #include <CL/cl_intel.h>
45 #include "hwcontext_drm.h"
48 #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
50 #include <mfx/mfxstructures.h>
53 #include <CL/cl_va_api_media_sharing_intel.h>
54 #include "hwcontext_vaapi.h"
59 #include <CL/cl_dx9_media_sharing.h>
61 #include "hwcontext_dxva2.h"
65 #include <CL/cl_d3d11.h>
66 #include "hwcontext_d3d11va.h"
69 #if HAVE_OPENCL_DRM_ARM
70 #include <CL/cl_ext.h>
71 #include <drm_fourcc.h>
72 #include "hwcontext_drm.h"
75 #if HAVE_OPENCL_VAAPI_INTEL_MEDIA && CONFIG_LIBMFX
76 extern int ff_qsv_get_surface_base_handle(mfxFrameSurface1
*surf
,
77 enum AVHWDeviceType base_dev_typ
,
82 typedef struct OpenCLDeviceContext
{
83 // Default command queue to use for transfer/mapping operations on
84 // the device. If the user supplies one, this is a reference to it.
85 // Otherwise, it is newly-created.
86 cl_command_queue command_queue
;
88 // The platform the context exists on. This is needed to query and
89 // retrieve extension functions.
90 cl_platform_id platform_id
;
92 // Platform/device-specific functions.
93 #if HAVE_OPENCL_DRM_BEIGNET
94 int beignet_drm_mapping_usable
;
95 clCreateImageFromFdINTEL_fn clCreateImageFromFdINTEL
;
98 #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
99 int qsv_mapping_usable
;
100 clCreateFromVA_APIMediaSurfaceINTEL_fn
101 clCreateFromVA_APIMediaSurfaceINTEL
;
102 clEnqueueAcquireVA_APIMediaSurfacesINTEL_fn
103 clEnqueueAcquireVA_APIMediaSurfacesINTEL
;
104 clEnqueueReleaseVA_APIMediaSurfacesINTEL_fn
105 clEnqueueReleaseVA_APIMediaSurfacesINTEL
;
108 #if HAVE_OPENCL_DXVA2
109 int dxva2_mapping_usable
;
110 cl_dx9_media_adapter_type_khr dx9_media_adapter_type
;
112 clCreateFromDX9MediaSurfaceKHR_fn
113 clCreateFromDX9MediaSurfaceKHR
;
114 clEnqueueAcquireDX9MediaSurfacesKHR_fn
115 clEnqueueAcquireDX9MediaSurfacesKHR
;
116 clEnqueueReleaseDX9MediaSurfacesKHR_fn
117 clEnqueueReleaseDX9MediaSurfacesKHR
;
120 #if HAVE_OPENCL_D3D11
121 int d3d11_mapping_usable
;
122 clCreateFromD3D11Texture2DKHR_fn
123 clCreateFromD3D11Texture2DKHR
;
124 clEnqueueAcquireD3D11ObjectsKHR_fn
125 clEnqueueAcquireD3D11ObjectsKHR
;
126 clEnqueueReleaseD3D11ObjectsKHR_fn
127 clEnqueueReleaseD3D11ObjectsKHR
;
130 #if HAVE_OPENCL_DRM_ARM
131 int drm_arm_mapping_usable
;
133 } OpenCLDeviceContext
;
135 typedef struct OpenCLFramesContext
{
136 // Command queue used for transfer/mapping operations on this frames
137 // context. If the user supplies one, this is a reference to it.
138 // Otherwise, it is a reference to the default command queue for the
140 cl_command_queue command_queue
;
142 #if HAVE_OPENCL_DXVA2 || HAVE_OPENCL_D3D11
143 // For mapping APIs which have separate creation and acquire/release
144 // steps, this stores the OpenCL memory objects corresponding to each
146 int nb_mapped_frames
;
147 AVOpenCLFrameDescriptor
*mapped_frames
;
149 } OpenCLFramesContext
;
152 static void CL_CALLBACK
opencl_error_callback(const char *errinfo
,
153 const void *private_info
,
157 AVHWDeviceContext
*ctx
= user_data
;
158 av_log(ctx
, AV_LOG_ERROR
, "OpenCL error: %s\n", errinfo
);
161 static void opencl_device_free(AVHWDeviceContext
*hwdev
)
163 AVOpenCLDeviceContext
*hwctx
= hwdev
->hwctx
;
166 cle
= clReleaseContext(hwctx
->context
);
167 if (cle
!= CL_SUCCESS
) {
168 av_log(hwdev
, AV_LOG_ERROR
, "Failed to release OpenCL "
169 "context: %d.\n", cle
);
175 cl_platform_info name
;
176 } opencl_platform_params
[] = {
177 { "platform_profile", CL_PLATFORM_PROFILE
},
178 { "platform_version", CL_PLATFORM_VERSION
},
179 { "platform_name", CL_PLATFORM_NAME
},
180 { "platform_vendor", CL_PLATFORM_VENDOR
},
181 { "platform_extensions", CL_PLATFORM_EXTENSIONS
},
187 } opencl_device_params
[] = {
188 { "device_name", CL_DEVICE_NAME
},
189 { "device_vendor", CL_DEVICE_VENDOR
},
190 { "driver_version", CL_DRIVER_VERSION
},
191 { "device_version", CL_DEVICE_VERSION
},
192 { "device_profile", CL_DEVICE_PROFILE
},
193 { "device_extensions", CL_DEVICE_EXTENSIONS
},
199 } opencl_device_types
[] = {
200 { "cpu", CL_DEVICE_TYPE_CPU
},
201 { "gpu", CL_DEVICE_TYPE_GPU
},
202 { "accelerator", CL_DEVICE_TYPE_ACCELERATOR
},
203 { "custom", CL_DEVICE_TYPE_CUSTOM
},
204 { "default", CL_DEVICE_TYPE_DEFAULT
},
205 { "all", CL_DEVICE_TYPE_ALL
},
208 static char *opencl_get_platform_string(cl_platform_id platform_id
,
209 cl_platform_info key
)
214 cle
= clGetPlatformInfo(platform_id
, key
, 0, NULL
, &size
);
215 if (cle
!= CL_SUCCESS
)
217 str
= av_malloc(size
);
220 cle
= clGetPlatformInfo(platform_id
, key
, size
, str
, &size
);
221 if (cle
!= CL_SUCCESS
) {
225 av_assert0(strlen(str
) + 1 == size
);
229 static char *opencl_get_device_string(cl_device_id device_id
,
235 cle
= clGetDeviceInfo(device_id
, key
, 0, NULL
, &size
);
236 if (cle
!= CL_SUCCESS
)
238 str
= av_malloc(size
);
241 cle
= clGetDeviceInfo(device_id
, key
, size
, str
, &size
);
242 if (cle
!= CL_SUCCESS
) {
246 av_assert0(strlen(str
) + 1== size
);
250 static int opencl_check_platform_extension(cl_platform_id platform_id
,
255 str
= opencl_get_platform_string(platform_id
,
256 CL_PLATFORM_EXTENSIONS
);
257 if (str
&& strstr(str
, name
))
263 static int opencl_check_device_extension(cl_device_id device_id
,
268 str
= opencl_get_device_string(device_id
,
269 CL_DEVICE_EXTENSIONS
);
270 if (str
&& strstr(str
, name
))
276 static av_unused
int opencl_check_extension(AVHWDeviceContext
*hwdev
,
279 AVOpenCLDeviceContext
*hwctx
= hwdev
->hwctx
;
280 OpenCLDeviceContext
*priv
= hwdev
->internal
->priv
;
282 if (opencl_check_platform_extension(priv
->platform_id
, name
)) {
283 av_log(hwdev
, AV_LOG_DEBUG
,
284 "%s found as platform extension.\n", name
);
288 if (opencl_check_device_extension(hwctx
->device_id
, name
)) {
289 av_log(hwdev
, AV_LOG_DEBUG
,
290 "%s found as device extension.\n", name
);
297 static int opencl_enumerate_platforms(AVHWDeviceContext
*hwdev
,
298 cl_uint
*nb_platforms
,
299 cl_platform_id
**platforms
,
304 cle
= clGetPlatformIDs(0, NULL
, nb_platforms
);
305 if (cle
!= CL_SUCCESS
) {
306 av_log(hwdev
, AV_LOG_ERROR
, "Failed to get number of "
307 "OpenCL platforms: %d.\n", cle
);
308 return AVERROR(ENODEV
);
310 av_log(hwdev
, AV_LOG_DEBUG
, "%u OpenCL platforms found.\n",
313 *platforms
= av_malloc_array(*nb_platforms
, sizeof(**platforms
));
315 return AVERROR(ENOMEM
);
317 cle
= clGetPlatformIDs(*nb_platforms
, *platforms
, NULL
);
318 if (cle
!= CL_SUCCESS
) {
319 av_log(hwdev
, AV_LOG_ERROR
, "Failed to get list of OpenCL "
320 "platforms: %d.\n", cle
);
322 return AVERROR(ENODEV
);
328 static int opencl_filter_platform(AVHWDeviceContext
*hwdev
,
329 cl_platform_id platform_id
,
330 const char *platform_name
,
333 AVDictionary
*opts
= context
;
334 const AVDictionaryEntry
*param
;
338 for (i
= 0; i
< FF_ARRAY_ELEMS(opencl_platform_params
); i
++) {
339 param
= av_dict_get(opts
, opencl_platform_params
[i
].key
,
344 str
= opencl_get_platform_string(platform_id
,
345 opencl_platform_params
[i
].name
);
347 av_log(hwdev
, AV_LOG_ERROR
, "Failed to query %s "
348 "of platform \"%s\".\n",
349 opencl_platform_params
[i
].key
, platform_name
);
350 return AVERROR_UNKNOWN
;
352 if (!av_stristr(str
, param
->value
)) {
353 av_log(hwdev
, AV_LOG_DEBUG
, "%s does not match (\"%s\").\n",
363 static int opencl_enumerate_devices(AVHWDeviceContext
*hwdev
,
364 cl_platform_id platform_id
,
365 const char *platform_name
,
367 cl_device_id
**devices
,
372 cle
= clGetDeviceIDs(platform_id
, CL_DEVICE_TYPE_ALL
,
373 0, NULL
, nb_devices
);
374 if (cle
== CL_DEVICE_NOT_FOUND
) {
375 av_log(hwdev
, AV_LOG_DEBUG
, "No devices found "
376 "on platform \"%s\".\n", platform_name
);
379 } else if (cle
!= CL_SUCCESS
) {
380 av_log(hwdev
, AV_LOG_ERROR
, "Failed to get number of devices "
381 "on platform \"%s\": %d.\n", platform_name
, cle
);
382 return AVERROR(ENODEV
);
384 av_log(hwdev
, AV_LOG_DEBUG
, "%u OpenCL devices found on "
385 "platform \"%s\".\n", *nb_devices
, platform_name
);
387 *devices
= av_malloc_array(*nb_devices
, sizeof(**devices
));
389 return AVERROR(ENOMEM
);
391 cle
= clGetDeviceIDs(platform_id
, CL_DEVICE_TYPE_ALL
,
392 *nb_devices
, *devices
, NULL
);
393 if (cle
!= CL_SUCCESS
) {
394 av_log(hwdev
, AV_LOG_ERROR
, "Failed to get list of devices "
395 "on platform \"%s\": %d.\n", platform_name
, cle
);
397 return AVERROR(ENODEV
);
403 static int opencl_filter_device(AVHWDeviceContext
*hwdev
,
404 cl_device_id device_id
,
405 const char *device_name
,
408 AVDictionary
*opts
= context
;
409 const AVDictionaryEntry
*param
;
413 param
= av_dict_get(opts
, "device_type", NULL
, 0);
415 cl_device_type match_type
= 0, device_type
;
418 for (i
= 0; i
< FF_ARRAY_ELEMS(opencl_device_types
); i
++) {
419 if (!strcmp(opencl_device_types
[i
].key
, param
->value
)) {
420 match_type
= opencl_device_types
[i
].type
;
425 av_log(hwdev
, AV_LOG_ERROR
, "Unknown device type %s.\n",
427 return AVERROR(EINVAL
);
430 cle
= clGetDeviceInfo(device_id
, CL_DEVICE_TYPE
,
431 sizeof(device_type
), &device_type
, NULL
);
432 if (cle
!= CL_SUCCESS
) {
433 av_log(hwdev
, AV_LOG_ERROR
, "Failed to query device type "
434 "of device \"%s\".\n", device_name
);
435 return AVERROR_UNKNOWN
;
438 if (!(device_type
& match_type
)) {
439 av_log(hwdev
, AV_LOG_DEBUG
, "device_type does not match.\n");
444 for (i
= 0; i
< FF_ARRAY_ELEMS(opencl_device_params
); i
++) {
445 param
= av_dict_get(opts
, opencl_device_params
[i
].key
,
450 str
= opencl_get_device_string(device_id
,
451 opencl_device_params
[i
].name
);
453 av_log(hwdev
, AV_LOG_ERROR
, "Failed to query %s "
454 "of device \"%s\".\n",
455 opencl_device_params
[i
].key
, device_name
);
456 return AVERROR_UNKNOWN
;
458 if (!av_stristr(str
, param
->value
)) {
459 av_log(hwdev
, AV_LOG_DEBUG
, "%s does not match (\"%s\").\n",
469 typedef struct OpenCLDeviceSelector
{
473 int (*enumerate_platforms
)(AVHWDeviceContext
*hwdev
,
474 cl_uint
*nb_platforms
,
475 cl_platform_id
**platforms
,
477 int (*filter_platform
) (AVHWDeviceContext
*hwdev
,
478 cl_platform_id platform_id
,
479 const char *platform_name
,
481 int (*enumerate_devices
) (AVHWDeviceContext
*hwdev
,
482 cl_platform_id platform_id
,
483 const char *platform_name
,
485 cl_device_id
**devices
,
487 int (*filter_device
) (AVHWDeviceContext
*hwdev
,
488 cl_device_id device_id
,
489 const char *device_name
,
491 } OpenCLDeviceSelector
;
493 static int opencl_device_create_internal(AVHWDeviceContext
*hwdev
,
494 const OpenCLDeviceSelector
*selector
,
495 cl_context_properties
*props
)
497 cl_uint nb_platforms
;
498 cl_platform_id
*platforms
= NULL
;
499 cl_platform_id platform_id
;
501 cl_device_id
*devices
= NULL
;
502 AVOpenCLDeviceContext
*hwctx
= hwdev
->hwctx
;
504 cl_context_properties default_props
[3];
505 char *platform_name_src
= NULL
,
506 *device_name_src
= NULL
;
507 int err
, found
, p
, d
;
509 av_assert0(selector
->enumerate_platforms
&&
510 selector
->enumerate_devices
);
512 err
= selector
->enumerate_platforms(hwdev
, &nb_platforms
, &platforms
,
518 for (p
= 0; p
< nb_platforms
; p
++) {
519 const char *platform_name
;
521 if (selector
->platform_index
>= 0 &&
522 selector
->platform_index
!= p
)
525 av_freep(&platform_name_src
);
526 platform_name_src
= opencl_get_platform_string(platforms
[p
],
528 if (platform_name_src
)
529 platform_name
= platform_name_src
;
531 platform_name
= "Unknown Platform";
533 if (selector
->filter_platform
) {
534 err
= selector
->filter_platform(hwdev
, platforms
[p
],
543 err
= selector
->enumerate_devices(hwdev
, platforms
[p
], platform_name
,
544 &nb_devices
, &devices
,
549 for (d
= 0; d
< nb_devices
; d
++) {
550 const char *device_name
;
552 if (selector
->device_index
>= 0 &&
553 selector
->device_index
!= d
)
556 av_freep(&device_name_src
);
557 device_name_src
= opencl_get_device_string(devices
[d
],
560 device_name
= device_name_src
;
562 device_name
= "Unknown Device";
564 if (selector
->filter_device
) {
565 err
= selector
->filter_device(hwdev
, devices
[d
],
574 av_log(hwdev
, AV_LOG_VERBOSE
, "%d.%d: %s / %s\n", p
, d
,
575 platform_name
, device_name
);
578 platform_id
= platforms
[p
];
579 hwctx
->device_id
= devices
[d
];
586 av_log(hwdev
, AV_LOG_ERROR
, "No matching devices found.\n");
587 err
= AVERROR(ENODEV
);
591 av_log(hwdev
, AV_LOG_ERROR
, "More than one matching device found.\n");
592 err
= AVERROR(ENODEV
);
597 props
= default_props
;
598 default_props
[0] = CL_CONTEXT_PLATFORM
;
599 default_props
[1] = (intptr_t)platform_id
;
600 default_props
[2] = 0;
602 if (props
[0] == CL_CONTEXT_PLATFORM
&& props
[1] == 0)
603 props
[1] = (intptr_t)platform_id
;
606 hwctx
->context
= clCreateContext(props
, 1, &hwctx
->device_id
,
607 &opencl_error_callback
, hwdev
, &cle
);
608 if (!hwctx
->context
) {
609 av_log(hwdev
, AV_LOG_ERROR
, "Failed to create OpenCL context: "
611 err
= AVERROR(ENODEV
);
615 hwdev
->free
= &opencl_device_free
;
619 av_freep(&platform_name_src
);
620 av_freep(&device_name_src
);
621 av_freep(&platforms
);
626 static int opencl_device_create(AVHWDeviceContext
*hwdev
, const char *device
,
627 AVDictionary
*opts
, int flags
)
629 OpenCLDeviceSelector selector
= {
631 .enumerate_platforms
= &opencl_enumerate_platforms
,
632 .filter_platform
= &opencl_filter_platform
,
633 .enumerate_devices
= &opencl_enumerate_devices
,
634 .filter_device
= &opencl_filter_device
,
637 if (device
&& device
[0]) {
638 // Match one or both indices for platform and device.
639 int d
= -1, p
= -1, ret
;
640 if (device
[0] == '.')
641 ret
= sscanf(device
, ".%d", &d
);
643 ret
= sscanf(device
, "%d.%d", &p
, &d
);
645 av_log(hwdev
, AV_LOG_ERROR
, "Invalid OpenCL platform/device "
646 "index specification \"%s\".\n", device
);
647 return AVERROR(EINVAL
);
649 selector
.platform_index
= p
;
650 selector
.device_index
= d
;
652 selector
.platform_index
= -1;
653 selector
.device_index
= -1;
656 return opencl_device_create_internal(hwdev
, &selector
, NULL
);
659 static int opencl_device_init(AVHWDeviceContext
*hwdev
)
661 AVOpenCLDeviceContext
*hwctx
= hwdev
->hwctx
;
662 OpenCLDeviceContext
*priv
= hwdev
->internal
->priv
;
665 if (hwctx
->command_queue
) {
666 cle
= clRetainCommandQueue(hwctx
->command_queue
);
667 if (cle
!= CL_SUCCESS
) {
668 av_log(hwdev
, AV_LOG_ERROR
, "Failed to retain external "
669 "command queue: %d.\n", cle
);
672 priv
->command_queue
= hwctx
->command_queue
;
674 priv
->command_queue
= clCreateCommandQueue(hwctx
->context
,
677 if (!priv
->command_queue
) {
678 av_log(hwdev
, AV_LOG_ERROR
, "Failed to create internal "
679 "command queue: %d.\n", cle
);
684 cle
= clGetDeviceInfo(hwctx
->device_id
, CL_DEVICE_PLATFORM
,
685 sizeof(priv
->platform_id
), &priv
->platform_id
,
687 if (cle
!= CL_SUCCESS
) {
688 av_log(hwdev
, AV_LOG_ERROR
, "Failed to determine the OpenCL "
689 "platform containing the device.\n");
693 #define CL_FUNC(name, desc) do { \
696 priv->name = clGetExtensionFunctionAddressForPlatform( \
697 priv->platform_id, #name); \
699 av_log(hwdev, AV_LOG_VERBOSE, \
700 desc " function not found (%s).\n", #name); \
703 av_log(hwdev, AV_LOG_VERBOSE, \
704 desc " function found (%s).\n", #name); \
708 #if HAVE_OPENCL_DRM_BEIGNET
712 CL_FUNC(clCreateImageFromFdINTEL
,
713 "Beignet DRM to OpenCL image mapping");
716 av_log(hwdev
, AV_LOG_WARNING
, "Beignet DRM to OpenCL "
717 "mapping not usable.\n");
718 priv
->beignet_drm_mapping_usable
= 0;
720 priv
->beignet_drm_mapping_usable
= 1;
725 #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
728 cl_context_properties
*props
= NULL
;
729 VADisplay va_display
;
730 const char *va_ext
= "cl_intel_va_api_media_sharing";
733 if (!opencl_check_extension(hwdev
, va_ext
)) {
734 av_log(hwdev
, AV_LOG_VERBOSE
, "The %s extension is "
735 "required for QSV to OpenCL mapping.\n", va_ext
);
739 cle
= clGetContextInfo(hwctx
->context
, CL_CONTEXT_PROPERTIES
,
740 0, NULL
, &props_size
);
741 if (cle
!= CL_SUCCESS
) {
742 av_log(hwdev
, AV_LOG_VERBOSE
, "Failed to get context "
743 "properties: %d.\n", cle
);
746 if (props_size
== 0) {
747 av_log(hwdev
, AV_LOG_VERBOSE
, "Media sharing must be "
748 "enabled on context creation to use QSV to "
749 "OpenCL mapping.\n");
753 props
= av_malloc(props_size
);
755 return AVERROR(ENOMEM
);
757 cle
= clGetContextInfo(hwctx
->context
, CL_CONTEXT_PROPERTIES
,
758 props_size
, props
, NULL
);
759 if (cle
!= CL_SUCCESS
) {
760 av_log(hwdev
, AV_LOG_VERBOSE
, "Failed to get context "
761 "properties: %d.\n", cle
);
766 for (i
= 0; i
< (props_size
/ sizeof(*props
) - 1); i
++) {
767 if (props
[i
] == CL_CONTEXT_VA_API_DISPLAY_INTEL
) {
768 va_display
= (VADisplay
)(intptr_t)props
[i
+1];
773 av_log(hwdev
, AV_LOG_VERBOSE
, "Media sharing must be "
774 "enabled on context creation to use QSV to "
775 "OpenCL mapping.\n");
778 if (!vaDisplayIsValid(va_display
)) {
779 av_log(hwdev
, AV_LOG_VERBOSE
, "A valid VADisplay is "
780 "required on context creation to use QSV to "
781 "OpenCL mapping.\n");
785 CL_FUNC(clCreateFromVA_APIMediaSurfaceINTEL
,
786 "Intel QSV to OpenCL mapping");
787 CL_FUNC(clEnqueueAcquireVA_APIMediaSurfacesINTEL
,
788 "Intel QSV in OpenCL acquire");
789 CL_FUNC(clEnqueueReleaseVA_APIMediaSurfacesINTEL
,
790 "Intel QSV in OpenCL release");
794 av_log(hwdev
, AV_LOG_WARNING
, "QSV to OpenCL mapping "
796 priv
->qsv_mapping_usable
= 0;
798 priv
->qsv_mapping_usable
= 1;
804 #if HAVE_OPENCL_DXVA2
808 CL_FUNC(clCreateFromDX9MediaSurfaceKHR
,
809 "DXVA2 to OpenCL mapping");
810 CL_FUNC(clEnqueueAcquireDX9MediaSurfacesKHR
,
811 "DXVA2 in OpenCL acquire");
812 CL_FUNC(clEnqueueReleaseDX9MediaSurfacesKHR
,
813 "DXVA2 in OpenCL release");
816 av_log(hwdev
, AV_LOG_WARNING
, "DXVA2 to OpenCL mapping "
818 priv
->dxva2_mapping_usable
= 0;
820 priv
->dx9_media_adapter_type
= CL_ADAPTER_D3D9EX_KHR
;
821 priv
->dxva2_mapping_usable
= 1;
826 #if HAVE_OPENCL_D3D11
828 const char *d3d11_ext
= "cl_khr_d3d11_sharing";
829 const char *nv12_ext
= "cl_intel_d3d11_nv12_media_sharing";
832 if (!opencl_check_extension(hwdev
, d3d11_ext
)) {
833 av_log(hwdev
, AV_LOG_VERBOSE
, "The %s extension is "
834 "required for D3D11 to OpenCL mapping.\n", d3d11_ext
);
836 } else if (!opencl_check_extension(hwdev
, nv12_ext
)) {
837 av_log(hwdev
, AV_LOG_VERBOSE
, "The %s extension may be "
838 "required for D3D11 to OpenCL mapping.\n", nv12_ext
);
842 CL_FUNC(clCreateFromD3D11Texture2DKHR
,
843 "D3D11 to OpenCL mapping");
844 CL_FUNC(clEnqueueAcquireD3D11ObjectsKHR
,
845 "D3D11 in OpenCL acquire");
846 CL_FUNC(clEnqueueReleaseD3D11ObjectsKHR
,
847 "D3D11 in OpenCL release");
850 av_log(hwdev
, AV_LOG_WARNING
, "D3D11 to OpenCL mapping "
852 priv
->d3d11_mapping_usable
= 0;
854 priv
->d3d11_mapping_usable
= 1;
859 #if HAVE_OPENCL_DRM_ARM
861 const char *drm_arm_ext
= "cl_arm_import_memory";
862 const char *image_ext
= "cl_khr_image2d_from_buffer";
865 if (!opencl_check_extension(hwdev
, drm_arm_ext
)) {
866 av_log(hwdev
, AV_LOG_VERBOSE
, "The %s extension is "
867 "required for DRM to OpenCL mapping on ARM.\n",
871 if (!opencl_check_extension(hwdev
, image_ext
)) {
872 av_log(hwdev
, AV_LOG_VERBOSE
, "The %s extension is "
873 "required for DRM to OpenCL mapping on ARM.\n",
878 // clImportMemoryARM() is linked statically.
881 av_log(hwdev
, AV_LOG_WARNING
, "DRM to OpenCL mapping on ARM "
883 priv
->drm_arm_mapping_usable
= 0;
885 priv
->drm_arm_mapping_usable
= 1;
895 static void opencl_device_uninit(AVHWDeviceContext
*hwdev
)
897 OpenCLDeviceContext
*priv
= hwdev
->internal
->priv
;
900 if (priv
->command_queue
) {
901 cle
= clReleaseCommandQueue(priv
->command_queue
);
902 if (cle
!= CL_SUCCESS
) {
903 av_log(hwdev
, AV_LOG_ERROR
, "Failed to release internal "
904 "command queue reference: %d.\n", cle
);
906 priv
->command_queue
= NULL
;
910 #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
911 static int opencl_filter_intel_media_vaapi_platform(AVHWDeviceContext
*hwdev
,
912 cl_platform_id platform_id
,
913 const char *platform_name
,
916 // This doesn't exist as a platform extension, so just test whether
917 // the function we will use for device enumeration exists.
919 if (!clGetExtensionFunctionAddressForPlatform(platform_id
,
920 "clGetDeviceIDsFromVA_APIMediaAdapterINTEL")) {
921 av_log(hwdev
, AV_LOG_DEBUG
, "Platform %s does not export the "
922 "VAAPI device enumeration function.\n", platform_name
);
929 static int opencl_enumerate_intel_media_vaapi_devices(AVHWDeviceContext
*hwdev
,
930 cl_platform_id platform_id
,
931 const char *platform_name
,
933 cl_device_id
**devices
,
936 VADisplay va_display
= context
;
937 clGetDeviceIDsFromVA_APIMediaAdapterINTEL_fn
938 clGetDeviceIDsFromVA_APIMediaAdapterINTEL
;
941 clGetDeviceIDsFromVA_APIMediaAdapterINTEL
=
942 clGetExtensionFunctionAddressForPlatform(platform_id
,
943 "clGetDeviceIDsFromVA_APIMediaAdapterINTEL");
944 if (!clGetDeviceIDsFromVA_APIMediaAdapterINTEL
) {
945 av_log(hwdev
, AV_LOG_ERROR
, "Failed to get address of "
946 "clGetDeviceIDsFromVA_APIMediaAdapterINTEL().\n");
947 return AVERROR_UNKNOWN
;
950 cle
= clGetDeviceIDsFromVA_APIMediaAdapterINTEL(
951 platform_id
, CL_VA_API_DISPLAY_INTEL
, va_display
,
952 CL_PREFERRED_DEVICES_FOR_VA_API_INTEL
, 0, NULL
, nb_devices
);
953 if (cle
== CL_DEVICE_NOT_FOUND
) {
954 av_log(hwdev
, AV_LOG_DEBUG
, "No VAAPI-supporting devices found "
955 "on platform \"%s\".\n", platform_name
);
958 } else if (cle
!= CL_SUCCESS
) {
959 av_log(hwdev
, AV_LOG_ERROR
, "Failed to get number of devices "
960 "on platform \"%s\": %d.\n", platform_name
, cle
);
961 return AVERROR_UNKNOWN
;
964 *devices
= av_malloc_array(*nb_devices
, sizeof(**devices
));
966 return AVERROR(ENOMEM
);
968 cle
= clGetDeviceIDsFromVA_APIMediaAdapterINTEL(
969 platform_id
, CL_VA_API_DISPLAY_INTEL
, va_display
,
970 CL_PREFERRED_DEVICES_FOR_VA_API_INTEL
, *nb_devices
, *devices
, NULL
);
971 if (cle
!= CL_SUCCESS
) {
972 av_log(hwdev
, AV_LOG_ERROR
, "Failed to get list of VAAPI-supporting "
973 "devices on platform \"%s\": %d.\n", platform_name
, cle
);
975 return AVERROR_UNKNOWN
;
981 static int opencl_filter_intel_media_vaapi_device(AVHWDeviceContext
*hwdev
,
982 cl_device_id device_id
,
983 const char *device_name
,
986 const char *va_ext
= "cl_intel_va_api_media_sharing";
988 if (opencl_check_device_extension(device_id
, va_ext
)) {
991 av_log(hwdev
, AV_LOG_DEBUG
, "Device %s does not support the "
992 "%s extension.\n", device_name
, va_ext
);
998 #if HAVE_OPENCL_DXVA2
999 static int opencl_filter_dxva2_platform(AVHWDeviceContext
*hwdev
,
1000 cl_platform_id platform_id
,
1001 const char *platform_name
,
1004 const char *dx9_ext
= "cl_khr_dx9_media_sharing";
1006 if (opencl_check_platform_extension(platform_id
, dx9_ext
)) {
1009 av_log(hwdev
, AV_LOG_DEBUG
, "Platform %s does not support the "
1010 "%s extension.\n", platform_name
, dx9_ext
);
1015 static int opencl_enumerate_dxva2_devices(AVHWDeviceContext
*hwdev
,
1016 cl_platform_id platform_id
,
1017 const char *platform_name
,
1018 cl_uint
*nb_devices
,
1019 cl_device_id
**devices
,
1022 IDirect3DDevice9
*device
= context
;
1023 clGetDeviceIDsFromDX9MediaAdapterKHR_fn
1024 clGetDeviceIDsFromDX9MediaAdapterKHR
;
1025 cl_dx9_media_adapter_type_khr media_adapter_type
= CL_ADAPTER_D3D9EX_KHR
;
1028 clGetDeviceIDsFromDX9MediaAdapterKHR
=
1029 clGetExtensionFunctionAddressForPlatform(platform_id
,
1030 "clGetDeviceIDsFromDX9MediaAdapterKHR");
1031 if (!clGetDeviceIDsFromDX9MediaAdapterKHR
) {
1032 av_log(hwdev
, AV_LOG_ERROR
, "Failed to get address of "
1033 "clGetDeviceIDsFromDX9MediaAdapterKHR().\n");
1034 return AVERROR_UNKNOWN
;
1037 cle
= clGetDeviceIDsFromDX9MediaAdapterKHR(
1038 platform_id
, 1, &media_adapter_type
, (void**)&device
,
1039 CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR
,
1040 0, NULL
, nb_devices
);
1041 if (cle
== CL_DEVICE_NOT_FOUND
) {
1042 av_log(hwdev
, AV_LOG_DEBUG
, "No DXVA2-supporting devices found "
1043 "on platform \"%s\".\n", platform_name
);
1046 } else if (cle
!= CL_SUCCESS
) {
1047 av_log(hwdev
, AV_LOG_ERROR
, "Failed to get number of devices "
1048 "on platform \"%s\": %d.\n", platform_name
, cle
);
1049 return AVERROR_UNKNOWN
;
1052 *devices
= av_malloc_array(*nb_devices
, sizeof(**devices
));
1054 return AVERROR(ENOMEM
);
1056 cle
= clGetDeviceIDsFromDX9MediaAdapterKHR(
1057 platform_id
, 1, &media_adapter_type
, (void**)&device
,
1058 CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR
,
1059 *nb_devices
, *devices
, NULL
);
1060 if (cle
!= CL_SUCCESS
) {
1061 av_log(hwdev
, AV_LOG_ERROR
, "Failed to get list of DXVA2-supporting "
1062 "devices on platform \"%s\": %d.\n", platform_name
, cle
);
1064 return AVERROR_UNKNOWN
;
1071 #if HAVE_OPENCL_D3D11
1072 static int opencl_filter_d3d11_platform(AVHWDeviceContext
*hwdev
,
1073 cl_platform_id platform_id
,
1074 const char *platform_name
,
1077 const char *d3d11_ext
= "cl_khr_d3d11_sharing";
1079 if (opencl_check_platform_extension(platform_id
, d3d11_ext
)) {
1082 av_log(hwdev
, AV_LOG_DEBUG
, "Platform %s does not support the "
1083 "%s extension.\n", platform_name
, d3d11_ext
);
1088 static int opencl_enumerate_d3d11_devices(AVHWDeviceContext
*hwdev
,
1089 cl_platform_id platform_id
,
1090 const char *platform_name
,
1091 cl_uint
*nb_devices
,
1092 cl_device_id
**devices
,
1095 ID3D11Device
*device
= context
;
1096 clGetDeviceIDsFromD3D11KHR_fn clGetDeviceIDsFromD3D11KHR
;
1099 clGetDeviceIDsFromD3D11KHR
=
1100 clGetExtensionFunctionAddressForPlatform(platform_id
,
1101 "clGetDeviceIDsFromD3D11KHR");
1102 if (!clGetDeviceIDsFromD3D11KHR
) {
1103 av_log(hwdev
, AV_LOG_ERROR
, "Failed to get address of "
1104 "clGetDeviceIDsFromD3D11KHR().\n");
1105 return AVERROR_UNKNOWN
;
1108 cle
= clGetDeviceIDsFromD3D11KHR(platform_id
,
1109 CL_D3D11_DEVICE_KHR
, device
,
1110 CL_PREFERRED_DEVICES_FOR_D3D11_KHR
,
1111 0, NULL
, nb_devices
);
1112 if (cle
== CL_DEVICE_NOT_FOUND
) {
1113 av_log(hwdev
, AV_LOG_DEBUG
, "No D3D11-supporting devices found "
1114 "on platform \"%s\".\n", platform_name
);
1117 } else if (cle
!= CL_SUCCESS
) {
1118 av_log(hwdev
, AV_LOG_ERROR
, "Failed to get number of devices "
1119 "on platform \"%s\": %d.\n", platform_name
, cle
);
1120 return AVERROR_UNKNOWN
;
1123 *devices
= av_malloc_array(*nb_devices
, sizeof(**devices
));
1125 return AVERROR(ENOMEM
);
1127 cle
= clGetDeviceIDsFromD3D11KHR(platform_id
,
1128 CL_D3D11_DEVICE_KHR
, device
,
1129 CL_PREFERRED_DEVICES_FOR_D3D11_KHR
,
1130 *nb_devices
, *devices
, NULL
);
1131 if (cle
!= CL_SUCCESS
) {
1132 av_log(hwdev
, AV_LOG_ERROR
, "Failed to get list of D3D11-supporting "
1133 "devices on platform \"%s\": %d.\n", platform_name
, cle
);
1135 return AVERROR_UNKNOWN
;
1142 #if HAVE_OPENCL_DXVA2 || HAVE_OPENCL_D3D11
1143 static int opencl_filter_gpu_device(AVHWDeviceContext
*hwdev
,
1144 cl_device_id device_id
,
1145 const char *device_name
,
1148 cl_device_type device_type
;
1151 cle
= clGetDeviceInfo(device_id
, CL_DEVICE_TYPE
,
1152 sizeof(device_type
), &device_type
, NULL
);
1153 if (cle
!= CL_SUCCESS
) {
1154 av_log(hwdev
, AV_LOG_ERROR
, "Failed to query device type "
1155 "of device \"%s\".\n", device_name
);
1156 return AVERROR_UNKNOWN
;
1158 if (!(device_type
& CL_DEVICE_TYPE_GPU
)) {
1159 av_log(hwdev
, AV_LOG_DEBUG
, "Device %s skipped (not GPU).\n",
1168 #if HAVE_OPENCL_DRM_ARM
1169 static int opencl_filter_drm_arm_platform(AVHWDeviceContext
*hwdev
,
1170 cl_platform_id platform_id
,
1171 const char *platform_name
,
1174 const char *drm_arm_ext
= "cl_arm_import_memory";
1176 if (opencl_check_platform_extension(platform_id
, drm_arm_ext
)) {
1179 av_log(hwdev
, AV_LOG_DEBUG
, "Platform %s does not support the "
1180 "%s extension.\n", platform_name
, drm_arm_ext
);
1185 static int opencl_filter_drm_arm_device(AVHWDeviceContext
*hwdev
,
1186 cl_device_id device_id
,
1187 const char *device_name
,
1190 const char *drm_arm_ext
= "cl_arm_import_memory";
1192 if (opencl_check_device_extension(device_id
, drm_arm_ext
)) {
1195 av_log(hwdev
, AV_LOG_DEBUG
, "Device %s does not support the "
1196 "%s extension.\n", device_name
, drm_arm_ext
);
1202 static int opencl_device_derive(AVHWDeviceContext
*hwdev
,
1203 AVHWDeviceContext
*src_ctx
, AVDictionary
*opts
,
1207 switch (src_ctx
->type
) {
1209 #if HAVE_OPENCL_DRM_BEIGNET
1210 case AV_HWDEVICE_TYPE_DRM
:
1211 case AV_HWDEVICE_TYPE_VAAPI
:
1213 // Surface mapping works via DRM PRIME fds with no special
1214 // initialisation required in advance. This just finds the
1215 // Beignet ICD by name.
1216 AVDictionary
*selector_opts
= NULL
;
1218 err
= av_dict_set(&selector_opts
, "platform_vendor", "Intel", 0);
1220 err
= av_dict_set(&selector_opts
, "platform_version", "beignet", 0);
1222 OpenCLDeviceSelector selector
= {
1223 .platform_index
= -1,
1225 .context
= selector_opts
,
1226 .enumerate_platforms
= &opencl_enumerate_platforms
,
1227 .filter_platform
= &opencl_filter_platform
,
1228 .enumerate_devices
= &opencl_enumerate_devices
,
1229 .filter_device
= NULL
,
1231 err
= opencl_device_create_internal(hwdev
, &selector
, NULL
);
1233 av_dict_free(&selector_opts
);
1238 #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
1239 // The generic code automatically attempts to derive from all
1240 // ancestors of the given device, so we can ignore QSV devices here
1241 // and just consider the inner VAAPI device it was derived from.
1242 case AV_HWDEVICE_TYPE_VAAPI
:
1244 AVVAAPIDeviceContext
*src_hwctx
= src_ctx
->hwctx
;
1245 cl_context_properties props
[7] = {
1246 CL_CONTEXT_PLATFORM
,
1248 CL_CONTEXT_VA_API_DISPLAY_INTEL
,
1249 (intptr_t)src_hwctx
->display
,
1250 CL_CONTEXT_INTEROP_USER_SYNC
,
1254 OpenCLDeviceSelector selector
= {
1255 .platform_index
= -1,
1257 .context
= src_hwctx
->display
,
1258 .enumerate_platforms
= &opencl_enumerate_platforms
,
1259 .filter_platform
= &opencl_filter_intel_media_vaapi_platform
,
1260 .enumerate_devices
= &opencl_enumerate_intel_media_vaapi_devices
,
1261 .filter_device
= &opencl_filter_intel_media_vaapi_device
,
1264 err
= opencl_device_create_internal(hwdev
, &selector
, props
);
1269 #if HAVE_OPENCL_DXVA2
1270 case AV_HWDEVICE_TYPE_DXVA2
:
1272 AVDXVA2DeviceContext
*src_hwctx
= src_ctx
->hwctx
;
1273 IDirect3DDevice9
*device
;
1274 HANDLE device_handle
;
1277 hr
= IDirect3DDeviceManager9_OpenDeviceHandle(src_hwctx
->devmgr
,
1280 av_log(hwdev
, AV_LOG_ERROR
, "Failed to open device handle "
1281 "for Direct3D9 device: %lx.\n", (unsigned long)hr
);
1282 err
= AVERROR_UNKNOWN
;
1286 hr
= IDirect3DDeviceManager9_LockDevice(src_hwctx
->devmgr
,
1289 if (SUCCEEDED(hr
)) {
1290 cl_context_properties props
[5] = {
1291 CL_CONTEXT_PLATFORM
,
1293 CL_CONTEXT_ADAPTER_D3D9EX_KHR
,
1297 OpenCLDeviceSelector selector
= {
1298 .platform_index
= -1,
1301 .enumerate_platforms
= &opencl_enumerate_platforms
,
1302 .filter_platform
= &opencl_filter_dxva2_platform
,
1303 .enumerate_devices
= &opencl_enumerate_dxva2_devices
,
1304 .filter_device
= &opencl_filter_gpu_device
,
1307 err
= opencl_device_create_internal(hwdev
, &selector
, props
);
1309 IDirect3DDeviceManager9_UnlockDevice(src_hwctx
->devmgr
,
1310 device_handle
, FALSE
);
1312 av_log(hwdev
, AV_LOG_ERROR
, "Failed to lock device handle "
1313 "for Direct3D9 device: %lx.\n", (unsigned long)hr
);
1314 err
= AVERROR_UNKNOWN
;
1317 IDirect3DDeviceManager9_CloseDeviceHandle(src_hwctx
->devmgr
,
1323 #if HAVE_OPENCL_D3D11
1324 case AV_HWDEVICE_TYPE_D3D11VA
:
1326 AVD3D11VADeviceContext
*src_hwctx
= src_ctx
->hwctx
;
1327 cl_context_properties props
[5] = {
1328 CL_CONTEXT_PLATFORM
,
1330 CL_CONTEXT_D3D11_DEVICE_KHR
,
1331 (intptr_t)src_hwctx
->device
,
1334 OpenCLDeviceSelector selector
= {
1335 .platform_index
= -1,
1337 .context
= src_hwctx
->device
,
1338 .enumerate_platforms
= &opencl_enumerate_platforms
,
1339 .filter_platform
= &opencl_filter_d3d11_platform
,
1340 .enumerate_devices
= &opencl_enumerate_d3d11_devices
,
1341 .filter_device
= &opencl_filter_gpu_device
,
1344 err
= opencl_device_create_internal(hwdev
, &selector
, props
);
1349 #if HAVE_OPENCL_DRM_ARM
1350 case AV_HWDEVICE_TYPE_DRM
:
1352 OpenCLDeviceSelector selector
= {
1353 .platform_index
= -1,
1356 .enumerate_platforms
= &opencl_enumerate_platforms
,
1357 .filter_platform
= &opencl_filter_drm_arm_platform
,
1358 .enumerate_devices
= &opencl_enumerate_devices
,
1359 .filter_device
= &opencl_filter_drm_arm_device
,
1362 err
= opencl_device_create_internal(hwdev
, &selector
, NULL
);
1368 err
= AVERROR(ENOSYS
);
1375 static int opencl_get_plane_format(enum AVPixelFormat pixfmt
,
1376 int plane
, int width
, int height
,
1377 cl_image_format
*image_format
,
1378 cl_image_desc
*image_desc
)
1380 const AVPixFmtDescriptor
*desc
;
1381 const AVComponentDescriptor
*comp
;
1382 int channels
= 0, order
= 0, depth
= 0, step
= 0;
1383 int wsub
, hsub
, alpha
;
1386 if (plane
>= AV_NUM_DATA_POINTERS
)
1387 return AVERROR(ENOENT
);
1389 desc
= av_pix_fmt_desc_get(pixfmt
);
1391 // Only normal images are allowed.
1392 if (desc
->flags
& (AV_PIX_FMT_FLAG_BITSTREAM
|
1393 AV_PIX_FMT_FLAG_HWACCEL
|
1394 AV_PIX_FMT_FLAG_PAL
))
1395 return AVERROR(EINVAL
);
1397 wsub
= 1 << desc
->log2_chroma_w
;
1398 hsub
= 1 << desc
->log2_chroma_h
;
1399 // Subsampled components must be exact.
1400 if (width
& wsub
- 1 || height
& hsub
- 1)
1401 return AVERROR(EINVAL
);
1403 for (c
= 0; c
< desc
->nb_components
; c
++) {
1404 comp
= &desc
->comp
[c
];
1405 if (comp
->plane
!= plane
)
1407 // The step size must be a power of two.
1408 if (comp
->step
!= 1 && comp
->step
!= 2 &&
1409 comp
->step
!= 4 && comp
->step
!= 8)
1410 return AVERROR(EINVAL
);
1411 // The bits in each component must be packed in the
1412 // most-significant-bits of the relevant bytes.
1413 if (comp
->shift
+ comp
->depth
!= 8 &&
1414 comp
->shift
+ comp
->depth
!= 16 &&
1415 comp
->shift
+ comp
->depth
!= 32)
1416 return AVERROR(EINVAL
);
1417 // The depth must not vary between components.
1418 if (depth
&& comp
->depth
!= depth
)
1419 return AVERROR(EINVAL
);
1420 // If a single data element crosses multiple bytes then
1421 // it must match the native endianness.
1422 if (comp
->depth
> 8 &&
1423 HAVE_BIGENDIAN
== !(desc
->flags
& AV_PIX_FMT_FLAG_BE
))
1424 return AVERROR(EINVAL
);
1425 // A single data element must not contain multiple samples
1426 // from the same component.
1427 if (step
&& comp
->step
!= step
)
1428 return AVERROR(EINVAL
);
1430 depth
= comp
->depth
;
1431 order
= order
* 10 + comp
->offset
/ ((depth
+ 7) / 8) + 1;
1433 alpha
= (desc
->flags
& AV_PIX_FMT_FLAG_ALPHA
&&
1434 c
== desc
->nb_components
- 1);
1438 return AVERROR(ENOENT
);
1440 memset(image_format
, 0, sizeof(*image_format
));
1441 memset(image_desc
, 0, sizeof(*image_desc
));
1442 image_desc
->image_type
= CL_MEM_OBJECT_IMAGE2D
;
1444 if (plane
== 0 || alpha
) {
1445 image_desc
->image_width
= width
;
1446 image_desc
->image_height
= height
;
1447 image_desc
->image_row_pitch
= step
* width
;
1449 image_desc
->image_width
= width
/ wsub
;
1450 image_desc
->image_height
= height
/ hsub
;
1451 image_desc
->image_row_pitch
= step
* width
/ wsub
;
1455 image_format
->image_channel_data_type
= CL_UNORM_INT8
;
1458 image_format
->image_channel_data_type
= CL_UNORM_INT16
;
1459 else if (depth
== 32)
1460 image_format
->image_channel_data_type
= CL_FLOAT
;
1462 return AVERROR(EINVAL
);
1465 #define CHANNEL_ORDER(order, type) \
1466 case order: image_format->image_channel_order = type; break;
1468 CHANNEL_ORDER(1, CL_R
);
1469 CHANNEL_ORDER(12, CL_RG
);
1470 CHANNEL_ORDER(1234, CL_RGBA
);
1471 CHANNEL_ORDER(2341, CL_ARGB
);
1472 CHANNEL_ORDER(3214, CL_BGRA
);
1474 CHANNEL_ORDER(4321, CL_ABGR
);
1477 return AVERROR(EINVAL
);
1479 #undef CHANNEL_ORDER
1484 static int opencl_frames_get_constraints(AVHWDeviceContext
*hwdev
,
1485 const void *hwconfig
,
1486 AVHWFramesConstraints
*constraints
)
1488 AVOpenCLDeviceContext
*hwctx
= hwdev
->hwctx
;
1489 cl_uint nb_image_formats
;
1490 cl_image_format
*image_formats
= NULL
;
1492 enum AVPixelFormat pix_fmt
;
1493 int err
, pix_fmts_found
;
1494 size_t max_width
, max_height
;
1496 cle
= clGetDeviceInfo(hwctx
->device_id
, CL_DEVICE_IMAGE2D_MAX_WIDTH
,
1497 sizeof(max_width
), &max_width
, NULL
);
1498 if (cle
!= CL_SUCCESS
) {
1499 av_log(hwdev
, AV_LOG_ERROR
, "Failed to query maximum "
1500 "supported image width: %d.\n", cle
);
1502 constraints
->max_width
= max_width
;
1504 cle
= clGetDeviceInfo(hwctx
->device_id
, CL_DEVICE_IMAGE2D_MAX_HEIGHT
,
1505 sizeof(max_height
), &max_height
, NULL
);
1506 if (cle
!= CL_SUCCESS
) {
1507 av_log(hwdev
, AV_LOG_ERROR
, "Failed to query maximum "
1508 "supported image height: %d.\n", cle
);
1510 constraints
->max_height
= max_height
;
1512 av_log(hwdev
, AV_LOG_DEBUG
, "Maximum supported image size %dx%d.\n",
1513 constraints
->max_width
, constraints
->max_height
);
1515 cle
= clGetSupportedImageFormats(hwctx
->context
,
1517 CL_MEM_OBJECT_IMAGE2D
,
1518 0, NULL
, &nb_image_formats
);
1519 if (cle
!= CL_SUCCESS
) {
1520 av_log(hwdev
, AV_LOG_ERROR
, "Failed to query supported "
1521 "image formats: %d.\n", cle
);
1522 err
= AVERROR(ENOSYS
);
1525 if (nb_image_formats
== 0) {
1526 av_log(hwdev
, AV_LOG_ERROR
, "No image support in OpenCL "
1527 "driver (zero supported image formats).\n");
1528 err
= AVERROR(ENOSYS
);
1533 av_malloc_array(nb_image_formats
, sizeof(*image_formats
));
1534 if (!image_formats
) {
1535 err
= AVERROR(ENOMEM
);
1539 cle
= clGetSupportedImageFormats(hwctx
->context
,
1541 CL_MEM_OBJECT_IMAGE2D
,
1543 image_formats
, NULL
);
1544 if (cle
!= CL_SUCCESS
) {
1545 av_log(hwdev
, AV_LOG_ERROR
, "Failed to query supported "
1546 "image formats: %d.\n", cle
);
1547 err
= AVERROR(ENOSYS
);
1552 for (pix_fmt
= 0; pix_fmt
< AV_PIX_FMT_NB
; pix_fmt
++) {
1553 cl_image_format image_format
;
1554 cl_image_desc image_desc
;
1557 for (plane
= 0;; plane
++) {
1558 err
= opencl_get_plane_format(pix_fmt
, plane
, 0, 0,
1564 for (i
= 0; i
< nb_image_formats
; i
++) {
1565 if (image_formats
[i
].image_channel_order
==
1566 image_format
.image_channel_order
&&
1567 image_formats
[i
].image_channel_data_type
==
1568 image_format
.image_channel_data_type
)
1571 if (i
== nb_image_formats
) {
1572 err
= AVERROR(EINVAL
);
1576 if (err
!= AVERROR(ENOENT
))
1579 av_log(hwdev
, AV_LOG_DEBUG
, "Format %s supported.\n",
1580 av_get_pix_fmt_name(pix_fmt
));
1582 err
= av_reallocp_array(&constraints
->valid_sw_formats
,
1584 sizeof(*constraints
->valid_sw_formats
));
1587 constraints
->valid_sw_formats
[pix_fmts_found
] = pix_fmt
;
1588 constraints
->valid_sw_formats
[pix_fmts_found
+ 1] =
1593 av_freep(&image_formats
);
1595 constraints
->valid_hw_formats
=
1596 av_malloc_array(2, sizeof(*constraints
->valid_hw_formats
));
1597 if (!constraints
->valid_hw_formats
) {
1598 err
= AVERROR(ENOMEM
);
1601 constraints
->valid_hw_formats
[0] = AV_PIX_FMT_OPENCL
;
1602 constraints
->valid_hw_formats
[1] = AV_PIX_FMT_NONE
;
1607 av_freep(&image_formats
);
1611 static void opencl_pool_free(void *opaque
, uint8_t *data
)
1613 AVHWFramesContext
*hwfc
= opaque
;
1614 AVOpenCLFrameDescriptor
*desc
= (AVOpenCLFrameDescriptor
*)data
;
1618 for (p
= 0; p
< desc
->nb_planes
; p
++) {
1619 cle
= clReleaseMemObject(desc
->planes
[p
]);
1620 if (cle
!= CL_SUCCESS
) {
1621 av_log(hwfc
, AV_LOG_ERROR
, "Failed to release plane %d: "
1629 static AVBufferRef
*opencl_pool_alloc(void *opaque
, size_t size
)
1631 AVHWFramesContext
*hwfc
= opaque
;
1632 AVOpenCLDeviceContext
*hwctx
= hwfc
->device_ctx
->hwctx
;
1633 AVOpenCLFrameDescriptor
*desc
;
1636 cl_image_format image_format
;
1637 cl_image_desc image_desc
;
1641 desc
= av_mallocz(sizeof(*desc
));
1646 err
= opencl_get_plane_format(hwfc
->sw_format
, p
,
1647 hwfc
->width
, hwfc
->height
,
1648 &image_format
, &image_desc
);
1649 if (err
== AVERROR(ENOENT
))
1654 // For generic image objects, the pitch is determined by the
1656 image_desc
.image_row_pitch
= 0;
1658 image
= clCreateImage(hwctx
->context
, CL_MEM_READ_WRITE
,
1659 &image_format
, &image_desc
, NULL
, &cle
);
1661 av_log(hwfc
, AV_LOG_ERROR
, "Failed to create image for "
1662 "plane %d: %d.\n", p
, cle
);
1666 desc
->planes
[p
] = image
;
1669 desc
->nb_planes
= p
;
1671 ref
= av_buffer_create((uint8_t*)desc
, sizeof(*desc
),
1672 &opencl_pool_free
, hwfc
, 0);
1679 for (p
= 0; desc
->planes
[p
]; p
++)
1680 clReleaseMemObject(desc
->planes
[p
]);
1685 static int opencl_frames_init_command_queue(AVHWFramesContext
*hwfc
)
1687 AVOpenCLFramesContext
*hwctx
= hwfc
->hwctx
;
1688 OpenCLDeviceContext
*devpriv
= hwfc
->device_ctx
->internal
->priv
;
1689 OpenCLFramesContext
*priv
= hwfc
->internal
->priv
;
1692 priv
->command_queue
= hwctx
->command_queue
? hwctx
->command_queue
1693 : devpriv
->command_queue
;
1694 cle
= clRetainCommandQueue(priv
->command_queue
);
1695 if (cle
!= CL_SUCCESS
) {
1696 av_log(hwfc
, AV_LOG_ERROR
, "Failed to retain frame "
1697 "command queue: %d.\n", cle
);
1698 return AVERROR(EIO
);
1704 static int opencl_frames_init(AVHWFramesContext
*hwfc
)
1707 hwfc
->internal
->pool_internal
=
1708 av_buffer_pool_init2(sizeof(cl_mem
), hwfc
,
1709 &opencl_pool_alloc
, NULL
);
1710 if (!hwfc
->internal
->pool_internal
)
1711 return AVERROR(ENOMEM
);
1714 return opencl_frames_init_command_queue(hwfc
);
1717 static void opencl_frames_uninit(AVHWFramesContext
*hwfc
)
1719 OpenCLFramesContext
*priv
= hwfc
->internal
->priv
;
1722 #if HAVE_OPENCL_DXVA2 || HAVE_OPENCL_D3D11
1724 for (i
= 0; i
< priv
->nb_mapped_frames
; i
++) {
1725 AVOpenCLFrameDescriptor
*desc
= &priv
->mapped_frames
[i
];
1726 for (p
= 0; p
< desc
->nb_planes
; p
++) {
1727 cle
= clReleaseMemObject(desc
->planes
[p
]);
1728 if (cle
!= CL_SUCCESS
) {
1729 av_log(hwfc
, AV_LOG_ERROR
, "Failed to release mapped "
1730 "frame object (frame %d plane %d): %d.\n",
1735 av_freep(&priv
->mapped_frames
);
1738 if (priv
->command_queue
) {
1739 cle
= clReleaseCommandQueue(priv
->command_queue
);
1740 if (cle
!= CL_SUCCESS
) {
1741 av_log(hwfc
, AV_LOG_ERROR
, "Failed to release frame "
1742 "command queue: %d.\n", cle
);
1744 priv
->command_queue
= NULL
;
1748 static int opencl_get_buffer(AVHWFramesContext
*hwfc
, AVFrame
*frame
)
1750 AVOpenCLFrameDescriptor
*desc
;
1753 frame
->buf
[0] = av_buffer_pool_get(hwfc
->pool
);
1755 return AVERROR(ENOMEM
);
1757 desc
= (AVOpenCLFrameDescriptor
*)frame
->buf
[0]->data
;
1759 for (p
= 0; p
< desc
->nb_planes
; p
++)
1760 frame
->data
[p
] = (uint8_t*)desc
->planes
[p
];
1762 frame
->format
= AV_PIX_FMT_OPENCL
;
1763 frame
->width
= hwfc
->width
;
1764 frame
->height
= hwfc
->height
;
1769 static int opencl_transfer_get_formats(AVHWFramesContext
*hwfc
,
1770 enum AVHWFrameTransferDirection dir
,
1771 enum AVPixelFormat
**formats
)
1773 enum AVPixelFormat
*fmts
;
1775 fmts
= av_malloc_array(2, sizeof(*fmts
));
1777 return AVERROR(ENOMEM
);
1779 fmts
[0] = hwfc
->sw_format
;
1780 fmts
[1] = AV_PIX_FMT_NONE
;
1786 static int opencl_wait_events(AVHWFramesContext
*hwfc
,
1787 cl_event
*events
, int nb_events
)
1792 cle
= clWaitForEvents(nb_events
, events
);
1793 if (cle
!= CL_SUCCESS
) {
1794 av_log(hwfc
, AV_LOG_ERROR
, "Failed to wait for event "
1795 "completion: %d.\n", cle
);
1796 return AVERROR(EIO
);
1799 for (i
= 0; i
< nb_events
; i
++) {
1800 cle
= clReleaseEvent(events
[i
]);
1801 if (cle
!= CL_SUCCESS
) {
1802 av_log(hwfc
, AV_LOG_ERROR
, "Failed to release "
1803 "event: %d.\n", cle
);
1810 static int opencl_transfer_data_from(AVHWFramesContext
*hwfc
,
1811 AVFrame
*dst
, const AVFrame
*src
)
1813 OpenCLFramesContext
*priv
= hwfc
->internal
->priv
;
1814 cl_image_format image_format
;
1815 cl_image_desc image_desc
;
1817 size_t origin
[3] = { 0, 0, 0 };
1819 cl_event events
[AV_NUM_DATA_POINTERS
];
1822 if (dst
->format
!= hwfc
->sw_format
)
1823 return AVERROR(EINVAL
);
1826 err
= opencl_get_plane_format(hwfc
->sw_format
, p
,
1827 src
->width
, src
->height
,
1828 &image_format
, &image_desc
);
1830 if (err
== AVERROR(ENOENT
))
1835 if (!dst
->data
[p
]) {
1836 av_log(hwfc
, AV_LOG_ERROR
, "Plane %d missing on "
1837 "destination frame for transfer.\n", p
);
1838 err
= AVERROR(EINVAL
);
1842 region
[0] = image_desc
.image_width
;
1843 region
[1] = image_desc
.image_height
;
1846 cle
= clEnqueueReadImage(priv
->command_queue
,
1847 (cl_mem
)src
->data
[p
],
1848 CL_FALSE
, origin
, region
,
1849 dst
->linesize
[p
], 0,
1851 0, NULL
, &events
[p
]);
1852 if (cle
!= CL_SUCCESS
) {
1853 av_log(hwfc
, AV_LOG_ERROR
, "Failed to enqueue read of "
1854 "OpenCL image plane %d: %d.\n", p
, cle
);
1860 opencl_wait_events(hwfc
, events
, p
);
1865 static int opencl_transfer_data_to(AVHWFramesContext
*hwfc
,
1866 AVFrame
*dst
, const AVFrame
*src
)
1868 OpenCLFramesContext
*priv
= hwfc
->internal
->priv
;
1869 cl_image_format image_format
;
1870 cl_image_desc image_desc
;
1872 size_t origin
[3] = { 0, 0, 0 };
1874 cl_event events
[AV_NUM_DATA_POINTERS
];
1877 if (src
->format
!= hwfc
->sw_format
)
1878 return AVERROR(EINVAL
);
1881 err
= opencl_get_plane_format(hwfc
->sw_format
, p
,
1882 src
->width
, src
->height
,
1883 &image_format
, &image_desc
);
1885 if (err
== AVERROR(ENOENT
))
1890 if (!src
->data
[p
]) {
1891 av_log(hwfc
, AV_LOG_ERROR
, "Plane %d missing on "
1892 "source frame for transfer.\n", p
);
1893 err
= AVERROR(EINVAL
);
1897 region
[0] = image_desc
.image_width
;
1898 region
[1] = image_desc
.image_height
;
1901 cle
= clEnqueueWriteImage(priv
->command_queue
,
1902 (cl_mem
)dst
->data
[p
],
1903 CL_FALSE
, origin
, region
,
1904 src
->linesize
[p
], 0,
1906 0, NULL
, &events
[p
]);
1907 if (cle
!= CL_SUCCESS
) {
1908 av_log(hwfc
, AV_LOG_ERROR
, "Failed to enqueue write of "
1909 "OpenCL image plane %d: %d.\n", p
, cle
);
1915 opencl_wait_events(hwfc
, events
, p
);
1920 typedef struct OpenCLMapping
{
1921 // The mapped addresses for each plane.
1922 // The destination frame is not available when we unmap, so these
1923 // need to be stored separately.
1924 void *address
[AV_NUM_DATA_POINTERS
];
1927 static void opencl_unmap_frame(AVHWFramesContext
*hwfc
,
1928 HWMapDescriptor
*hwmap
)
1930 OpenCLFramesContext
*priv
= hwfc
->internal
->priv
;
1931 OpenCLMapping
*map
= hwmap
->priv
;
1932 cl_event events
[AV_NUM_DATA_POINTERS
];
1936 for (p
= e
= 0; p
< FF_ARRAY_ELEMS(map
->address
); p
++) {
1937 if (!map
->address
[p
])
1940 cle
= clEnqueueUnmapMemObject(priv
->command_queue
,
1941 (cl_mem
)hwmap
->source
->data
[p
],
1943 0, NULL
, &events
[e
]);
1944 if (cle
!= CL_SUCCESS
) {
1945 av_log(hwfc
, AV_LOG_ERROR
, "Failed to unmap OpenCL "
1946 "image plane %d: %d.\n", p
, cle
);
1951 opencl_wait_events(hwfc
, events
, e
);
1956 static int opencl_map_frame(AVHWFramesContext
*hwfc
, AVFrame
*dst
,
1957 const AVFrame
*src
, int flags
)
1959 OpenCLFramesContext
*priv
= hwfc
->internal
->priv
;
1960 cl_map_flags map_flags
;
1961 cl_image_format image_format
;
1962 cl_image_desc image_desc
;
1965 size_t origin
[3] = { 0, 0, 0 };
1968 cl_event events
[AV_NUM_DATA_POINTERS
];
1971 av_assert0(hwfc
->sw_format
== dst
->format
);
1973 if (flags
& AV_HWFRAME_MAP_OVERWRITE
&&
1974 !(flags
& AV_HWFRAME_MAP_READ
)) {
1975 // This is mutually exclusive with the read/write flags, so
1976 // there is no way to map with read here.
1977 map_flags
= CL_MAP_WRITE_INVALIDATE_REGION
;
1980 if (flags
& AV_HWFRAME_MAP_READ
)
1981 map_flags
|= CL_MAP_READ
;
1982 if (flags
& AV_HWFRAME_MAP_WRITE
)
1983 map_flags
|= CL_MAP_WRITE
;
1986 map
= av_mallocz(sizeof(*map
));
1988 return AVERROR(ENOMEM
);
1991 err
= opencl_get_plane_format(hwfc
->sw_format
, p
,
1992 src
->width
, src
->height
,
1993 &image_format
, &image_desc
);
1994 if (err
== AVERROR(ENOENT
))
1999 region
[0] = image_desc
.image_width
;
2000 region
[1] = image_desc
.image_height
;
2004 clEnqueueMapImage(priv
->command_queue
,
2005 (cl_mem
)src
->data
[p
],
2006 CL_FALSE
, map_flags
, origin
, region
,
2007 &row_pitch
, NULL
, 0, NULL
,
2009 if (!map
->address
[p
]) {
2010 av_log(hwfc
, AV_LOG_ERROR
, "Failed to map OpenCL "
2011 "image plane %d: %d.\n", p
, cle
);
2016 dst
->data
[p
] = map
->address
[p
];
2018 av_log(hwfc
, AV_LOG_DEBUG
, "Map plane %d (%p -> %p).\n",
2019 p
, src
->data
[p
], dst
->data
[p
]);
2022 err
= opencl_wait_events(hwfc
, events
, p
);
2026 err
= ff_hwframe_map_create(src
->hw_frames_ctx
, dst
, src
,
2027 &opencl_unmap_frame
, map
);
2031 dst
->width
= src
->width
;
2032 dst
->height
= src
->height
;
2037 for (p
= 0; p
< AV_NUM_DATA_POINTERS
; p
++) {
2038 if (!map
->address
[p
])
2040 clEnqueueUnmapMemObject(priv
->command_queue
,
2041 (cl_mem
)src
->data
[p
],
2043 0, NULL
, &events
[p
]);
2046 opencl_wait_events(hwfc
, events
, p
);
2051 #if HAVE_OPENCL_DRM_BEIGNET
2053 typedef struct DRMBeignetToOpenCLMapping
{
2055 AVDRMFrameDescriptor
*drm_desc
;
2057 AVOpenCLFrameDescriptor frame
;
2058 } DRMBeignetToOpenCLMapping
;
2060 static void opencl_unmap_from_drm_beignet(AVHWFramesContext
*dst_fc
,
2061 HWMapDescriptor
*hwmap
)
2063 DRMBeignetToOpenCLMapping
*mapping
= hwmap
->priv
;
2067 for (i
= 0; i
< mapping
->frame
.nb_planes
; i
++) {
2068 cle
= clReleaseMemObject(mapping
->frame
.planes
[i
]);
2069 if (cle
!= CL_SUCCESS
) {
2070 av_log(dst_fc
, AV_LOG_ERROR
, "Failed to release CL image "
2071 "of plane %d of DRM frame: %d.\n", i
, cle
);
2078 static int opencl_map_from_drm_beignet(AVHWFramesContext
*dst_fc
,
2079 AVFrame
*dst
, const AVFrame
*src
,
2082 AVOpenCLDeviceContext
*hwctx
= dst_fc
->device_ctx
->hwctx
;
2083 OpenCLDeviceContext
*priv
= dst_fc
->device_ctx
->internal
->priv
;
2084 DRMBeignetToOpenCLMapping
*mapping
;
2085 const AVDRMFrameDescriptor
*desc
;
2089 desc
= (const AVDRMFrameDescriptor
*)src
->data
[0];
2091 mapping
= av_mallocz(sizeof(*mapping
));
2093 return AVERROR(ENOMEM
);
2096 for (i
= 0; i
< desc
->nb_layers
; i
++) {
2097 const AVDRMLayerDescriptor
*layer
= &desc
->layers
[i
];
2098 for (j
= 0; j
< layer
->nb_planes
; j
++) {
2099 const AVDRMPlaneDescriptor
*plane
= &layer
->planes
[j
];
2100 const AVDRMObjectDescriptor
*object
=
2101 &desc
->objects
[plane
->object_index
];
2103 cl_import_image_info_intel image_info
= {
2105 .size
= object
->size
,
2106 .type
= CL_MEM_OBJECT_IMAGE2D
,
2107 .offset
= plane
->offset
,
2108 .row_pitch
= plane
->pitch
,
2110 cl_image_desc image_desc
;
2112 err
= opencl_get_plane_format(dst_fc
->sw_format
, p
,
2113 src
->width
, src
->height
,
2117 av_log(dst_fc
, AV_LOG_ERROR
, "DRM frame layer %d "
2118 "plane %d is not representable in OpenCL: %d.\n",
2122 image_info
.width
= image_desc
.image_width
;
2123 image_info
.height
= image_desc
.image_height
;
2125 mapping
->frame
.planes
[p
] =
2126 priv
->clCreateImageFromFdINTEL(hwctx
->context
,
2128 if (!mapping
->frame
.planes
[p
]) {
2129 av_log(dst_fc
, AV_LOG_ERROR
, "Failed to create CL image "
2130 "from layer %d plane %d of DRM frame: %d.\n",
2136 dst
->data
[p
] = (uint8_t*)mapping
->frame
.planes
[p
];
2137 mapping
->frame
.nb_planes
= ++p
;
2141 err
= ff_hwframe_map_create(dst
->hw_frames_ctx
, dst
, src
,
2142 &opencl_unmap_from_drm_beignet
,
2147 dst
->width
= src
->width
;
2148 dst
->height
= src
->height
;
2153 for (p
= 0; p
< mapping
->frame
.nb_planes
; p
++) {
2154 if (mapping
->frame
.planes
[p
])
2155 clReleaseMemObject(mapping
->frame
.planes
[p
]);
2158 memset(dst
->data
, 0, sizeof(dst
->data
));
2162 #if HAVE_OPENCL_VAAPI_BEIGNET
2164 static int opencl_map_from_vaapi(AVHWFramesContext
*dst_fc
,
2165 AVFrame
*dst
, const AVFrame
*src
,
2171 tmp
= av_frame_alloc();
2173 return AVERROR(ENOMEM
);
2175 tmp
->format
= AV_PIX_FMT_DRM_PRIME
;
2177 err
= av_hwframe_map(tmp
, src
, flags
);
2181 err
= opencl_map_from_drm_beignet(dst_fc
, dst
, tmp
, flags
);
2185 err
= ff_hwframe_map_replace(dst
, src
);
2188 av_frame_free(&tmp
);
2192 #endif /* HAVE_OPENCL_VAAPI_BEIGNET */
2193 #endif /* HAVE_OPENCL_DRM_BEIGNET */
2195 static inline cl_mem_flags
opencl_mem_flags_for_mapping(int map_flags
)
2197 if ((map_flags
& AV_HWFRAME_MAP_READ
) &&
2198 (map_flags
& AV_HWFRAME_MAP_WRITE
))
2199 return CL_MEM_READ_WRITE
;
2200 else if (map_flags
& AV_HWFRAME_MAP_READ
)
2201 return CL_MEM_READ_ONLY
;
2202 else if (map_flags
& AV_HWFRAME_MAP_WRITE
)
2203 return CL_MEM_WRITE_ONLY
;
2208 #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
2210 static void opencl_unmap_from_qsv(AVHWFramesContext
*dst_fc
,
2211 HWMapDescriptor
*hwmap
)
2213 AVOpenCLFrameDescriptor
*desc
= hwmap
->priv
;
2214 OpenCLDeviceContext
*device_priv
= dst_fc
->device_ctx
->internal
->priv
;
2215 OpenCLFramesContext
*frames_priv
= dst_fc
->internal
->priv
;
2220 av_log(dst_fc
, AV_LOG_DEBUG
, "Unmap QSV/VAAPI surface from OpenCL.\n");
2222 cle
= device_priv
->clEnqueueReleaseVA_APIMediaSurfacesINTEL(
2223 frames_priv
->command_queue
, desc
->nb_planes
, desc
->planes
,
2225 if (cle
!= CL_SUCCESS
) {
2226 av_log(dst_fc
, AV_LOG_ERROR
, "Failed to release surface "
2227 "handles: %d.\n", cle
);
2230 opencl_wait_events(dst_fc
, &event
, 1);
2232 for (p
= 0; p
< desc
->nb_planes
; p
++) {
2233 cle
= clReleaseMemObject(desc
->planes
[p
]);
2234 if (cle
!= CL_SUCCESS
) {
2235 av_log(dst_fc
, AV_LOG_ERROR
, "Failed to release CL "
2236 "image of plane %d of QSV/VAAPI surface: %d\n",
2244 static int opencl_map_from_qsv(AVHWFramesContext
*dst_fc
, AVFrame
*dst
,
2245 const AVFrame
*src
, int flags
)
2247 AVHWFramesContext
*src_fc
=
2248 (AVHWFramesContext
*)src
->hw_frames_ctx
->data
;
2249 AVOpenCLDeviceContext
*dst_dev
= dst_fc
->device_ctx
->hwctx
;
2250 OpenCLDeviceContext
*device_priv
= dst_fc
->device_ctx
->internal
->priv
;
2251 OpenCLFramesContext
*frames_priv
= dst_fc
->internal
->priv
;
2252 AVOpenCLFrameDescriptor
*desc
;
2253 VASurfaceID va_surface
;
2254 cl_mem_flags cl_flags
;
2260 if (src
->format
== AV_PIX_FMT_QSV
) {
2262 mfxFrameSurface1
*mfx_surface
= (mfxFrameSurface1
*)src
->data
[3];
2263 err
= ff_qsv_get_surface_base_handle(mfx_surface
,
2264 AV_HWDEVICE_TYPE_VAAPI
,
2268 va_surface
= *(VASurfaceID
*)base_handle
;
2271 if (src
->format
== AV_PIX_FMT_VAAPI
) {
2272 va_surface
= (VASurfaceID
)(uintptr_t)src
->data
[3];
2274 return AVERROR(ENOSYS
);
2277 cl_flags
= opencl_mem_flags_for_mapping(flags
);
2279 return AVERROR(EINVAL
);
2281 av_log(src_fc
, AV_LOG_DEBUG
, "Map QSV/VAAPI surface %#x to "
2282 "OpenCL.\n", va_surface
);
2284 desc
= av_mallocz(sizeof(*desc
));
2286 return AVERROR(ENOMEM
);
2288 // The cl_intel_va_api_media_sharing extension only supports NV12
2289 // surfaces, so for now there are always exactly two planes.
2290 desc
->nb_planes
= 2;
2292 for (p
= 0; p
< desc
->nb_planes
; p
++) {
2294 device_priv
->clCreateFromVA_APIMediaSurfaceINTEL(
2295 dst_dev
->context
, cl_flags
, &va_surface
, p
, &cle
);
2296 if (!desc
->planes
[p
]) {
2297 av_log(dst_fc
, AV_LOG_ERROR
, "Failed to create CL "
2298 "image from plane %d of QSV/VAAPI surface "
2299 "%#x: %d.\n", p
, va_surface
, cle
);
2304 dst
->data
[p
] = (uint8_t*)desc
->planes
[p
];
2307 cle
= device_priv
->clEnqueueAcquireVA_APIMediaSurfacesINTEL(
2308 frames_priv
->command_queue
, desc
->nb_planes
, desc
->planes
,
2310 if (cle
!= CL_SUCCESS
) {
2311 av_log(dst_fc
, AV_LOG_ERROR
, "Failed to acquire surface "
2312 "handles: %d.\n", cle
);
2317 err
= opencl_wait_events(dst_fc
, &event
, 1);
2321 err
= ff_hwframe_map_create(dst
->hw_frames_ctx
, dst
, src
,
2322 &opencl_unmap_from_qsv
, desc
);
2326 dst
->width
= src
->width
;
2327 dst
->height
= src
->height
;
2332 for (p
= 0; p
< desc
->nb_planes
; p
++)
2333 if (desc
->planes
[p
])
2334 clReleaseMemObject(desc
->planes
[p
]);
2336 memset(dst
->data
, 0, sizeof(dst
->data
));
2342 #if HAVE_OPENCL_DXVA2
2344 static void opencl_unmap_from_dxva2(AVHWFramesContext
*dst_fc
,
2345 HWMapDescriptor
*hwmap
)
2347 AVOpenCLFrameDescriptor
*desc
= hwmap
->priv
;
2348 OpenCLDeviceContext
*device_priv
= dst_fc
->device_ctx
->internal
->priv
;
2349 OpenCLFramesContext
*frames_priv
= dst_fc
->device_ctx
->internal
->priv
;
2353 av_log(dst_fc
, AV_LOG_DEBUG
, "Unmap DXVA2 surface from OpenCL.\n");
2355 cle
= device_priv
->clEnqueueReleaseDX9MediaSurfacesKHR(
2356 frames_priv
->command_queue
, desc
->nb_planes
, desc
->planes
,
2358 if (cle
!= CL_SUCCESS
) {
2359 av_log(dst_fc
, AV_LOG_ERROR
, "Failed to release surface "
2360 "handle: %d.\n", cle
);
2364 opencl_wait_events(dst_fc
, &event
, 1);
2367 static int opencl_map_from_dxva2(AVHWFramesContext
*dst_fc
, AVFrame
*dst
,
2368 const AVFrame
*src
, int flags
)
2370 AVHWFramesContext
*src_fc
=
2371 (AVHWFramesContext
*)src
->hw_frames_ctx
->data
;
2372 AVDXVA2FramesContext
*src_hwctx
= src_fc
->hwctx
;
2373 OpenCLDeviceContext
*device_priv
= dst_fc
->device_ctx
->internal
->priv
;
2374 OpenCLFramesContext
*frames_priv
= dst_fc
->internal
->priv
;
2375 AVOpenCLFrameDescriptor
*desc
;
2380 av_log(dst_fc
, AV_LOG_DEBUG
, "Map DXVA2 surface %p to "
2381 "OpenCL.\n", src
->data
[3]);
2383 for (i
= 0; i
< src_hwctx
->nb_surfaces
; i
++) {
2384 if (src_hwctx
->surfaces
[i
] == (IDirect3DSurface9
*)src
->data
[3])
2387 if (i
>= src_hwctx
->nb_surfaces
) {
2388 av_log(dst_fc
, AV_LOG_ERROR
, "Trying to map from a surface which "
2389 "is not in the mapped frames context.\n");
2390 return AVERROR(EINVAL
);
2393 desc
= &frames_priv
->mapped_frames
[i
];
2395 cle
= device_priv
->clEnqueueAcquireDX9MediaSurfacesKHR(
2396 frames_priv
->command_queue
, desc
->nb_planes
, desc
->planes
,
2398 if (cle
!= CL_SUCCESS
) {
2399 av_log(dst_fc
, AV_LOG_ERROR
, "Failed to acquire surface "
2400 "handle: %d.\n", cle
);
2401 return AVERROR(EIO
);
2404 err
= opencl_wait_events(dst_fc
, &event
, 1);
2408 for (i
= 0; i
< desc
->nb_planes
; i
++)
2409 dst
->data
[i
] = (uint8_t*)desc
->planes
[i
];
2411 err
= ff_hwframe_map_create(dst
->hw_frames_ctx
, dst
, src
,
2412 &opencl_unmap_from_dxva2
, desc
);
2416 dst
->width
= src
->width
;
2417 dst
->height
= src
->height
;
2422 cle
= device_priv
->clEnqueueReleaseDX9MediaSurfacesKHR(
2423 frames_priv
->command_queue
, desc
->nb_planes
, desc
->planes
,
2425 if (cle
== CL_SUCCESS
)
2426 opencl_wait_events(dst_fc
, &event
, 1);
2427 memset(dst
->data
, 0, sizeof(dst
->data
));
2431 static int opencl_frames_derive_from_dxva2(AVHWFramesContext
*dst_fc
,
2432 AVHWFramesContext
*src_fc
, int flags
)
2434 AVOpenCLDeviceContext
*dst_dev
= dst_fc
->device_ctx
->hwctx
;
2435 AVDXVA2FramesContext
*src_hwctx
= src_fc
->hwctx
;
2436 OpenCLDeviceContext
*device_priv
= dst_fc
->device_ctx
->internal
->priv
;
2437 OpenCLFramesContext
*frames_priv
= dst_fc
->internal
->priv
;
2438 cl_mem_flags cl_flags
;
2440 int err
, i
, p
, nb_planes
;
2442 if (src_fc
->sw_format
!= AV_PIX_FMT_NV12
) {
2443 av_log(dst_fc
, AV_LOG_ERROR
, "Only NV12 textures are supported "
2444 "for DXVA2 to OpenCL mapping.\n");
2445 return AVERROR(EINVAL
);
2449 if (src_fc
->initial_pool_size
== 0) {
2450 av_log(dst_fc
, AV_LOG_ERROR
, "Only fixed-size pools are supported "
2451 "for DXVA2 to OpenCL mapping.\n");
2452 return AVERROR(EINVAL
);
2455 cl_flags
= opencl_mem_flags_for_mapping(flags
);
2457 return AVERROR(EINVAL
);
2459 frames_priv
->nb_mapped_frames
= src_hwctx
->nb_surfaces
;
2461 frames_priv
->mapped_frames
=
2462 av_calloc(frames_priv
->nb_mapped_frames
,
2463 sizeof(*frames_priv
->mapped_frames
));
2464 if (!frames_priv
->mapped_frames
)
2465 return AVERROR(ENOMEM
);
2467 for (i
= 0; i
< frames_priv
->nb_mapped_frames
; i
++) {
2468 AVOpenCLFrameDescriptor
*desc
= &frames_priv
->mapped_frames
[i
];
2469 cl_dx9_surface_info_khr surface_info
= {
2470 .resource
= src_hwctx
->surfaces
[i
],
2471 .shared_handle
= NULL
,
2473 desc
->nb_planes
= nb_planes
;
2474 for (p
= 0; p
< nb_planes
; p
++) {
2476 device_priv
->clCreateFromDX9MediaSurfaceKHR(
2477 dst_dev
->context
, cl_flags
,
2478 device_priv
->dx9_media_adapter_type
,
2479 &surface_info
, p
, &cle
);
2480 if (!desc
->planes
[p
]) {
2481 av_log(dst_fc
, AV_LOG_ERROR
, "Failed to create CL "
2482 "image from plane %d of DXVA2 surface %d: %d.\n",
2493 for (i
= 0; i
< frames_priv
->nb_mapped_frames
; i
++) {
2494 AVOpenCLFrameDescriptor
*desc
= &frames_priv
->mapped_frames
[i
];
2495 for (p
= 0; p
< desc
->nb_planes
; p
++) {
2496 if (desc
->planes
[p
])
2497 clReleaseMemObject(desc
->planes
[p
]);
2500 av_freep(&frames_priv
->mapped_frames
);
2501 frames_priv
->nb_mapped_frames
= 0;
2507 #if HAVE_OPENCL_D3D11
2509 static void opencl_unmap_from_d3d11(AVHWFramesContext
*dst_fc
,
2510 HWMapDescriptor
*hwmap
)
2512 AVOpenCLFrameDescriptor
*desc
= hwmap
->priv
;
2513 OpenCLDeviceContext
*device_priv
= dst_fc
->device_ctx
->internal
->priv
;
2514 OpenCLFramesContext
*frames_priv
= dst_fc
->device_ctx
->internal
->priv
;
2518 cle
= device_priv
->clEnqueueReleaseD3D11ObjectsKHR(
2519 frames_priv
->command_queue
, desc
->nb_planes
, desc
->planes
,
2521 if (cle
!= CL_SUCCESS
) {
2522 av_log(dst_fc
, AV_LOG_ERROR
, "Failed to release surface "
2523 "handle: %d.\n", cle
);
2526 opencl_wait_events(dst_fc
, &event
, 1);
2529 static int opencl_map_from_d3d11(AVHWFramesContext
*dst_fc
, AVFrame
*dst
,
2530 const AVFrame
*src
, int flags
)
2532 OpenCLDeviceContext
*device_priv
= dst_fc
->device_ctx
->internal
->priv
;
2533 OpenCLFramesContext
*frames_priv
= dst_fc
->internal
->priv
;
2534 AVOpenCLFrameDescriptor
*desc
;
2539 index
= (intptr_t)src
->data
[1];
2540 if (index
>= frames_priv
->nb_mapped_frames
) {
2541 av_log(dst_fc
, AV_LOG_ERROR
, "Texture array index out of range for "
2542 "mapping: %d >= %d.\n", index
, frames_priv
->nb_mapped_frames
);
2543 return AVERROR(EINVAL
);
2546 av_log(dst_fc
, AV_LOG_DEBUG
, "Map D3D11 texture %d to OpenCL.\n",
2549 desc
= &frames_priv
->mapped_frames
[index
];
2551 cle
= device_priv
->clEnqueueAcquireD3D11ObjectsKHR(
2552 frames_priv
->command_queue
, desc
->nb_planes
, desc
->planes
,
2554 if (cle
!= CL_SUCCESS
) {
2555 av_log(dst_fc
, AV_LOG_ERROR
, "Failed to acquire surface "
2556 "handle: %d.\n", cle
);
2557 return AVERROR(EIO
);
2560 err
= opencl_wait_events(dst_fc
, &event
, 1);
2564 for (i
= 0; i
< desc
->nb_planes
; i
++)
2565 dst
->data
[i
] = (uint8_t*)desc
->planes
[i
];
2567 err
= ff_hwframe_map_create(dst
->hw_frames_ctx
, dst
, src
,
2568 &opencl_unmap_from_d3d11
, desc
);
2572 dst
->width
= src
->width
;
2573 dst
->height
= src
->height
;
2578 cle
= device_priv
->clEnqueueReleaseD3D11ObjectsKHR(
2579 frames_priv
->command_queue
, desc
->nb_planes
, desc
->planes
,
2581 if (cle
== CL_SUCCESS
)
2582 opencl_wait_events(dst_fc
, &event
, 1);
2583 memset(dst
->data
, 0, sizeof(dst
->data
));
2587 static int opencl_frames_derive_from_d3d11(AVHWFramesContext
*dst_fc
,
2588 AVHWFramesContext
*src_fc
, int flags
)
2590 AVOpenCLDeviceContext
*dst_dev
= dst_fc
->device_ctx
->hwctx
;
2591 AVD3D11VAFramesContext
*src_hwctx
= src_fc
->hwctx
;
2592 OpenCLDeviceContext
*device_priv
= dst_fc
->device_ctx
->internal
->priv
;
2593 OpenCLFramesContext
*frames_priv
= dst_fc
->internal
->priv
;
2594 cl_mem_flags cl_flags
;
2596 int err
, i
, p
, nb_planes
;
2598 if (src_fc
->sw_format
!= AV_PIX_FMT_NV12
) {
2599 av_log(dst_fc
, AV_LOG_ERROR
, "Only NV12 textures are supported "
2600 "for D3D11 to OpenCL mapping.\n");
2601 return AVERROR(EINVAL
);
2605 if (src_fc
->initial_pool_size
== 0) {
2606 av_log(dst_fc
, AV_LOG_ERROR
, "Only fixed-size pools are supported "
2607 "for D3D11 to OpenCL mapping.\n");
2608 return AVERROR(EINVAL
);
2611 cl_flags
= opencl_mem_flags_for_mapping(flags
);
2613 return AVERROR(EINVAL
);
2615 frames_priv
->nb_mapped_frames
= src_fc
->initial_pool_size
;
2617 frames_priv
->mapped_frames
=
2618 av_calloc(frames_priv
->nb_mapped_frames
,
2619 sizeof(*frames_priv
->mapped_frames
));
2620 if (!frames_priv
->mapped_frames
)
2621 return AVERROR(ENOMEM
);
2623 for (i
= 0; i
< frames_priv
->nb_mapped_frames
; i
++) {
2624 AVOpenCLFrameDescriptor
*desc
= &frames_priv
->mapped_frames
[i
];
2625 desc
->nb_planes
= nb_planes
;
2626 for (p
= 0; p
< nb_planes
; p
++) {
2627 UINT subresource
= 2 * i
+ p
;
2630 device_priv
->clCreateFromD3D11Texture2DKHR(
2631 dst_dev
->context
, cl_flags
, src_hwctx
->texture
,
2633 if (!desc
->planes
[p
]) {
2634 av_log(dst_fc
, AV_LOG_ERROR
, "Failed to create CL "
2635 "image from plane %d of D3D texture "
2636 "index %d (subresource %u): %d.\n",
2637 p
, i
, (unsigned int)subresource
, cle
);
2647 for (i
= 0; i
< frames_priv
->nb_mapped_frames
; i
++) {
2648 AVOpenCLFrameDescriptor
*desc
= &frames_priv
->mapped_frames
[i
];
2649 for (p
= 0; p
< desc
->nb_planes
; p
++) {
2650 if (desc
->planes
[p
])
2651 clReleaseMemObject(desc
->planes
[p
]);
2654 av_freep(&frames_priv
->mapped_frames
);
2655 frames_priv
->nb_mapped_frames
= 0;
2661 #if HAVE_OPENCL_DRM_ARM
2663 typedef struct DRMARMtoOpenCLMapping
{
2665 cl_mem object_buffers
[AV_DRM_MAX_PLANES
];
2667 cl_mem plane_images
[AV_DRM_MAX_PLANES
];
2668 } DRMARMtoOpenCLMapping
;
2670 static void opencl_unmap_from_drm_arm(AVHWFramesContext
*dst_fc
,
2671 HWMapDescriptor
*hwmap
)
2673 DRMARMtoOpenCLMapping
*mapping
= hwmap
->priv
;
2676 for (i
= 0; i
< mapping
->nb_planes
; i
++)
2677 clReleaseMemObject(mapping
->plane_images
[i
]);
2679 for (i
= 0; i
< mapping
->nb_objects
; i
++)
2680 clReleaseMemObject(mapping
->object_buffers
[i
]);
2685 static int opencl_map_from_drm_arm(AVHWFramesContext
*dst_fc
, AVFrame
*dst
,
2686 const AVFrame
*src
, int flags
)
2688 AVHWFramesContext
*src_fc
=
2689 (AVHWFramesContext
*)src
->hw_frames_ctx
->data
;
2690 AVOpenCLDeviceContext
*dst_dev
= dst_fc
->device_ctx
->hwctx
;
2691 const AVDRMFrameDescriptor
*desc
;
2692 DRMARMtoOpenCLMapping
*mapping
= NULL
;
2693 cl_mem_flags cl_flags
;
2694 const cl_import_properties_arm props
[3] = {
2695 CL_IMPORT_TYPE_ARM
, CL_IMPORT_TYPE_DMA_BUF_ARM
, 0,
2700 desc
= (const AVDRMFrameDescriptor
*)src
->data
[0];
2702 cl_flags
= opencl_mem_flags_for_mapping(flags
);
2704 return AVERROR(EINVAL
);
2706 mapping
= av_mallocz(sizeof(*mapping
));
2708 return AVERROR(ENOMEM
);
2710 mapping
->nb_objects
= desc
->nb_objects
;
2711 for (i
= 0; i
< desc
->nb_objects
; i
++) {
2712 int fd
= desc
->objects
[i
].fd
;
2714 av_log(dst_fc
, AV_LOG_DEBUG
, "Map DRM PRIME fd %d to OpenCL.\n", fd
);
2716 if (desc
->objects
[i
].format_modifier
) {
2717 av_log(dst_fc
, AV_LOG_DEBUG
, "Warning: object %d fd %d has "
2718 "nonzero format modifier %"PRId64
", result may not "
2719 "be as expected.\n", i
, fd
,
2720 desc
->objects
[i
].format_modifier
);
2723 mapping
->object_buffers
[i
] =
2724 clImportMemoryARM(dst_dev
->context
, cl_flags
, props
,
2725 &fd
, desc
->objects
[i
].size
, &cle
);
2726 if (!mapping
->object_buffers
[i
]) {
2727 av_log(dst_fc
, AV_LOG_ERROR
, "Failed to create CL buffer "
2728 "from object %d (fd %d, size %"SIZE_SPECIFIER
") of DRM frame: %d.\n",
2729 i
, fd
, desc
->objects
[i
].size
, cle
);
2735 mapping
->nb_planes
= 0;
2736 for (i
= 0; i
< desc
->nb_layers
; i
++) {
2737 const AVDRMLayerDescriptor
*layer
= &desc
->layers
[i
];
2739 for (j
= 0; j
< layer
->nb_planes
; j
++) {
2740 const AVDRMPlaneDescriptor
*plane
= &layer
->planes
[j
];
2741 cl_mem plane_buffer
;
2742 cl_image_format image_format
;
2743 cl_image_desc image_desc
;
2744 cl_buffer_region region
;
2745 int p
= mapping
->nb_planes
;
2747 err
= opencl_get_plane_format(src_fc
->sw_format
, p
,
2748 src_fc
->width
, src_fc
->height
,
2749 &image_format
, &image_desc
);
2751 av_log(dst_fc
, AV_LOG_ERROR
, "Invalid plane %d (DRM "
2752 "layer %d plane %d): %d.\n", p
, i
, j
, err
);
2756 region
.origin
= plane
->offset
;
2757 region
.size
= image_desc
.image_row_pitch
*
2758 image_desc
.image_height
;
2761 clCreateSubBuffer(mapping
->object_buffers
[plane
->object_index
],
2763 CL_BUFFER_CREATE_TYPE_REGION
,
2765 if (!plane_buffer
) {
2766 av_log(dst_fc
, AV_LOG_ERROR
, "Failed to create sub-buffer "
2767 "for plane %d: %d.\n", p
, cle
);
2772 image_desc
.buffer
= plane_buffer
;
2774 mapping
->plane_images
[p
] =
2775 clCreateImage(dst_dev
->context
, cl_flags
,
2776 &image_format
, &image_desc
, NULL
, &cle
);
2778 // Unreference the sub-buffer immediately - we don't need it
2779 // directly and a reference is held by the image.
2780 clReleaseMemObject(plane_buffer
);
2782 if (!mapping
->plane_images
[p
]) {
2783 av_log(dst_fc
, AV_LOG_ERROR
, "Failed to create image "
2784 "for plane %d: %d.\n", p
, cle
);
2789 ++mapping
->nb_planes
;
2793 for (i
= 0; i
< mapping
->nb_planes
; i
++)
2794 dst
->data
[i
] = (uint8_t*)mapping
->plane_images
[i
];
2796 err
= ff_hwframe_map_create(dst
->hw_frames_ctx
, dst
, src
,
2797 &opencl_unmap_from_drm_arm
, mapping
);
2801 dst
->width
= src
->width
;
2802 dst
->height
= src
->height
;
2807 for (i
= 0; i
< mapping
->nb_planes
; i
++) {
2808 clReleaseMemObject(mapping
->plane_images
[i
]);
2810 for (i
= 0; i
< mapping
->nb_objects
; i
++) {
2811 if (mapping
->object_buffers
[i
])
2812 clReleaseMemObject(mapping
->object_buffers
[i
]);
2815 memset(dst
->data
, 0, sizeof(dst
->data
));
2821 static int opencl_map_from(AVHWFramesContext
*hwfc
, AVFrame
*dst
,
2822 const AVFrame
*src
, int flags
)
2824 av_assert0(src
->format
== AV_PIX_FMT_OPENCL
);
2825 if (hwfc
->sw_format
!= dst
->format
)
2826 return AVERROR(ENOSYS
);
2827 return opencl_map_frame(hwfc
, dst
, src
, flags
);
2830 static int opencl_map_to(AVHWFramesContext
*hwfc
, AVFrame
*dst
,
2831 const AVFrame
*src
, int flags
)
2833 av_unused OpenCLDeviceContext
*priv
= hwfc
->device_ctx
->internal
->priv
;
2834 av_assert0(dst
->format
== AV_PIX_FMT_OPENCL
);
2835 switch (src
->format
) {
2836 #if HAVE_OPENCL_DRM_BEIGNET
2837 case AV_PIX_FMT_DRM_PRIME
:
2838 if (priv
->beignet_drm_mapping_usable
)
2839 return opencl_map_from_drm_beignet(hwfc
, dst
, src
, flags
);
2841 #if HAVE_OPENCL_VAAPI_BEIGNET
2842 case AV_PIX_FMT_VAAPI
:
2843 if (priv
->beignet_drm_mapping_usable
)
2844 return opencl_map_from_vaapi(hwfc
, dst
, src
, flags
);
2846 #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
2847 case AV_PIX_FMT_QSV
:
2848 case AV_PIX_FMT_VAAPI
:
2849 if (priv
->qsv_mapping_usable
)
2850 return opencl_map_from_qsv(hwfc
, dst
, src
, flags
);
2852 #if HAVE_OPENCL_DXVA2
2853 case AV_PIX_FMT_DXVA2_VLD
:
2854 if (priv
->dxva2_mapping_usable
)
2855 return opencl_map_from_dxva2(hwfc
, dst
, src
, flags
);
2857 #if HAVE_OPENCL_D3D11
2858 case AV_PIX_FMT_D3D11
:
2859 if (priv
->d3d11_mapping_usable
)
2860 return opencl_map_from_d3d11(hwfc
, dst
, src
, flags
);
2862 #if HAVE_OPENCL_DRM_ARM
2863 case AV_PIX_FMT_DRM_PRIME
:
2864 if (priv
->drm_arm_mapping_usable
)
2865 return opencl_map_from_drm_arm(hwfc
, dst
, src
, flags
);
2868 return AVERROR(ENOSYS
);
2871 static int opencl_frames_derive_to(AVHWFramesContext
*dst_fc
,
2872 AVHWFramesContext
*src_fc
, int flags
)
2874 av_unused OpenCLDeviceContext
*priv
= dst_fc
->device_ctx
->internal
->priv
;
2875 switch (src_fc
->device_ctx
->type
) {
2876 #if HAVE_OPENCL_DRM_BEIGNET
2877 case AV_HWDEVICE_TYPE_DRM
:
2878 if (!priv
->beignet_drm_mapping_usable
)
2879 return AVERROR(ENOSYS
);
2882 #if HAVE_OPENCL_VAAPI_BEIGNET
2883 case AV_HWDEVICE_TYPE_VAAPI
:
2884 if (!priv
->beignet_drm_mapping_usable
)
2885 return AVERROR(ENOSYS
);
2888 #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
2889 case AV_HWDEVICE_TYPE_QSV
:
2890 case AV_HWDEVICE_TYPE_VAAPI
:
2891 if (!priv
->qsv_mapping_usable
)
2892 return AVERROR(ENOSYS
);
2895 #if HAVE_OPENCL_DXVA2
2896 case AV_HWDEVICE_TYPE_DXVA2
:
2897 if (!priv
->dxva2_mapping_usable
)
2898 return AVERROR(ENOSYS
);
2901 err
= opencl_frames_derive_from_dxva2(dst_fc
, src_fc
, flags
);
2907 #if HAVE_OPENCL_D3D11
2908 case AV_HWDEVICE_TYPE_D3D11VA
:
2909 if (!priv
->d3d11_mapping_usable
)
2910 return AVERROR(ENOSYS
);
2913 err
= opencl_frames_derive_from_d3d11(dst_fc
, src_fc
, flags
);
2919 #if HAVE_OPENCL_DRM_ARM
2920 case AV_HWDEVICE_TYPE_DRM
:
2921 if (!priv
->drm_arm_mapping_usable
)
2922 return AVERROR(ENOSYS
);
2926 return AVERROR(ENOSYS
);
2928 return opencl_frames_init_command_queue(dst_fc
);
2931 const HWContextType ff_hwcontext_type_opencl
= {
2932 .type
= AV_HWDEVICE_TYPE_OPENCL
,
2935 .device_hwctx_size
= sizeof(AVOpenCLDeviceContext
),
2936 .device_priv_size
= sizeof(OpenCLDeviceContext
),
2937 .frames_hwctx_size
= sizeof(AVOpenCLFramesContext
),
2938 .frames_priv_size
= sizeof(OpenCLFramesContext
),
2940 .device_create
= &opencl_device_create
,
2941 .device_derive
= &opencl_device_derive
,
2942 .device_init
= &opencl_device_init
,
2943 .device_uninit
= &opencl_device_uninit
,
2945 .frames_get_constraints
= &opencl_frames_get_constraints
,
2946 .frames_init
= &opencl_frames_init
,
2947 .frames_uninit
= &opencl_frames_uninit
,
2948 .frames_get_buffer
= &opencl_get_buffer
,
2950 .transfer_get_formats
= &opencl_transfer_get_formats
,
2951 .transfer_data_to
= &opencl_transfer_data_to
,
2952 .transfer_data_from
= &opencl_transfer_data_from
,
2954 .map_from
= &opencl_map_from
,
2955 .map_to
= &opencl_map_to
,
2956 .frames_derive_to
= &opencl_frames_derive_to
,
2958 .pix_fmts
= (const enum AVPixelFormat
[]) {