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.

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