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.

2364 lines
77KB

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