You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2943 lines
95KB

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