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.

2945 lines
96KB

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