hwcontext_opencl.c 95 KB

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