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 <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_VIDEOTOOLBOX
76 #include <OpenCL/cl_gl_ext.h>
77 #include <VideoToolbox/VideoToolbox.h>
80 #if HAVE_OPENCL_VAAPI_INTEL_MEDIA && CONFIG_LIBMFX
81 extern int ff_qsv_get_surface_base_handle(mfxFrameSurface1
*surf
,
82 enum AVHWDeviceType base_dev_typ
,
87 typedef struct OpenCLDeviceContext
{
89 * The public AVOpenCLDeviceContext. See hwcontext_opencl.h for it.
91 AVOpenCLDeviceContext p
;
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
;
98 // The platform the context exists on. This is needed to query and
99 // retrieve extension functions.
100 cl_platform_id platform_id
;
102 // Platform/device-specific functions.
103 #if HAVE_OPENCL_DRM_BEIGNET
104 int beignet_drm_mapping_usable
;
105 clCreateImageFromFdINTEL_fn clCreateImageFromFdINTEL
;
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
;
118 #if HAVE_OPENCL_DXVA2
119 int dxva2_mapping_usable
;
120 cl_dx9_media_adapter_type_khr dx9_media_adapter_type
;
122 clCreateFromDX9MediaSurfaceKHR_fn
123 clCreateFromDX9MediaSurfaceKHR
;
124 clEnqueueAcquireDX9MediaSurfacesKHR_fn
125 clEnqueueAcquireDX9MediaSurfacesKHR
;
126 clEnqueueReleaseDX9MediaSurfacesKHR_fn
127 clEnqueueReleaseDX9MediaSurfacesKHR
;
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
;
140 #if HAVE_OPENCL_DRM_ARM
141 int drm_arm_mapping_usable
;
143 } OpenCLDeviceContext
;
145 typedef struct OpenCLFramesContext
{
147 * The public AVOpenCLFramesContext. See hwcontext_opencl.h for it.
149 AVOpenCLFramesContext p
;
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
155 cl_command_queue command_queue
;
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
161 int nb_mapped_frames
;
162 AVOpenCLFrameDescriptor
*mapped_frames
;
164 } OpenCLFramesContext
;
167 static void CL_CALLBACK
opencl_error_callback(const char *errinfo
,
168 const void *private_info
,
172 AVHWDeviceContext
*ctx
= user_data
;
173 av_log(ctx
, AV_LOG_ERROR
, "OpenCL error: %s\n", errinfo
);
176 static void opencl_device_free(AVHWDeviceContext
*hwdev
)
178 AVOpenCLDeviceContext
*hwctx
= hwdev
->hwctx
;
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
);
190 cl_platform_info name
;
191 } opencl_platform_params
[] = {
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
},
202 } opencl_device_params
[] = {
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
},
214 } opencl_device_types
[] = {
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
},
223 static char *opencl_get_platform_string(cl_platform_id platform_id
,
224 cl_platform_info key
)
229 cle
= clGetPlatformInfo(platform_id
, key
, 0, NULL
, &size
);
230 if (cle
!= CL_SUCCESS
)
232 str
= av_malloc(size
);
235 cle
= clGetPlatformInfo(platform_id
, key
, size
, str
, &size
);
236 if (cle
!= CL_SUCCESS
) {
240 av_assert0(strlen(str
) + 1 == size
);
244 static char *opencl_get_device_string(cl_device_id device_id
,
250 cle
= clGetDeviceInfo(device_id
, key
, 0, NULL
, &size
);
251 if (cle
!= CL_SUCCESS
)
253 str
= av_malloc(size
);
256 cle
= clGetDeviceInfo(device_id
, key
, size
, str
, &size
);
257 if (cle
!= CL_SUCCESS
) {
261 av_assert0(strlen(str
) + 1== size
);
265 static int opencl_check_platform_extension(cl_platform_id platform_id
,
270 str
= opencl_get_platform_string(platform_id
,
271 CL_PLATFORM_EXTENSIONS
);
272 if (str
&& strstr(str
, name
))
278 static int opencl_check_device_extension(cl_device_id device_id
,
283 str
= opencl_get_device_string(device_id
,
284 CL_DEVICE_EXTENSIONS
);
285 if (str
&& strstr(str
, name
))
291 av_unused
static int opencl_check_extension(AVHWDeviceContext
*hwdev
,
294 OpenCLDeviceContext
*priv
= hwdev
->hwctx
;
295 AVOpenCLDeviceContext
*hwctx
= &priv
->p
;
297 if (opencl_check_platform_extension(priv
->platform_id
, name
)) {
298 av_log(hwdev
, AV_LOG_DEBUG
,
299 "%s found as platform extension.\n", name
);
303 if (opencl_check_device_extension(hwctx
->device_id
, name
)) {
304 av_log(hwdev
, AV_LOG_DEBUG
,
305 "%s found as device extension.\n", name
);
312 static int opencl_enumerate_platforms(AVHWDeviceContext
*hwdev
,
313 cl_uint
*nb_platforms
,
314 cl_platform_id
**platforms
,
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
);
325 av_log(hwdev
, AV_LOG_DEBUG
, "%u OpenCL platforms found.\n",
328 *platforms
= av_malloc_array(*nb_platforms
, sizeof(**platforms
));
330 return AVERROR(ENOMEM
);
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
);
337 return AVERROR(ENODEV
);
343 static int opencl_filter_platform(AVHWDeviceContext
*hwdev
,
344 cl_platform_id platform_id
,
345 const char *platform_name
,
348 AVDictionary
*opts
= context
;
349 const AVDictionaryEntry
*param
;
353 for (i
= 0; i
< FF_ARRAY_ELEMS(opencl_platform_params
); i
++) {
354 param
= av_dict_get(opts
, opencl_platform_params
[i
].key
,
359 str
= opencl_get_platform_string(platform_id
,
360 opencl_platform_params
[i
].name
);
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
;
367 if (!av_stristr(str
, param
->value
)) {
368 av_log(hwdev
, AV_LOG_DEBUG
, "%s does not match (\"%s\").\n",
378 static int opencl_enumerate_devices(AVHWDeviceContext
*hwdev
,
379 cl_platform_id platform_id
,
380 const char *platform_name
,
382 cl_device_id
**devices
,
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
);
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
);
399 av_log(hwdev
, AV_LOG_DEBUG
, "%u OpenCL devices found on "
400 "platform \"%s\".\n", *nb_devices
, platform_name
);
402 *devices
= av_malloc_array(*nb_devices
, sizeof(**devices
));
404 return AVERROR(ENOMEM
);
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
);
412 return AVERROR(ENODEV
);
418 static int opencl_filter_device(AVHWDeviceContext
*hwdev
,
419 cl_device_id device_id
,
420 const char *device_name
,
423 AVDictionary
*opts
= context
;
424 const AVDictionaryEntry
*param
;
428 param
= av_dict_get(opts
, "device_type", NULL
, 0);
430 cl_device_type match_type
= 0, device_type
;
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
;
440 av_log(hwdev
, AV_LOG_ERROR
, "Unknown device type %s.\n",
442 return AVERROR(EINVAL
);
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
;
453 if (!(device_type
& match_type
)) {
454 av_log(hwdev
, AV_LOG_DEBUG
, "device_type does not match.\n");
459 for (i
= 0; i
< FF_ARRAY_ELEMS(opencl_device_params
); i
++) {
460 param
= av_dict_get(opts
, opencl_device_params
[i
].key
,
465 str
= opencl_get_device_string(device_id
,
466 opencl_device_params
[i
].name
);
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
;
473 if (!av_stristr(str
, param
->value
)) {
474 av_log(hwdev
, AV_LOG_DEBUG
, "%s does not match (\"%s\").\n",
484 typedef struct OpenCLDeviceSelector
{
488 int (*enumerate_platforms
)(AVHWDeviceContext
*hwdev
,
489 cl_uint
*nb_platforms
,
490 cl_platform_id
**platforms
,
492 int (*filter_platform
) (AVHWDeviceContext
*hwdev
,
493 cl_platform_id platform_id
,
494 const char *platform_name
,
496 int (*enumerate_devices
) (AVHWDeviceContext
*hwdev
,
497 cl_platform_id platform_id
,
498 const char *platform_name
,
500 cl_device_id
**devices
,
502 int (*filter_device
) (AVHWDeviceContext
*hwdev
,
503 cl_device_id device_id
,
504 const char *device_name
,
506 } OpenCLDeviceSelector
;
508 static int opencl_device_create_internal(AVHWDeviceContext
*hwdev
,
509 const OpenCLDeviceSelector
*selector
,
510 cl_context_properties
*props
)
512 cl_uint nb_platforms
;
513 cl_platform_id
*platforms
= NULL
;
514 cl_platform_id platform_id
;
516 cl_device_id
*devices
= NULL
;
517 AVOpenCLDeviceContext
*hwctx
= hwdev
->hwctx
;
519 cl_context_properties default_props
[3];
520 char *platform_name_src
= NULL
,
521 *device_name_src
= NULL
;
522 int err
, found
, p
, d
;
524 av_assert0(selector
->enumerate_platforms
&&
525 selector
->enumerate_devices
);
527 err
= selector
->enumerate_platforms(hwdev
, &nb_platforms
, &platforms
,
533 for (p
= 0; p
< nb_platforms
; p
++) {
534 const char *platform_name
;
536 if (selector
->platform_index
>= 0 &&
537 selector
->platform_index
!= p
)
540 av_freep(&platform_name_src
);
541 platform_name_src
= opencl_get_platform_string(platforms
[p
],
543 if (platform_name_src
)
544 platform_name
= platform_name_src
;
546 platform_name
= "Unknown Platform";
548 if (selector
->filter_platform
) {
549 err
= selector
->filter_platform(hwdev
, platforms
[p
],
558 err
= selector
->enumerate_devices(hwdev
, platforms
[p
], platform_name
,
559 &nb_devices
, &devices
,
564 for (d
= 0; d
< nb_devices
; d
++) {
565 const char *device_name
;
567 if (selector
->device_index
>= 0 &&
568 selector
->device_index
!= d
)
571 av_freep(&device_name_src
);
572 device_name_src
= opencl_get_device_string(devices
[d
],
575 device_name
= device_name_src
;
577 device_name
= "Unknown Device";
579 if (selector
->filter_device
) {
580 err
= selector
->filter_device(hwdev
, devices
[d
],
589 av_log(hwdev
, AV_LOG_VERBOSE
, "%d.%d: %s / %s\n", p
, d
,
590 platform_name
, device_name
);
593 platform_id
= platforms
[p
];
594 hwctx
->device_id
= devices
[d
];
601 av_log(hwdev
, AV_LOG_ERROR
, "No matching devices found.\n");
602 err
= AVERROR(ENODEV
);
606 av_log(hwdev
, AV_LOG_ERROR
, "More than one matching device found.\n");
607 err
= AVERROR(ENODEV
);
612 props
= default_props
;
613 default_props
[0] = CL_CONTEXT_PLATFORM
;
614 default_props
[1] = (intptr_t)platform_id
;
615 default_props
[2] = 0;
617 if (props
[0] == CL_CONTEXT_PLATFORM
&& props
[1] == 0)
618 props
[1] = (intptr_t)platform_id
;
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: "
626 err
= AVERROR(ENODEV
);
630 hwdev
->free
= &opencl_device_free
;
634 av_freep(&platform_name_src
);
635 av_freep(&device_name_src
);
636 av_freep(&platforms
);
641 static int opencl_device_create(AVHWDeviceContext
*hwdev
, const char *device
,
642 AVDictionary
*opts
, int flags
)
644 OpenCLDeviceSelector selector
= {
646 .enumerate_platforms
= &opencl_enumerate_platforms
,
647 .filter_platform
= &opencl_filter_platform
,
648 .enumerate_devices
= &opencl_enumerate_devices
,
649 .filter_device
= &opencl_filter_device
,
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
);
658 ret
= sscanf(device
, "%d.%d", &p
, &d
);
660 av_log(hwdev
, AV_LOG_ERROR
, "Invalid OpenCL platform/device "
661 "index specification \"%s\".\n", device
);
662 return AVERROR(EINVAL
);
664 selector
.platform_index
= p
;
665 selector
.device_index
= d
;
667 selector
.platform_index
= -1;
668 selector
.device_index
= -1;
671 return opencl_device_create_internal(hwdev
, &selector
, NULL
);
674 static int opencl_device_init(AVHWDeviceContext
*hwdev
)
676 OpenCLDeviceContext
*priv
= hwdev
->hwctx
;
677 AVOpenCLDeviceContext
*hwctx
= &priv
->p
;
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
);
687 priv
->command_queue
= hwctx
->command_queue
;
689 priv
->command_queue
= clCreateCommandQueue(hwctx
->context
,
692 if (!priv
->command_queue
) {
693 av_log(hwdev
, AV_LOG_ERROR
, "Failed to create internal "
694 "command queue: %d.\n", cle
);
699 cle
= clGetDeviceInfo(hwctx
->device_id
, CL_DEVICE_PLATFORM
,
700 sizeof(priv
->platform_id
), &priv
->platform_id
,
702 if (cle
!= CL_SUCCESS
) {
703 av_log(hwdev
, AV_LOG_ERROR
, "Failed to determine the OpenCL "
704 "platform containing the device.\n");
708 #define CL_FUNC(name, desc) do { \
711 priv->name = clGetExtensionFunctionAddressForPlatform( \
712 priv->platform_id, #name); \
714 av_log(hwdev, AV_LOG_VERBOSE, \
715 desc " function not found (%s).\n", #name); \
718 av_log(hwdev, AV_LOG_VERBOSE, \
719 desc " function found (%s).\n", #name); \
723 #if HAVE_OPENCL_DRM_BEIGNET
727 CL_FUNC(clCreateImageFromFdINTEL
,
728 "Beignet DRM to OpenCL image mapping");
731 av_log(hwdev
, AV_LOG_WARNING
, "Beignet DRM to OpenCL "
732 "mapping not usable.\n");
733 priv
->beignet_drm_mapping_usable
= 0;
735 priv
->beignet_drm_mapping_usable
= 1;
740 #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
743 cl_context_properties
*props
= NULL
;
744 VADisplay va_display
;
745 const char *va_ext
= "cl_intel_va_api_media_sharing";
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
);
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
);
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");
768 props
= av_malloc(props_size
);
770 return AVERROR(ENOMEM
);
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
);
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];
788 av_log(hwdev
, AV_LOG_VERBOSE
, "Media sharing must be "
789 "enabled on context creation to use QSV to "
790 "OpenCL mapping.\n");
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");
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");
809 av_log(hwdev
, AV_LOG_WARNING
, "QSV to OpenCL mapping "
811 priv
->qsv_mapping_usable
= 0;
813 priv
->qsv_mapping_usable
= 1;
819 #if HAVE_OPENCL_DXVA2
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");
831 av_log(hwdev
, AV_LOG_WARNING
, "DXVA2 to OpenCL mapping "
833 priv
->dxva2_mapping_usable
= 0;
835 priv
->dx9_media_adapter_type
= CL_ADAPTER_D3D9EX_KHR
;
836 priv
->dxva2_mapping_usable
= 1;
841 #if HAVE_OPENCL_D3D11
843 const char *d3d11_ext
= "cl_khr_d3d11_sharing";
844 const char *nv12_ext
= "cl_intel_d3d11_nv12_media_sharing";
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
);
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
);
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");
865 av_log(hwdev
, AV_LOG_WARNING
, "D3D11 to OpenCL mapping "
867 priv
->d3d11_mapping_usable
= 0;
869 priv
->d3d11_mapping_usable
= 1;
874 #if HAVE_OPENCL_DRM_ARM
876 const char *drm_arm_ext
= "cl_arm_import_memory";
877 const char *image_ext
= "cl_khr_image2d_from_buffer";
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",
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",
893 // clImportMemoryARM() is linked statically.
896 av_log(hwdev
, AV_LOG_WARNING
, "DRM to OpenCL mapping on ARM "
898 priv
->drm_arm_mapping_usable
= 0;
900 priv
->drm_arm_mapping_usable
= 1;
910 static void opencl_device_uninit(AVHWDeviceContext
*hwdev
)
912 OpenCLDeviceContext
*priv
= hwdev
->hwctx
;
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
);
921 priv
->command_queue
= NULL
;
925 #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
926 static int opencl_filter_intel_media_vaapi_platform(AVHWDeviceContext
*hwdev
,
927 cl_platform_id platform_id
,
928 const char *platform_name
,
931 // This doesn't exist as a platform extension, so just test whether
932 // the function we will use for device enumeration exists.
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
);
944 static int opencl_enumerate_intel_media_vaapi_devices(AVHWDeviceContext
*hwdev
,
945 cl_platform_id platform_id
,
946 const char *platform_name
,
948 cl_device_id
**devices
,
951 VADisplay va_display
= context
;
952 clGetDeviceIDsFromVA_APIMediaAdapterINTEL_fn
953 clGetDeviceIDsFromVA_APIMediaAdapterINTEL
;
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
;
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
);
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
;
979 *devices
= av_malloc_array(*nb_devices
, sizeof(**devices
));
981 return AVERROR(ENOMEM
);
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
);
990 return AVERROR_UNKNOWN
;
996 static int opencl_filter_intel_media_vaapi_device(AVHWDeviceContext
*hwdev
,
997 cl_device_id device_id
,
998 const char *device_name
,
1001 const char *va_ext
= "cl_intel_va_api_media_sharing";
1003 if (opencl_check_device_extension(device_id
, va_ext
)) {
1006 av_log(hwdev
, AV_LOG_DEBUG
, "Device %s does not support the "
1007 "%s extension.\n", device_name
, va_ext
);
1013 #if HAVE_OPENCL_DXVA2
1014 static int opencl_filter_dxva2_platform(AVHWDeviceContext
*hwdev
,
1015 cl_platform_id platform_id
,
1016 const char *platform_name
,
1019 const char *dx9_ext
= "cl_khr_dx9_media_sharing";
1021 if (opencl_check_platform_extension(platform_id
, dx9_ext
)) {
1024 av_log(hwdev
, AV_LOG_DEBUG
, "Platform %s does not support the "
1025 "%s extension.\n", platform_name
, dx9_ext
);
1030 static 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
,
1037 IDirect3DDevice9
*device
= context
;
1038 clGetDeviceIDsFromDX9MediaAdapterKHR_fn
1039 clGetDeviceIDsFromDX9MediaAdapterKHR
;
1040 cl_dx9_media_adapter_type_khr media_adapter_type
= CL_ADAPTER_D3D9EX_KHR
;
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
;
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
);
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
;
1067 *devices
= av_malloc_array(*nb_devices
, sizeof(**devices
));
1069 return AVERROR(ENOMEM
);
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
);
1079 return AVERROR_UNKNOWN
;
1086 #if HAVE_OPENCL_D3D11
1087 static int opencl_filter_d3d11_platform(AVHWDeviceContext
*hwdev
,
1088 cl_platform_id platform_id
,
1089 const char *platform_name
,
1092 const char *d3d11_ext
= "cl_khr_d3d11_sharing";
1094 if (opencl_check_platform_extension(platform_id
, d3d11_ext
)) {
1097 av_log(hwdev
, AV_LOG_DEBUG
, "Platform %s does not support the "
1098 "%s extension.\n", platform_name
, d3d11_ext
);
1103 static 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
,
1110 ID3D11Device
*device
= context
;
1111 clGetDeviceIDsFromD3D11KHR_fn clGetDeviceIDsFromD3D11KHR
;
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
;
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
);
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
;
1138 *devices
= av_malloc_array(*nb_devices
, sizeof(**devices
));
1140 return AVERROR(ENOMEM
);
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
);
1150 return AVERROR_UNKNOWN
;
1157 #if HAVE_OPENCL_DXVA2 || HAVE_OPENCL_D3D11
1158 static int opencl_filter_gpu_device(AVHWDeviceContext
*hwdev
,
1159 cl_device_id device_id
,
1160 const char *device_name
,
1163 cl_device_type device_type
;
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
;
1173 if (!(device_type
& CL_DEVICE_TYPE_GPU
)) {
1174 av_log(hwdev
, AV_LOG_DEBUG
, "Device %s skipped (not GPU).\n",
1183 #if HAVE_OPENCL_DRM_ARM
1184 static int opencl_filter_drm_arm_platform(AVHWDeviceContext
*hwdev
,
1185 cl_platform_id platform_id
,
1186 const char *platform_name
,
1189 const char *drm_arm_ext
= "cl_arm_import_memory";
1191 if (opencl_check_platform_extension(platform_id
, drm_arm_ext
)) {
1194 av_log(hwdev
, AV_LOG_DEBUG
, "Platform %s does not support the "
1195 "%s extension.\n", platform_name
, drm_arm_ext
);
1200 static int opencl_filter_drm_arm_device(AVHWDeviceContext
*hwdev
,
1201 cl_device_id device_id
,
1202 const char *device_name
,
1205 const char *drm_arm_ext
= "cl_arm_import_memory";
1207 if (opencl_check_device_extension(device_id
, drm_arm_ext
)) {
1210 av_log(hwdev
, AV_LOG_DEBUG
, "Device %s does not support the "
1211 "%s extension.\n", device_name
, drm_arm_ext
);
1217 static int opencl_device_derive(AVHWDeviceContext
*hwdev
,
1218 AVHWDeviceContext
*src_ctx
, AVDictionary
*opts
,
1222 switch (src_ctx
->type
) {
1224 #if HAVE_OPENCL_DRM_BEIGNET
1225 case AV_HWDEVICE_TYPE_DRM
:
1226 case AV_HWDEVICE_TYPE_VAAPI
:
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
;
1233 err
= av_dict_set(&selector_opts
, "platform_vendor", "Intel", 0);
1235 err
= av_dict_set(&selector_opts
, "platform_version", "beignet", 0);
1237 OpenCLDeviceSelector selector
= {
1238 .platform_index
= -1,
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
,
1246 err
= opencl_device_create_internal(hwdev
, &selector
, NULL
);
1248 av_dict_free(&selector_opts
);
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.
1257 case AV_HWDEVICE_TYPE_VAAPI
:
1259 AVVAAPIDeviceContext
*src_hwctx
= src_ctx
->hwctx
;
1260 cl_context_properties props
[7] = {
1261 CL_CONTEXT_PLATFORM
,
1263 CL_CONTEXT_VA_API_DISPLAY_INTEL
,
1264 (intptr_t)src_hwctx
->display
,
1265 CL_CONTEXT_INTEROP_USER_SYNC
,
1269 OpenCLDeviceSelector selector
= {
1270 .platform_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
,
1279 err
= opencl_device_create_internal(hwdev
, &selector
, props
);
1284 #if HAVE_OPENCL_DXVA2
1285 case AV_HWDEVICE_TYPE_DXVA2
:
1287 AVDXVA2DeviceContext
*src_hwctx
= src_ctx
->hwctx
;
1288 IDirect3DDevice9
*device
;
1289 HANDLE device_handle
;
1292 hr
= IDirect3DDeviceManager9_OpenDeviceHandle(src_hwctx
->devmgr
,
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
;
1301 hr
= IDirect3DDeviceManager9_LockDevice(src_hwctx
->devmgr
,
1304 if (SUCCEEDED(hr
)) {
1305 cl_context_properties props
[5] = {
1306 CL_CONTEXT_PLATFORM
,
1308 CL_CONTEXT_ADAPTER_D3D9EX_KHR
,
1312 OpenCLDeviceSelector selector
= {
1313 .platform_index
= -1,
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
,
1322 err
= opencl_device_create_internal(hwdev
, &selector
, props
);
1324 IDirect3DDeviceManager9_UnlockDevice(src_hwctx
->devmgr
,
1325 device_handle
, FALSE
);
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
;
1332 IDirect3DDeviceManager9_CloseDeviceHandle(src_hwctx
->devmgr
,
1338 #if HAVE_OPENCL_D3D11
1339 case AV_HWDEVICE_TYPE_D3D11VA
:
1341 AVD3D11VADeviceContext
*src_hwctx
= src_ctx
->hwctx
;
1342 cl_context_properties props
[5] = {
1343 CL_CONTEXT_PLATFORM
,
1345 CL_CONTEXT_D3D11_DEVICE_KHR
,
1346 (intptr_t)src_hwctx
->device
,
1349 OpenCLDeviceSelector selector
= {
1350 .platform_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
,
1359 err
= opencl_device_create_internal(hwdev
, &selector
, props
);
1364 #if HAVE_OPENCL_DRM_ARM
1365 case AV_HWDEVICE_TYPE_DRM
:
1367 OpenCLDeviceSelector selector
= {
1368 .platform_index
= -1,
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
,
1377 err
= opencl_device_create_internal(hwdev
, &selector
, NULL
);
1382 #if HAVE_OPENCL_VIDEOTOOLBOX
1383 case AV_HWDEVICE_TYPE_VIDEOTOOLBOX
:
1384 err
= opencl_device_create(hwdev
, NULL
, NULL
, 0);
1389 err
= AVERROR(ENOSYS
);
1396 static int opencl_get_plane_format(enum AVPixelFormat pixfmt
,
1397 int plane
, int width
, int height
,
1398 cl_image_format
*image_format
,
1399 cl_image_desc
*image_desc
)
1401 const AVPixFmtDescriptor
*desc
;
1402 const AVComponentDescriptor
*comp
;
1403 int channels
= 0, order
= 0, depth
= 0, step
= 0;
1404 int wsub
, hsub
, alpha
;
1407 if (plane
>= AV_NUM_DATA_POINTERS
)
1408 return AVERROR(ENOENT
);
1410 desc
= av_pix_fmt_desc_get(pixfmt
);
1412 // Only normal images are allowed.
1413 if (desc
->flags
& (AV_PIX_FMT_FLAG_BITSTREAM
|
1414 AV_PIX_FMT_FLAG_HWACCEL
|
1415 AV_PIX_FMT_FLAG_PAL
))
1416 return AVERROR(EINVAL
);
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
);
1424 for (c
= 0; c
< desc
->nb_components
; c
++) {
1425 comp
= &desc
->comp
[c
];
1426 if (comp
->plane
!= plane
)
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
);
1451 depth
= comp
->depth
;
1452 order
= order
* 10 + comp
->offset
/ ((depth
+ 7) / 8) + 1;
1454 alpha
= (desc
->flags
& AV_PIX_FMT_FLAG_ALPHA
&&
1455 c
== desc
->nb_components
- 1);
1459 return AVERROR(ENOENT
);
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
;
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
;
1470 image_desc
->image_width
= width
/ wsub
;
1471 image_desc
->image_height
= height
/ hsub
;
1472 image_desc
->image_row_pitch
= step
* width
/ wsub
;
1476 image_format
->image_channel_data_type
= CL_UNORM_INT8
;
1479 image_format
->image_channel_data_type
= CL_UNORM_INT16
;
1480 else if (depth
== 32)
1481 image_format
->image_channel_data_type
= CL_FLOAT
;
1483 return AVERROR(EINVAL
);
1486 #define CHANNEL_ORDER(order, type) \
1487 case order: image_format->image_channel_order = type; break;
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
);
1495 CHANNEL_ORDER(4321, CL_ABGR
);
1498 return AVERROR(EINVAL
);
1500 #undef CHANNEL_ORDER
1505 static int opencl_frames_get_constraints(AVHWDeviceContext
*hwdev
,
1506 const void *hwconfig
,
1507 AVHWFramesConstraints
*constraints
)
1509 AVOpenCLDeviceContext
*hwctx
= hwdev
->hwctx
;
1510 cl_uint nb_image_formats
;
1511 cl_image_format
*image_formats
= NULL
;
1513 enum AVPixelFormat pix_fmt
;
1514 int err
, pix_fmts_found
;
1515 size_t max_width
, max_height
;
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
);
1523 constraints
->max_width
= max_width
;
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
);
1531 constraints
->max_height
= max_height
;
1533 av_log(hwdev
, AV_LOG_DEBUG
, "Maximum supported image size %dx%d.\n",
1534 constraints
->max_width
, constraints
->max_height
);
1536 cle
= clGetSupportedImageFormats(hwctx
->context
,
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
);
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
);
1554 av_malloc_array(nb_image_formats
, sizeof(*image_formats
));
1555 if (!image_formats
) {
1556 err
= AVERROR(ENOMEM
);
1560 cle
= clGetSupportedImageFormats(hwctx
->context
,
1562 CL_MEM_OBJECT_IMAGE2D
,
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
);
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
;
1578 for (plane
= 0;; plane
++) {
1579 err
= opencl_get_plane_format(pix_fmt
, plane
, 0, 0,
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
)
1592 if (i
== nb_image_formats
) {
1593 err
= AVERROR(EINVAL
);
1597 if (err
!= AVERROR(ENOENT
))
1600 av_log(hwdev
, AV_LOG_DEBUG
, "Format %s supported.\n",
1601 av_get_pix_fmt_name(pix_fmt
));
1603 err
= av_reallocp_array(&constraints
->valid_sw_formats
,
1605 sizeof(*constraints
->valid_sw_formats
));
1608 constraints
->valid_sw_formats
[pix_fmts_found
] = pix_fmt
;
1609 constraints
->valid_sw_formats
[pix_fmts_found
+ 1] =
1614 av_freep(&image_formats
);
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
);
1622 constraints
->valid_hw_formats
[0] = AV_PIX_FMT_OPENCL
;
1623 constraints
->valid_hw_formats
[1] = AV_PIX_FMT_NONE
;
1628 av_freep(&image_formats
);
1632 static void opencl_pool_free(void *opaque
, uint8_t *data
)
1634 AVHWFramesContext
*hwfc
= opaque
;
1635 AVOpenCLFrameDescriptor
*desc
= (AVOpenCLFrameDescriptor
*)data
;
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: "
1650 static AVBufferRef
*opencl_pool_alloc(void *opaque
, size_t size
)
1652 AVHWFramesContext
*hwfc
= opaque
;
1653 AVOpenCLDeviceContext
*hwctx
= hwfc
->device_ctx
->hwctx
;
1654 AVOpenCLFrameDescriptor
*desc
;
1657 cl_image_format image_format
;
1658 cl_image_desc image_desc
;
1662 desc
= av_mallocz(sizeof(*desc
));
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
))
1675 // For generic image objects, the pitch is determined by the
1677 image_desc
.image_row_pitch
= 0;
1679 image
= clCreateImage(hwctx
->context
, CL_MEM_READ_WRITE
,
1680 &image_format
, &image_desc
, NULL
, &cle
);
1682 av_log(hwfc
, AV_LOG_ERROR
, "Failed to create image for "
1683 "plane %d: %d.\n", p
, cle
);
1687 desc
->planes
[p
] = image
;
1690 desc
->nb_planes
= p
;
1692 ref
= av_buffer_create((uint8_t*)desc
, sizeof(*desc
),
1693 &opencl_pool_free
, hwfc
, 0);
1700 for (p
= 0; desc
->planes
[p
]; p
++)
1701 clReleaseMemObject(desc
->planes
[p
]);
1706 static int opencl_frames_init_command_queue(AVHWFramesContext
*hwfc
)
1708 OpenCLFramesContext
*priv
= hwfc
->hwctx
;
1709 AVOpenCLFramesContext
*hwctx
= &priv
->p
;
1710 OpenCLDeviceContext
*devpriv
= hwfc
->device_ctx
->hwctx
;
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
);
1725 static int opencl_frames_init(AVHWFramesContext
*hwfc
)
1728 ffhwframesctx(hwfc
)->pool_internal
=
1729 av_buffer_pool_init2(sizeof(cl_mem
), hwfc
,
1730 &opencl_pool_alloc
, NULL
);
1731 if (!ffhwframesctx(hwfc
)->pool_internal
)
1732 return AVERROR(ENOMEM
);
1735 return opencl_frames_init_command_queue(hwfc
);
1738 static void opencl_frames_uninit(AVHWFramesContext
*hwfc
)
1740 OpenCLFramesContext
*priv
= hwfc
->hwctx
;
1743 #if HAVE_OPENCL_DXVA2 || HAVE_OPENCL_D3D11
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",
1756 av_freep(&priv
->mapped_frames
);
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
);
1765 priv
->command_queue
= NULL
;
1769 static int opencl_get_buffer(AVHWFramesContext
*hwfc
, AVFrame
*frame
)
1771 AVOpenCLFrameDescriptor
*desc
;
1774 frame
->buf
[0] = av_buffer_pool_get(hwfc
->pool
);
1776 return AVERROR(ENOMEM
);
1778 desc
= (AVOpenCLFrameDescriptor
*)frame
->buf
[0]->data
;
1780 for (p
= 0; p
< desc
->nb_planes
; p
++)
1781 frame
->data
[p
] = (uint8_t*)desc
->planes
[p
];
1783 frame
->format
= AV_PIX_FMT_OPENCL
;
1784 frame
->width
= hwfc
->width
;
1785 frame
->height
= hwfc
->height
;
1790 static int opencl_transfer_get_formats(AVHWFramesContext
*hwfc
,
1791 enum AVHWFrameTransferDirection dir
,
1792 enum AVPixelFormat
**formats
)
1794 enum AVPixelFormat
*fmts
;
1796 fmts
= av_malloc_array(2, sizeof(*fmts
));
1798 return AVERROR(ENOMEM
);
1800 fmts
[0] = hwfc
->sw_format
;
1801 fmts
[1] = AV_PIX_FMT_NONE
;
1807 static int opencl_wait_events(AVHWFramesContext
*hwfc
,
1808 cl_event
*events
, int nb_events
)
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
);
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
);
1831 static int opencl_transfer_data_from(AVHWFramesContext
*hwfc
,
1832 AVFrame
*dst
, const AVFrame
*src
)
1834 OpenCLFramesContext
*priv
= hwfc
->hwctx
;
1835 cl_image_format image_format
;
1836 cl_image_desc image_desc
;
1838 size_t origin
[3] = { 0, 0, 0 };
1840 cl_event events
[AV_NUM_DATA_POINTERS
];
1843 if (dst
->format
!= hwfc
->sw_format
)
1844 return AVERROR(EINVAL
);
1847 err
= opencl_get_plane_format(hwfc
->sw_format
, p
,
1848 src
->width
, src
->height
,
1849 &image_format
, &image_desc
);
1851 if (err
== AVERROR(ENOENT
))
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
);
1863 region
[0] = image_desc
.image_width
;
1864 region
[1] = image_desc
.image_height
;
1867 cle
= clEnqueueReadImage(priv
->command_queue
,
1868 (cl_mem
)src
->data
[p
],
1869 CL_FALSE
, origin
, region
,
1870 dst
->linesize
[p
], 0,
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
);
1881 opencl_wait_events(hwfc
, events
, p
);
1886 static int opencl_transfer_data_to(AVHWFramesContext
*hwfc
,
1887 AVFrame
*dst
, const AVFrame
*src
)
1889 OpenCLFramesContext
*priv
= hwfc
->hwctx
;
1890 cl_image_format image_format
;
1891 cl_image_desc image_desc
;
1893 size_t origin
[3] = { 0, 0, 0 };
1895 cl_event events
[AV_NUM_DATA_POINTERS
];
1898 if (src
->format
!= hwfc
->sw_format
)
1899 return AVERROR(EINVAL
);
1902 err
= opencl_get_plane_format(hwfc
->sw_format
, p
,
1903 src
->width
, src
->height
,
1904 &image_format
, &image_desc
);
1906 if (err
== AVERROR(ENOENT
))
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
);
1918 region
[0] = image_desc
.image_width
;
1919 region
[1] = image_desc
.image_height
;
1922 cle
= clEnqueueWriteImage(priv
->command_queue
,
1923 (cl_mem
)dst
->data
[p
],
1924 CL_FALSE
, origin
, region
,
1925 src
->linesize
[p
], 0,
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
);
1936 opencl_wait_events(hwfc
, events
, p
);
1941 typedef 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.
1945 void *address
[AV_NUM_DATA_POINTERS
];
1948 static void opencl_unmap_frame(AVHWFramesContext
*hwfc
,
1949 HWMapDescriptor
*hwmap
)
1951 OpenCLFramesContext
*priv
= hwfc
->hwctx
;
1952 OpenCLMapping
*map
= hwmap
->priv
;
1953 cl_event events
[AV_NUM_DATA_POINTERS
];
1957 for (p
= e
= 0; p
< FF_ARRAY_ELEMS(map
->address
); p
++) {
1958 if (!map
->address
[p
])
1961 cle
= clEnqueueUnmapMemObject(priv
->command_queue
,
1962 (cl_mem
)hwmap
->source
->data
[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
);
1972 opencl_wait_events(hwfc
, events
, e
);
1977 static int opencl_map_frame(AVHWFramesContext
*hwfc
, AVFrame
*dst
,
1978 const AVFrame
*src
, int flags
)
1980 OpenCLFramesContext
*priv
= hwfc
->hwctx
;
1981 cl_map_flags map_flags
;
1982 cl_image_format image_format
;
1983 cl_image_desc image_desc
;
1986 size_t origin
[3] = { 0, 0, 0 };
1989 cl_event events
[AV_NUM_DATA_POINTERS
];
1992 av_assert0(hwfc
->sw_format
== dst
->format
);
1994 if (flags
& AV_HWFRAME_MAP_OVERWRITE
&&
1995 !(flags
& AV_HWFRAME_MAP_READ
)) {
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
;
2001 if (flags
& AV_HWFRAME_MAP_READ
)
2002 map_flags
|= CL_MAP_READ
;
2003 if (flags
& AV_HWFRAME_MAP_WRITE
)
2004 map_flags
|= CL_MAP_WRITE
;
2007 map
= av_mallocz(sizeof(*map
));
2009 return AVERROR(ENOMEM
);
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
))
2020 region
[0] = image_desc
.image_width
;
2021 region
[1] = image_desc
.image_height
;
2025 clEnqueueMapImage(priv
->command_queue
,
2026 (cl_mem
)src
->data
[p
],
2027 CL_FALSE
, map_flags
, origin
, region
,
2028 &row_pitch
, NULL
, 0, NULL
,
2030 if (!map
->address
[p
]) {
2031 av_log(hwfc
, AV_LOG_ERROR
, "Failed to map OpenCL "
2032 "image plane %d: %d.\n", p
, cle
);
2037 dst
->data
[p
] = map
->address
[p
];
2038 dst
->linesize
[p
] = row_pitch
;
2040 av_log(hwfc
, AV_LOG_DEBUG
, "Map plane %d (%p -> %p).\n",
2041 p
, src
->data
[p
], dst
->data
[p
]);
2044 err
= opencl_wait_events(hwfc
, events
, p
);
2048 err
= ff_hwframe_map_create(src
->hw_frames_ctx
, dst
, src
,
2049 &opencl_unmap_frame
, map
);
2053 dst
->width
= src
->width
;
2054 dst
->height
= src
->height
;
2059 for (p
= 0; p
< AV_NUM_DATA_POINTERS
; p
++) {
2060 if (!map
->address
[p
])
2062 clEnqueueUnmapMemObject(priv
->command_queue
,
2063 (cl_mem
)src
->data
[p
],
2065 0, NULL
, &events
[p
]);
2068 opencl_wait_events(hwfc
, events
, p
);
2073 #if HAVE_OPENCL_DRM_BEIGNET
2075 typedef struct DRMBeignetToOpenCLMapping
{
2077 AVDRMFrameDescriptor
*drm_desc
;
2079 AVOpenCLFrameDescriptor frame
;
2080 } DRMBeignetToOpenCLMapping
;
2082 static void opencl_unmap_from_drm_beignet(AVHWFramesContext
*dst_fc
,
2083 HWMapDescriptor
*hwmap
)
2085 DRMBeignetToOpenCLMapping
*mapping
= hwmap
->priv
;
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
);
2100 static int opencl_map_from_drm_beignet(AVHWFramesContext
*dst_fc
,
2101 AVFrame
*dst
, const AVFrame
*src
,
2104 OpenCLDeviceContext
*priv
= dst_fc
->device_ctx
->hwctx
;
2105 AVOpenCLDeviceContext
*hwctx
= &priv
->p
;
2106 DRMBeignetToOpenCLMapping
*mapping
;
2107 const AVDRMFrameDescriptor
*desc
;
2111 desc
= (const AVDRMFrameDescriptor
*)src
->data
[0];
2113 mapping
= av_mallocz(sizeof(*mapping
));
2115 return AVERROR(ENOMEM
);
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
];
2125 cl_import_image_info_intel image_info
= {
2127 .size
= object
->size
,
2128 .type
= CL_MEM_OBJECT_IMAGE2D
,
2129 .offset
= plane
->offset
,
2130 .row_pitch
= plane
->pitch
,
2132 cl_image_desc image_desc
;
2134 err
= opencl_get_plane_format(dst_fc
->sw_format
, p
,
2135 src
->width
, src
->height
,
2139 av_log(dst_fc
, AV_LOG_ERROR
, "DRM frame layer %d "
2140 "plane %d is not representable in OpenCL: %d.\n",
2144 image_info
.width
= image_desc
.image_width
;
2145 image_info
.height
= image_desc
.image_height
;
2147 mapping
->frame
.planes
[p
] =
2148 priv
->clCreateImageFromFdINTEL(hwctx
->context
,
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",
2158 dst
->data
[p
] = (uint8_t*)mapping
->frame
.planes
[p
];
2159 mapping
->frame
.nb_planes
= ++p
;
2163 err
= ff_hwframe_map_create(dst
->hw_frames_ctx
, dst
, src
,
2164 &opencl_unmap_from_drm_beignet
,
2169 dst
->width
= src
->width
;
2170 dst
->height
= src
->height
;
2175 for (p
= 0; p
< mapping
->frame
.nb_planes
; p
++) {
2176 if (mapping
->frame
.planes
[p
])
2177 clReleaseMemObject(mapping
->frame
.planes
[p
]);
2180 memset(dst
->data
, 0, sizeof(dst
->data
));
2184 #if HAVE_OPENCL_VAAPI_BEIGNET
2186 static int opencl_map_from_vaapi(AVHWFramesContext
*dst_fc
,
2187 AVFrame
*dst
, const AVFrame
*src
,
2193 tmp
= av_frame_alloc();
2195 return AVERROR(ENOMEM
);
2197 tmp
->format
= AV_PIX_FMT_DRM_PRIME
;
2199 err
= av_hwframe_map(tmp
, src
, flags
);
2203 err
= opencl_map_from_drm_beignet(dst_fc
, dst
, tmp
, flags
);
2207 err
= ff_hwframe_map_replace(dst
, src
);
2210 av_frame_free(&tmp
);
2214 #endif /* HAVE_OPENCL_VAAPI_BEIGNET */
2215 #endif /* HAVE_OPENCL_DRM_BEIGNET */
2217 static inline cl_mem_flags
opencl_mem_flags_for_mapping(int map_flags
)
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
;
2230 #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
2232 static void opencl_unmap_from_qsv(AVHWFramesContext
*dst_fc
,
2233 HWMapDescriptor
*hwmap
)
2235 AVOpenCLFrameDescriptor
*desc
= hwmap
->priv
;
2236 OpenCLDeviceContext
*device_priv
= dst_fc
->device_ctx
->hwctx
;
2237 OpenCLFramesContext
*frames_priv
= dst_fc
->hwctx
;
2242 av_log(dst_fc
, AV_LOG_DEBUG
, "Unmap QSV/VAAPI surface from OpenCL.\n");
2244 cle
= device_priv
->clEnqueueReleaseVA_APIMediaSurfacesINTEL(
2245 frames_priv
->command_queue
, desc
->nb_planes
, desc
->planes
,
2247 if (cle
!= CL_SUCCESS
) {
2248 av_log(dst_fc
, AV_LOG_ERROR
, "Failed to release surface "
2249 "handles: %d.\n", cle
);
2252 opencl_wait_events(dst_fc
, &event
, 1);
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",
2266 static int opencl_map_from_qsv(AVHWFramesContext
*dst_fc
, AVFrame
*dst
,
2267 const AVFrame
*src
, int flags
)
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
;
2274 AVOpenCLFrameDescriptor
*desc
;
2275 VASurfaceID va_surface
;
2276 cl_mem_flags cl_flags
;
2282 if (src
->format
== AV_PIX_FMT_QSV
) {
2284 mfxFrameSurface1
*mfx_surface
= (mfxFrameSurface1
*)src
->data
[3];
2285 err
= ff_qsv_get_surface_base_handle(mfx_surface
,
2286 AV_HWDEVICE_TYPE_VAAPI
,
2290 va_surface
= *(VASurfaceID
*)base_handle
;
2293 if (src
->format
== AV_PIX_FMT_VAAPI
) {
2294 va_surface
= (VASurfaceID
)(uintptr_t)src
->data
[3];
2296 return AVERROR(ENOSYS
);
2299 cl_flags
= opencl_mem_flags_for_mapping(flags
);
2301 return AVERROR(EINVAL
);
2303 av_log(src_fc
, AV_LOG_DEBUG
, "Map QSV/VAAPI surface %#x to "
2304 "OpenCL.\n", va_surface
);
2306 desc
= av_mallocz(sizeof(*desc
));
2308 return AVERROR(ENOMEM
);
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;
2314 for (p
= 0; p
< desc
->nb_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
);
2326 dst
->data
[p
] = (uint8_t*)desc
->planes
[p
];
2329 cle
= device_priv
->clEnqueueAcquireVA_APIMediaSurfacesINTEL(
2330 frames_priv
->command_queue
, desc
->nb_planes
, desc
->planes
,
2332 if (cle
!= CL_SUCCESS
) {
2333 av_log(dst_fc
, AV_LOG_ERROR
, "Failed to acquire surface "
2334 "handles: %d.\n", cle
);
2339 err
= opencl_wait_events(dst_fc
, &event
, 1);
2343 err
= ff_hwframe_map_create(dst
->hw_frames_ctx
, dst
, src
,
2344 &opencl_unmap_from_qsv
, desc
);
2348 dst
->width
= src
->width
;
2349 dst
->height
= src
->height
;
2354 for (p
= 0; p
< desc
->nb_planes
; p
++)
2355 if (desc
->planes
[p
])
2356 clReleaseMemObject(desc
->planes
[p
]);
2358 memset(dst
->data
, 0, sizeof(dst
->data
));
2364 #if HAVE_OPENCL_DXVA2
2366 static void opencl_unmap_from_dxva2(AVHWFramesContext
*dst_fc
,
2367 HWMapDescriptor
*hwmap
)
2369 AVOpenCLFrameDescriptor
*desc
= hwmap
->priv
;
2370 OpenCLDeviceContext
*device_priv
= dst_fc
->device_ctx
->hwctx
;
2371 OpenCLFramesContext
*frames_priv
= dst_fc
->hwctx
;
2375 av_log(dst_fc
, AV_LOG_DEBUG
, "Unmap DXVA2 surface from OpenCL.\n");
2377 cle
= device_priv
->clEnqueueReleaseDX9MediaSurfacesKHR(
2378 frames_priv
->command_queue
, desc
->nb_planes
, desc
->planes
,
2380 if (cle
!= CL_SUCCESS
) {
2381 av_log(dst_fc
, AV_LOG_ERROR
, "Failed to release surface "
2382 "handle: %d.\n", cle
);
2386 opencl_wait_events(dst_fc
, &event
, 1);
2389 static int opencl_map_from_dxva2(AVHWFramesContext
*dst_fc
, AVFrame
*dst
,
2390 const AVFrame
*src
, int flags
)
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
;
2397 AVOpenCLFrameDescriptor
*desc
;
2402 av_log(dst_fc
, AV_LOG_DEBUG
, "Map DXVA2 surface %p to "
2403 "OpenCL.\n", src
->data
[3]);
2405 for (i
= 0; i
< src_hwctx
->nb_surfaces
; i
++) {
2406 if (src_hwctx
->surfaces
[i
] == (IDirect3DSurface9
*)src
->data
[3])
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
);
2415 desc
= &frames_priv
->mapped_frames
[i
];
2417 cle
= device_priv
->clEnqueueAcquireDX9MediaSurfacesKHR(
2418 frames_priv
->command_queue
, desc
->nb_planes
, desc
->planes
,
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
);
2426 err
= opencl_wait_events(dst_fc
, &event
, 1);
2430 for (i
= 0; i
< desc
->nb_planes
; i
++)
2431 dst
->data
[i
] = (uint8_t*)desc
->planes
[i
];
2433 err
= ff_hwframe_map_create(dst
->hw_frames_ctx
, dst
, src
,
2434 &opencl_unmap_from_dxva2
, desc
);
2438 dst
->width
= src
->width
;
2439 dst
->height
= src
->height
;
2444 cle
= device_priv
->clEnqueueReleaseDX9MediaSurfacesKHR(
2445 frames_priv
->command_queue
, desc
->nb_planes
, desc
->planes
,
2447 if (cle
== CL_SUCCESS
)
2448 opencl_wait_events(dst_fc
, &event
, 1);
2449 memset(dst
->data
, 0, sizeof(dst
->data
));
2453 static int opencl_frames_derive_from_dxva2(AVHWFramesContext
*dst_fc
,
2454 AVHWFramesContext
*src_fc
, int flags
)
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
;
2462 int err
, i
, p
, nb_planes
;
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
);
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
);
2477 cl_flags
= opencl_mem_flags_for_mapping(flags
);
2479 return AVERROR(EINVAL
);
2481 frames_priv
->nb_mapped_frames
= src_hwctx
->nb_surfaces
;
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
);
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
,
2495 desc
->nb_planes
= nb_planes
;
2496 for (p
= 0; p
< nb_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",
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
]);
2522 av_freep(&frames_priv
->mapped_frames
);
2523 frames_priv
->nb_mapped_frames
= 0;
2529 #if HAVE_OPENCL_D3D11
2531 static void opencl_unmap_from_d3d11(AVHWFramesContext
*dst_fc
,
2532 HWMapDescriptor
*hwmap
)
2534 AVOpenCLFrameDescriptor
*desc
= hwmap
->priv
;
2535 OpenCLDeviceContext
*device_priv
= dst_fc
->device_ctx
->hwctx
;
2536 OpenCLFramesContext
*frames_priv
= dst_fc
->hwctx
;
2540 cle
= device_priv
->clEnqueueReleaseD3D11ObjectsKHR(
2541 frames_priv
->command_queue
, desc
->nb_planes
, desc
->planes
,
2543 if (cle
!= CL_SUCCESS
) {
2544 av_log(dst_fc
, AV_LOG_ERROR
, "Failed to release surface "
2545 "handle: %d.\n", cle
);
2548 opencl_wait_events(dst_fc
, &event
, 1);
2551 static int opencl_map_from_d3d11(AVHWFramesContext
*dst_fc
, AVFrame
*dst
,
2552 const AVFrame
*src
, int flags
)
2554 OpenCLDeviceContext
*device_priv
= dst_fc
->device_ctx
->hwctx
;
2555 OpenCLFramesContext
*frames_priv
= dst_fc
->hwctx
;
2556 AVOpenCLFrameDescriptor
*desc
;
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
);
2568 av_log(dst_fc
, AV_LOG_DEBUG
, "Map D3D11 texture %d to OpenCL.\n",
2571 desc
= &frames_priv
->mapped_frames
[index
];
2573 cle
= device_priv
->clEnqueueAcquireD3D11ObjectsKHR(
2574 frames_priv
->command_queue
, desc
->nb_planes
, desc
->planes
,
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
);
2582 err
= opencl_wait_events(dst_fc
, &event
, 1);
2586 for (i
= 0; i
< desc
->nb_planes
; i
++)
2587 dst
->data
[i
] = (uint8_t*)desc
->planes
[i
];
2589 err
= ff_hwframe_map_create(dst
->hw_frames_ctx
, dst
, src
,
2590 &opencl_unmap_from_d3d11
, desc
);
2594 dst
->width
= src
->width
;
2595 dst
->height
= src
->height
;
2600 cle
= device_priv
->clEnqueueReleaseD3D11ObjectsKHR(
2601 frames_priv
->command_queue
, desc
->nb_planes
, desc
->planes
,
2603 if (cle
== CL_SUCCESS
)
2604 opencl_wait_events(dst_fc
, &event
, 1);
2605 memset(dst
->data
, 0, sizeof(dst
->data
));
2609 static int opencl_frames_derive_from_d3d11(AVHWFramesContext
*dst_fc
,
2610 AVHWFramesContext
*src_fc
, int flags
)
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
;
2618 int err
, i
, p
, nb_planes
;
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
);
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
);
2633 cl_flags
= opencl_mem_flags_for_mapping(flags
);
2635 return AVERROR(EINVAL
);
2637 frames_priv
->nb_mapped_frames
= src_fc
->initial_pool_size
;
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
);
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
;
2652 device_priv
->clCreateFromD3D11Texture2DKHR(
2653 dst_dev
->context
, cl_flags
, src_hwctx
->texture
,
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
);
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
]);
2676 av_freep(&frames_priv
->mapped_frames
);
2677 frames_priv
->nb_mapped_frames
= 0;
2683 #if HAVE_OPENCL_DRM_ARM
2685 typedef struct DRMARMtoOpenCLMapping
{
2687 cl_mem object_buffers
[AV_DRM_MAX_PLANES
];
2689 cl_mem plane_images
[AV_DRM_MAX_PLANES
];
2690 } DRMARMtoOpenCLMapping
;
2692 static void opencl_unmap_from_drm_arm(AVHWFramesContext
*dst_fc
,
2693 HWMapDescriptor
*hwmap
)
2695 DRMARMtoOpenCLMapping
*mapping
= hwmap
->priv
;
2698 for (i
= 0; i
< mapping
->nb_planes
; i
++)
2699 clReleaseMemObject(mapping
->plane_images
[i
]);
2701 for (i
= 0; i
< mapping
->nb_objects
; i
++)
2702 clReleaseMemObject(mapping
->object_buffers
[i
]);
2707 static int opencl_map_from_drm_arm(AVHWFramesContext
*dst_fc
, AVFrame
*dst
,
2708 const AVFrame
*src
, int flags
)
2710 AVHWFramesContext
*src_fc
=
2711 (AVHWFramesContext
*)src
->hw_frames_ctx
->data
;
2712 AVOpenCLDeviceContext
*dst_dev
= dst_fc
->device_ctx
->hwctx
;
2713 const AVDRMFrameDescriptor
*desc
;
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,
2722 desc
= (const AVDRMFrameDescriptor
*)src
->data
[0];
2724 cl_flags
= opencl_mem_flags_for_mapping(flags
);
2726 return AVERROR(EINVAL
);
2728 mapping
= av_mallocz(sizeof(*mapping
));
2730 return AVERROR(ENOMEM
);
2732 mapping
->nb_objects
= desc
->nb_objects
;
2733 for (i
= 0; i
< desc
->nb_objects
; i
++) {
2734 int fd
= desc
->objects
[i
].fd
;
2736 av_log(dst_fc
, AV_LOG_DEBUG
, "Map DRM PRIME fd %d to OpenCL.\n", fd
);
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
);
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 %"SIZE_SPECIFIER
") of DRM frame: %d.\n",
2751 i
, fd
, desc
->objects
[i
].size
, cle
);
2757 mapping
->nb_planes
= 0;
2758 for (i
= 0; i
< desc
->nb_layers
; i
++) {
2759 const AVDRMLayerDescriptor
*layer
= &desc
->layers
[i
];
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
;
2769 err
= opencl_get_plane_format(src_fc
->sw_format
, p
,
2770 src_fc
->width
, src_fc
->height
,
2771 &image_format
, &image_desc
);
2773 av_log(dst_fc
, AV_LOG_ERROR
, "Invalid plane %d (DRM "
2774 "layer %d plane %d): %d.\n", p
, i
, j
, err
);
2778 region
.origin
= plane
->offset
;
2779 region
.size
= image_desc
.image_row_pitch
*
2780 image_desc
.image_height
;
2783 clCreateSubBuffer(mapping
->object_buffers
[plane
->object_index
],
2785 CL_BUFFER_CREATE_TYPE_REGION
,
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
);
2794 image_desc
.buffer
= plane_buffer
;
2796 mapping
->plane_images
[p
] =
2797 clCreateImage(dst_dev
->context
, cl_flags
,
2798 &image_format
, &image_desc
, NULL
, &cle
);
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
);
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
);
2811 ++mapping
->nb_planes
;
2815 for (i
= 0; i
< mapping
->nb_planes
; i
++)
2816 dst
->data
[i
] = (uint8_t*)mapping
->plane_images
[i
];
2818 err
= ff_hwframe_map_create(dst
->hw_frames_ctx
, dst
, src
,
2819 &opencl_unmap_from_drm_arm
, mapping
);
2823 dst
->width
= src
->width
;
2824 dst
->height
= src
->height
;
2829 for (i
= 0; i
< mapping
->nb_planes
; i
++) {
2830 clReleaseMemObject(mapping
->plane_images
[i
]);
2832 for (i
= 0; i
< mapping
->nb_objects
; i
++) {
2833 if (mapping
->object_buffers
[i
])
2834 clReleaseMemObject(mapping
->object_buffers
[i
]);
2837 memset(dst
->data
, 0, sizeof(dst
->data
));
2843 #if HAVE_OPENCL_VIDEOTOOLBOX
2845 static void opencl_unmap_from_vt(AVHWFramesContext
*hwfc
,
2846 HWMapDescriptor
*hwmap
)
2848 uint8_t *desc
= hwmap
->priv
;
2849 opencl_pool_free(hwfc
, desc
);
2852 static int opencl_map_from_vt(AVHWFramesContext
*dst_fc
, AVFrame
*dst
,
2853 const AVFrame
*src
, int flags
)
2855 CVPixelBufferRef pixbuf
= (CVPixelBufferRef
) src
->data
[3];
2856 IOSurfaceRef io_surface_ref
= CVPixelBufferGetIOSurface(pixbuf
);
2858 AVOpenCLFrameDescriptor
*desc
= NULL
;
2859 AVOpenCLDeviceContext
*dst_dev
= dst_fc
->device_ctx
->hwctx
;
2861 if (!io_surface_ref
) {
2862 av_log(dst_fc
, AV_LOG_ERROR
, "Failed to get IOSurfaceRef\n");
2863 return AVERROR_EXTERNAL
;
2866 desc
= av_mallocz(sizeof(*desc
));
2868 return AVERROR(ENOMEM
);
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
,
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
))
2887 desc
->planes
[p
] = clCreateImageFromIOSurfaceWithPropertiesAPPLE(dst_dev
->context
,
2888 opencl_mem_flags_for_mapping(flags
),
2889 &image_format
, &image_desc
,
2891 if (!desc
->planes
[p
]) {
2892 av_log(dst_fc
, AV_LOG_ERROR
, "Failed to create image from IOSurfaceRef\n");
2899 for (int i
= 0; i
< desc
->nb_planes
; i
++)
2900 dst
->data
[i
] = (uint8_t *) desc
->planes
[i
];
2902 err
= ff_hwframe_map_create(dst
->hw_frames_ctx
, dst
, src
,
2903 opencl_unmap_from_vt
, desc
);
2907 dst
->width
= src
->width
;
2908 dst
->height
= src
->height
;
2913 for (int i
= 0; i
< desc
->nb_planes
; i
++)
2914 clReleaseMemObject(desc
->planes
[i
]);
2921 static int opencl_map_from(AVHWFramesContext
*hwfc
, AVFrame
*dst
,
2922 const AVFrame
*src
, int flags
)
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
);
2930 static int opencl_map_to(AVHWFramesContext
*hwfc
, AVFrame
*dst
,
2931 const AVFrame
*src
, int flags
)
2933 av_unused OpenCLDeviceContext
*priv
= hwfc
->device_ctx
->hwctx
;
2934 av_assert0(dst
->format
== AV_PIX_FMT_OPENCL
);
2935 switch (src
->format
) {
2936 #if HAVE_OPENCL_DRM_BEIGNET
2937 case AV_PIX_FMT_DRM_PRIME
:
2938 if (priv
->beignet_drm_mapping_usable
)
2939 return opencl_map_from_drm_beignet(hwfc
, dst
, src
, flags
);
2941 #if HAVE_OPENCL_VAAPI_BEIGNET
2942 case AV_PIX_FMT_VAAPI
:
2943 if (priv
->beignet_drm_mapping_usable
)
2944 return opencl_map_from_vaapi(hwfc
, dst
, src
, flags
);
2946 #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
2947 case AV_PIX_FMT_QSV
:
2948 case AV_PIX_FMT_VAAPI
:
2949 if (priv
->qsv_mapping_usable
)
2950 return opencl_map_from_qsv(hwfc
, dst
, src
, flags
);
2952 #if HAVE_OPENCL_DXVA2
2953 case AV_PIX_FMT_DXVA2_VLD
:
2954 if (priv
->dxva2_mapping_usable
)
2955 return opencl_map_from_dxva2(hwfc
, dst
, src
, flags
);
2957 #if HAVE_OPENCL_D3D11
2958 case AV_PIX_FMT_D3D11
:
2959 if (priv
->d3d11_mapping_usable
)
2960 return opencl_map_from_d3d11(hwfc
, dst
, src
, flags
);
2962 #if HAVE_OPENCL_DRM_ARM
2963 case AV_PIX_FMT_DRM_PRIME
:
2964 if (priv
->drm_arm_mapping_usable
)
2965 return opencl_map_from_drm_arm(hwfc
, dst
, src
, flags
);
2967 #if HAVE_OPENCL_VIDEOTOOLBOX
2968 case AV_PIX_FMT_VIDEOTOOLBOX
:
2969 return opencl_map_from_vt(hwfc
, dst
, src
, flags
);
2972 return AVERROR(ENOSYS
);
2975 static int opencl_frames_derive_to(AVHWFramesContext
*dst_fc
,
2976 AVHWFramesContext
*src_fc
, int flags
)
2978 av_unused OpenCLDeviceContext
*priv
= dst_fc
->device_ctx
->hwctx
;
2979 switch (src_fc
->device_ctx
->type
) {
2980 #if HAVE_OPENCL_DRM_BEIGNET
2981 case AV_HWDEVICE_TYPE_DRM
:
2982 if (!priv
->beignet_drm_mapping_usable
)
2983 return AVERROR(ENOSYS
);
2986 #if HAVE_OPENCL_VAAPI_BEIGNET
2987 case AV_HWDEVICE_TYPE_VAAPI
:
2988 if (!priv
->beignet_drm_mapping_usable
)
2989 return AVERROR(ENOSYS
);
2992 #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
2993 case AV_HWDEVICE_TYPE_QSV
:
2994 case AV_HWDEVICE_TYPE_VAAPI
:
2995 if (!priv
->qsv_mapping_usable
)
2996 return AVERROR(ENOSYS
);
2999 #if HAVE_OPENCL_DXVA2
3000 case AV_HWDEVICE_TYPE_DXVA2
:
3001 if (!priv
->dxva2_mapping_usable
)
3002 return AVERROR(ENOSYS
);
3005 err
= opencl_frames_derive_from_dxva2(dst_fc
, src_fc
, flags
);
3011 #if HAVE_OPENCL_D3D11
3012 case AV_HWDEVICE_TYPE_D3D11VA
:
3013 if (!priv
->d3d11_mapping_usable
)
3014 return AVERROR(ENOSYS
);
3017 err
= opencl_frames_derive_from_d3d11(dst_fc
, src_fc
, flags
);
3023 #if HAVE_OPENCL_DRM_ARM
3024 case AV_HWDEVICE_TYPE_DRM
:
3025 if (!priv
->drm_arm_mapping_usable
)
3026 return AVERROR(ENOSYS
);
3029 #if HAVE_OPENCL_VIDEOTOOLBOX
3030 case AV_HWDEVICE_TYPE_VIDEOTOOLBOX
:
3034 return AVERROR(ENOSYS
);
3036 return opencl_frames_init_command_queue(dst_fc
);
3039 const HWContextType ff_hwcontext_type_opencl
= {
3040 .type
= AV_HWDEVICE_TYPE_OPENCL
,
3043 .device_hwctx_size
= sizeof(OpenCLDeviceContext
),
3044 .frames_hwctx_size
= sizeof(OpenCLFramesContext
),
3046 .device_create
= &opencl_device_create
,
3047 .device_derive
= &opencl_device_derive
,
3048 .device_init
= &opencl_device_init
,
3049 .device_uninit
= &opencl_device_uninit
,
3051 .frames_get_constraints
= &opencl_frames_get_constraints
,
3052 .frames_init
= &opencl_frames_init
,
3053 .frames_uninit
= &opencl_frames_uninit
,
3054 .frames_get_buffer
= &opencl_get_buffer
,
3056 .transfer_get_formats
= &opencl_transfer_get_formats
,
3057 .transfer_data_to
= &opencl_transfer_data_to
,
3058 .transfer_data_from
= &opencl_transfer_data_from
,
3060 .map_from
= &opencl_map_from
,
3061 .map_to
= &opencl_map_to
,
3062 .frames_derive_to
= &opencl_frames_derive_to
,
3064 .pix_fmts
= (const enum AVPixelFormat
[]) {