hwcontext_opencl.c 96 KB

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