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.

1967 lines
63KB

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