12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939 |
- /*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
- #define CL_USE_DEPRECATED_OPENCL_1_2_APIS
- #include <string.h>
- #include "config.h"
- #include "avassert.h"
- #include "avstring.h"
- #include "common.h"
- #include "hwcontext.h"
- #include "hwcontext_internal.h"
- #include "hwcontext_opencl.h"
- #include "mem.h"
- #include "pixdesc.h"
- #if HAVE_OPENCL_VAAPI_BEIGNET
- #include <unistd.h>
- #include <va/va.h>
- #include <va/va_drmcommon.h>
- #include <CL/cl_intel.h>
- #include "hwcontext_vaapi.h"
- #endif
- #if HAVE_OPENCL_DRM_BEIGNET
- #include <unistd.h>
- #include <CL/cl_intel.h>
- #include "hwcontext_drm.h"
- #endif
- #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
- #if CONFIG_LIBMFX
- #include <mfx/mfxstructures.h>
- #endif
- #include <va/va.h>
- #include <CL/va_ext.h>
- #include "hwcontext_vaapi.h"
- #endif
- #if HAVE_OPENCL_DXVA2
- #define COBJMACROS
- #include <CL/cl_dx9_media_sharing.h>
- #include <dxva2api.h>
- #include "hwcontext_dxva2.h"
- #endif
- #if HAVE_OPENCL_D3D11
- #include <CL/cl_d3d11.h>
- #include "hwcontext_d3d11va.h"
- #endif
- #if HAVE_OPENCL_DRM_ARM
- #include <CL/cl_ext.h>
- #include <drm_fourcc.h>
- #include "hwcontext_drm.h"
- #endif
- typedef struct OpenCLDeviceContext {
- // Default command queue to use for transfer/mapping operations on
- // the device. If the user supplies one, this is a reference to it.
- // Otherwise, it is newly-created.
- cl_command_queue command_queue;
- // The platform the context exists on. This is needed to query and
- // retrieve extension functions.
- cl_platform_id platform_id;
- // Platform/device-specific functions.
- #if HAVE_OPENCL_DRM_BEIGNET
- int beignet_drm_mapping_usable;
- clCreateImageFromFdINTEL_fn clCreateImageFromFdINTEL;
- #endif
- #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
- int qsv_mapping_usable;
- clCreateFromVA_APIMediaSurfaceINTEL_fn
- clCreateFromVA_APIMediaSurfaceINTEL;
- clEnqueueAcquireVA_APIMediaSurfacesINTEL_fn
- clEnqueueAcquireVA_APIMediaSurfacesINTEL;
- clEnqueueReleaseVA_APIMediaSurfacesINTEL_fn
- clEnqueueReleaseVA_APIMediaSurfacesINTEL;
- #endif
- #if HAVE_OPENCL_DXVA2
- int dxva2_mapping_usable;
- cl_dx9_media_adapter_type_khr dx9_media_adapter_type;
- clCreateFromDX9MediaSurfaceKHR_fn
- clCreateFromDX9MediaSurfaceKHR;
- clEnqueueAcquireDX9MediaSurfacesKHR_fn
- clEnqueueAcquireDX9MediaSurfacesKHR;
- clEnqueueReleaseDX9MediaSurfacesKHR_fn
- clEnqueueReleaseDX9MediaSurfacesKHR;
- #endif
- #if HAVE_OPENCL_D3D11
- int d3d11_mapping_usable;
- clCreateFromD3D11Texture2DKHR_fn
- clCreateFromD3D11Texture2DKHR;
- clEnqueueAcquireD3D11ObjectsKHR_fn
- clEnqueueAcquireD3D11ObjectsKHR;
- clEnqueueReleaseD3D11ObjectsKHR_fn
- clEnqueueReleaseD3D11ObjectsKHR;
- #endif
- #if HAVE_OPENCL_DRM_ARM
- int drm_arm_mapping_usable;
- #endif
- } OpenCLDeviceContext;
- typedef struct OpenCLFramesContext {
- // Command queue used for transfer/mapping operations on this frames
- // context. If the user supplies one, this is a reference to it.
- // Otherwise, it is a reference to the default command queue for the
- // device.
- cl_command_queue command_queue;
- #if HAVE_OPENCL_DXVA2 || HAVE_OPENCL_D3D11
- // For mapping APIs which have separate creation and acquire/release
- // steps, this stores the OpenCL memory objects corresponding to each
- // frame.
- int nb_mapped_frames;
- AVOpenCLFrameDescriptor *mapped_frames;
- #endif
- } OpenCLFramesContext;
- static void CL_CALLBACK opencl_error_callback(const char *errinfo,
- const void *private_info,
- size_t cb,
- void *user_data)
- {
- AVHWDeviceContext *ctx = user_data;
- av_log(ctx, AV_LOG_ERROR, "OpenCL error: %s\n", errinfo);
- }
- static void opencl_device_free(AVHWDeviceContext *hwdev)
- {
- AVOpenCLDeviceContext *hwctx = hwdev->hwctx;
- cl_int cle;
- cle = clReleaseContext(hwctx->context);
- if (cle != CL_SUCCESS) {
- av_log(hwdev, AV_LOG_ERROR, "Failed to release OpenCL "
- "context: %d.\n", cle);
- }
- }
- static struct {
- const char *key;
- cl_platform_info name;
- } opencl_platform_params[] = {
- { "platform_profile", CL_PLATFORM_PROFILE },
- { "platform_version", CL_PLATFORM_VERSION },
- { "platform_name", CL_PLATFORM_NAME },
- { "platform_vendor", CL_PLATFORM_VENDOR },
- { "platform_extensions", CL_PLATFORM_EXTENSIONS },
- };
- static struct {
- const char *key;
- cl_device_info name;
- } opencl_device_params[] = {
- { "device_name", CL_DEVICE_NAME },
- { "device_vendor", CL_DEVICE_VENDOR },
- { "driver_version", CL_DRIVER_VERSION },
- { "device_version", CL_DEVICE_VERSION },
- { "device_profile", CL_DEVICE_PROFILE },
- { "device_extensions", CL_DEVICE_EXTENSIONS },
- };
- static struct {
- const char *key;
- cl_device_type type;
- } opencl_device_types[] = {
- { "cpu", CL_DEVICE_TYPE_CPU },
- { "gpu", CL_DEVICE_TYPE_GPU },
- { "accelerator", CL_DEVICE_TYPE_ACCELERATOR },
- { "custom", CL_DEVICE_TYPE_CUSTOM },
- { "default", CL_DEVICE_TYPE_DEFAULT },
- { "all", CL_DEVICE_TYPE_ALL },
- };
- static char *opencl_get_platform_string(cl_platform_id platform_id,
- cl_platform_info key)
- {
- char *str;
- size_t size;
- cl_int cle;
- cle = clGetPlatformInfo(platform_id, key, 0, NULL, &size);
- if (cle != CL_SUCCESS)
- return NULL;
- str = av_malloc(size);
- if (!str)
- return NULL;
- cle = clGetPlatformInfo(platform_id, key, size, str, &size);
- if (cle != CL_SUCCESS) {
- av_free(str);
- return NULL;
- }
- av_assert0(strlen(str) + 1 == size);
- return str;
- }
- static char *opencl_get_device_string(cl_device_id device_id,
- cl_device_info key)
- {
- char *str;
- size_t size;
- cl_int cle;
- cle = clGetDeviceInfo(device_id, key, 0, NULL, &size);
- if (cle != CL_SUCCESS)
- return NULL;
- str = av_malloc(size);
- if (!str)
- return NULL;
- cle = clGetDeviceInfo(device_id, key, size, str, &size);
- if (cle != CL_SUCCESS) {
- av_free(str);
- return NULL;
- }
- av_assert0(strlen(str) + 1== size);
- return str;
- }
- static int opencl_check_platform_extension(cl_platform_id platform_id,
- const char *name)
- {
- char *str;
- int found = 0;
- str = opencl_get_platform_string(platform_id,
- CL_PLATFORM_EXTENSIONS);
- if (str && strstr(str, name))
- found = 1;
- av_free(str);
- return found;
- }
- static int opencl_check_device_extension(cl_device_id device_id,
- const char *name)
- {
- char *str;
- int found = 0;
- str = opencl_get_device_string(device_id,
- CL_DEVICE_EXTENSIONS);
- if (str && strstr(str, name))
- found = 1;
- av_free(str);
- return found;
- }
- static av_unused int opencl_check_extension(AVHWDeviceContext *hwdev,
- const char *name)
- {
- AVOpenCLDeviceContext *hwctx = hwdev->hwctx;
- OpenCLDeviceContext *priv = hwdev->internal->priv;
- if (opencl_check_platform_extension(priv->platform_id, name)) {
- av_log(hwdev, AV_LOG_DEBUG,
- "%s found as platform extension.\n", name);
- return 1;
- }
- if (opencl_check_device_extension(hwctx->device_id, name)) {
- av_log(hwdev, AV_LOG_DEBUG,
- "%s found as device extension.\n", name);
- return 1;
- }
- return 0;
- }
- static int opencl_enumerate_platforms(AVHWDeviceContext *hwdev,
- cl_uint *nb_platforms,
- cl_platform_id **platforms,
- void *context)
- {
- cl_int cle;
- cle = clGetPlatformIDs(0, NULL, nb_platforms);
- if (cle != CL_SUCCESS) {
- av_log(hwdev, AV_LOG_ERROR, "Failed to get number of "
- "OpenCL platforms: %d.\n", cle);
- return AVERROR(ENODEV);
- }
- av_log(hwdev, AV_LOG_DEBUG, "%u OpenCL platforms found.\n",
- *nb_platforms);
- *platforms = av_malloc_array(*nb_platforms, sizeof(**platforms));
- if (!*platforms)
- return AVERROR(ENOMEM);
- cle = clGetPlatformIDs(*nb_platforms, *platforms, NULL);
- if (cle != CL_SUCCESS) {
- av_log(hwdev, AV_LOG_ERROR, "Failed to get list of OpenCL "
- "platforms: %d.\n", cle);
- av_freep(platforms);
- return AVERROR(ENODEV);
- }
- return 0;
- }
- static int opencl_filter_platform(AVHWDeviceContext *hwdev,
- cl_platform_id platform_id,
- const char *platform_name,
- void *context)
- {
- AVDictionary *opts = context;
- const AVDictionaryEntry *param;
- char *str;
- int i, ret = 0;
- for (i = 0; i < FF_ARRAY_ELEMS(opencl_platform_params); i++) {
- param = av_dict_get(opts, opencl_platform_params[i].key,
- NULL, 0);
- if (!param)
- continue;
- str = opencl_get_platform_string(platform_id,
- opencl_platform_params[i].name);
- if (!str) {
- av_log(hwdev, AV_LOG_ERROR, "Failed to query %s "
- "of platform \"%s\".\n",
- opencl_platform_params[i].key, platform_name);
- return AVERROR_UNKNOWN;
- }
- if (!av_stristr(str, param->value)) {
- av_log(hwdev, AV_LOG_DEBUG, "%s does not match (\"%s\").\n",
- param->key, str);
- ret = 1;
- }
- av_free(str);
- }
- return ret;
- }
- static int opencl_enumerate_devices(AVHWDeviceContext *hwdev,
- cl_platform_id platform_id,
- const char *platform_name,
- cl_uint *nb_devices,
- cl_device_id **devices,
- void *context)
- {
- cl_int cle;
- cle = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_ALL,
- 0, NULL, nb_devices);
- if (cle == CL_DEVICE_NOT_FOUND) {
- av_log(hwdev, AV_LOG_DEBUG, "No devices found "
- "on platform \"%s\".\n", platform_name);
- *nb_devices = 0;
- return 0;
- } else if (cle != CL_SUCCESS) {
- av_log(hwdev, AV_LOG_ERROR, "Failed to get number of devices "
- "on platform \"%s\": %d.\n", platform_name, cle);
- return AVERROR(ENODEV);
- }
- av_log(hwdev, AV_LOG_DEBUG, "%u OpenCL devices found on "
- "platform \"%s\".\n", *nb_devices, platform_name);
- *devices = av_malloc_array(*nb_devices, sizeof(**devices));
- if (!*devices)
- return AVERROR(ENOMEM);
- cle = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_ALL,
- *nb_devices, *devices, NULL);
- if (cle != CL_SUCCESS) {
- av_log(hwdev, AV_LOG_ERROR, "Failed to get list of devices "
- "on platform \"%s\": %d.\n", platform_name, cle);
- av_freep(devices);
- return AVERROR(ENODEV);
- }
- return 0;
- }
- static int opencl_filter_device(AVHWDeviceContext *hwdev,
- cl_device_id device_id,
- const char *device_name,
- void *context)
- {
- AVDictionary *opts = context;
- const AVDictionaryEntry *param;
- char *str;
- int i, ret = 0;
- param = av_dict_get(opts, "device_type", NULL, 0);
- if (param) {
- cl_device_type match_type = 0, device_type;
- cl_int cle;
- for (i = 0; i < FF_ARRAY_ELEMS(opencl_device_types); i++) {
- if (!strcmp(opencl_device_types[i].key, param->value)) {
- match_type = opencl_device_types[i].type;
- break;
- }
- }
- if (!match_type) {
- av_log(hwdev, AV_LOG_ERROR, "Unknown device type %s.\n",
- param->value);
- return AVERROR(EINVAL);
- }
- cle = clGetDeviceInfo(device_id, CL_DEVICE_TYPE,
- sizeof(device_type), &device_type, NULL);
- if (cle != CL_SUCCESS) {
- av_log(hwdev, AV_LOG_ERROR, "Failed to query device type "
- "of device \"%s\".\n", device_name);
- return AVERROR_UNKNOWN;
- }
- if (!(device_type & match_type)) {
- av_log(hwdev, AV_LOG_DEBUG, "device_type does not match.\n");
- return 1;
- }
- }
- for (i = 0; i < FF_ARRAY_ELEMS(opencl_device_params); i++) {
- param = av_dict_get(opts, opencl_device_params[i].key,
- NULL, 0);
- if (!param)
- continue;
- str = opencl_get_device_string(device_id,
- opencl_device_params[i].name);
- if (!str) {
- av_log(hwdev, AV_LOG_ERROR, "Failed to query %s "
- "of device \"%s\".\n",
- opencl_device_params[i].key, device_name);
- return AVERROR_UNKNOWN;
- }
- if (!av_stristr(str, param->value)) {
- av_log(hwdev, AV_LOG_DEBUG, "%s does not match (\"%s\").\n",
- param->key, str);
- ret = 1;
- }
- av_free(str);
- }
- return ret;
- }
- typedef struct OpenCLDeviceSelector {
- int platform_index;
- int device_index;
- void *context;
- int (*enumerate_platforms)(AVHWDeviceContext *hwdev,
- cl_uint *nb_platforms,
- cl_platform_id **platforms,
- void *context);
- int (*filter_platform) (AVHWDeviceContext *hwdev,
- cl_platform_id platform_id,
- const char *platform_name,
- void *context);
- int (*enumerate_devices) (AVHWDeviceContext *hwdev,
- cl_platform_id platform_id,
- const char *platform_name,
- cl_uint *nb_devices,
- cl_device_id **devices,
- void *context);
- int (*filter_device) (AVHWDeviceContext *hwdev,
- cl_device_id device_id,
- const char *device_name,
- void *context);
- } OpenCLDeviceSelector;
- static int opencl_device_create_internal(AVHWDeviceContext *hwdev,
- const OpenCLDeviceSelector *selector,
- cl_context_properties *props)
- {
- cl_uint nb_platforms;
- cl_platform_id *platforms = NULL;
- cl_platform_id platform_id;
- cl_uint nb_devices;
- cl_device_id *devices = NULL;
- AVOpenCLDeviceContext *hwctx = hwdev->hwctx;
- cl_int cle;
- cl_context_properties default_props[3];
- char *platform_name_src = NULL,
- *device_name_src = NULL;
- int err, found, p, d;
- err = selector->enumerate_platforms(hwdev, &nb_platforms, &platforms,
- selector->context);
- if (err)
- return err;
- found = 0;
- for (p = 0; p < nb_platforms; p++) {
- const char *platform_name;
- if (selector->platform_index >= 0 &&
- selector->platform_index != p)
- continue;
- av_freep(&platform_name_src);
- platform_name_src = opencl_get_platform_string(platforms[p],
- CL_PLATFORM_NAME);
- if (platform_name_src)
- platform_name = platform_name_src;
- else
- platform_name = "Unknown Platform";
- if (selector->filter_platform) {
- err = selector->filter_platform(hwdev, platforms[p],
- platform_name,
- selector->context);
- if (err < 0)
- goto fail;
- if (err > 0)
- continue;
- }
- err = opencl_enumerate_devices(hwdev, platforms[p], platform_name,
- &nb_devices, &devices,
- selector->context);
- if (err < 0)
- continue;
- for (d = 0; d < nb_devices; d++) {
- const char *device_name;
- if (selector->device_index >= 0 &&
- selector->device_index != d)
- continue;
- av_freep(&device_name_src);
- device_name_src = opencl_get_device_string(devices[d],
- CL_DEVICE_NAME);
- if (device_name_src)
- device_name = device_name_src;
- else
- device_name = "Unknown Device";
- if (selector->filter_device) {
- err = selector->filter_device(hwdev, devices[d],
- device_name,
- selector->context);
- if (err < 0)
- goto fail;
- if (err > 0)
- continue;
- }
- av_log(hwdev, AV_LOG_VERBOSE, "%d.%d: %s / %s\n", p, d,
- platform_name, device_name);
- ++found;
- platform_id = platforms[p];
- hwctx->device_id = devices[d];
- }
- av_freep(&devices);
- }
- if (found == 0) {
- av_log(hwdev, AV_LOG_ERROR, "No matching devices found.\n");
- err = AVERROR(ENODEV);
- goto fail;
- }
- if (found > 1) {
- av_log(hwdev, AV_LOG_ERROR, "More than one matching device found.\n");
- err = AVERROR(ENODEV);
- goto fail;
- }
- if (!props) {
- props = default_props;
- default_props[0] = CL_CONTEXT_PLATFORM;
- default_props[1] = (intptr_t)platform_id;
- default_props[2] = 0;
- } else {
- if (props[0] == CL_CONTEXT_PLATFORM && props[1] == 0)
- props[1] = (intptr_t)platform_id;
- }
- hwctx->context = clCreateContext(props, 1, &hwctx->device_id,
- &opencl_error_callback, hwdev, &cle);
- if (!hwctx->context) {
- av_log(hwdev, AV_LOG_ERROR, "Failed to create OpenCL context: "
- "%d.\n", cle);
- err = AVERROR(ENODEV);
- goto fail;
- }
- hwdev->free = &opencl_device_free;
- err = 0;
- fail:
- av_freep(&platform_name_src);
- av_freep(&device_name_src);
- av_freep(&platforms);
- av_freep(&devices);
- return err;
- }
- static int opencl_device_create(AVHWDeviceContext *hwdev, const char *device,
- AVDictionary *opts, int flags)
- {
- OpenCLDeviceSelector selector = {
- .context = opts,
- .enumerate_platforms = &opencl_enumerate_platforms,
- .filter_platform = &opencl_filter_platform,
- .enumerate_devices = &opencl_enumerate_devices,
- .filter_device = &opencl_filter_device,
- };
- if (device && device[0]) {
- // Match one or both indices for platform and device.
- int d = -1, p = -1, ret;
- if (device[0] == '.')
- ret = sscanf(device, ".%d", &d);
- else
- ret = sscanf(device, "%d.%d", &p, &d);
- if (ret < 1) {
- av_log(hwdev, AV_LOG_ERROR, "Invalid OpenCL platform/device "
- "index specification \"%s\".\n", device);
- return AVERROR(EINVAL);
- }
- selector.platform_index = p;
- selector.device_index = d;
- } else {
- selector.platform_index = -1;
- selector.device_index = -1;
- }
- return opencl_device_create_internal(hwdev, &selector, NULL);
- }
- static int opencl_device_init(AVHWDeviceContext *hwdev)
- {
- AVOpenCLDeviceContext *hwctx = hwdev->hwctx;
- OpenCLDeviceContext *priv = hwdev->internal->priv;
- cl_int cle;
- if (hwctx->command_queue) {
- cle = clRetainCommandQueue(hwctx->command_queue);
- if (cle != CL_SUCCESS) {
- av_log(hwdev, AV_LOG_ERROR, "Failed to retain external "
- "command queue: %d.\n", cle);
- return AVERROR(EIO);
- }
- priv->command_queue = hwctx->command_queue;
- } else {
- priv->command_queue = clCreateCommandQueue(hwctx->context,
- hwctx->device_id,
- 0, &cle);
- if (!priv->command_queue) {
- av_log(hwdev, AV_LOG_ERROR, "Failed to create internal "
- "command queue: %d.\n", cle);
- return AVERROR(EIO);
- }
- }
- cle = clGetDeviceInfo(hwctx->device_id, CL_DEVICE_PLATFORM,
- sizeof(priv->platform_id), &priv->platform_id,
- NULL);
- if (cle != CL_SUCCESS) {
- av_log(hwdev, AV_LOG_ERROR, "Failed to determine the OpenCL "
- "platform containing the device.\n");
- return AVERROR(EIO);
- }
- #define CL_FUNC(name, desc) do { \
- if (fail) \
- break; \
- priv->name = clGetExtensionFunctionAddressForPlatform( \
- priv->platform_id, #name); \
- if (!priv->name) { \
- av_log(hwdev, AV_LOG_VERBOSE, \
- desc " function not found (%s).\n", #name); \
- fail = 1; \
- } else { \
- av_log(hwdev, AV_LOG_VERBOSE, \
- desc " function found (%s).\n", #name); \
- } \
- } while (0)
- #if HAVE_OPENCL_DRM_BEIGNET
- {
- int fail = 0;
- CL_FUNC(clCreateImageFromFdINTEL,
- "Beignet DRM to OpenCL image mapping");
- if (fail) {
- av_log(hwdev, AV_LOG_WARNING, "Beignet DRM to OpenCL "
- "mapping not usable.\n");
- priv->beignet_drm_mapping_usable = 0;
- } else {
- priv->beignet_drm_mapping_usable = 1;
- }
- }
- #endif
- #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
- {
- size_t props_size;
- cl_context_properties *props = NULL;
- VADisplay va_display;
- const char *va_ext = "cl_intel_va_api_media_sharing";
- int i, fail = 0;
- if (!opencl_check_extension(hwdev, va_ext)) {
- av_log(hwdev, AV_LOG_VERBOSE, "The %s extension is "
- "required for QSV to OpenCL mapping.\n", va_ext);
- goto no_qsv;
- }
- cle = clGetContextInfo(hwctx->context, CL_CONTEXT_PROPERTIES,
- 0, NULL, &props_size);
- if (cle != CL_SUCCESS) {
- av_log(hwdev, AV_LOG_VERBOSE, "Failed to get context "
- "properties: %d.\n", cle);
- goto no_qsv;
- }
- if (props_size == 0) {
- av_log(hwdev, AV_LOG_VERBOSE, "Media sharing must be "
- "enabled on context creation to use QSV to "
- "OpenCL mapping.\n");
- goto no_qsv;
- }
- props = av_malloc(props_size);
- if (!props)
- return AVERROR(ENOMEM);
- cle = clGetContextInfo(hwctx->context, CL_CONTEXT_PROPERTIES,
- props_size, props, NULL);
- if (cle != CL_SUCCESS) {
- av_log(hwdev, AV_LOG_VERBOSE, "Failed to get context "
- "properties: %d.\n", cle);
- goto no_qsv;
- }
- va_display = NULL;
- for (i = 0; i < (props_size / sizeof(*props) - 1); i++) {
- if (props[i] == CL_CONTEXT_VA_API_DISPLAY_INTEL) {
- va_display = (VADisplay)(intptr_t)props[i+1];
- break;
- }
- }
- if (!va_display) {
- av_log(hwdev, AV_LOG_VERBOSE, "Media sharing must be "
- "enabled on context creation to use QSV to "
- "OpenCL mapping.\n");
- goto no_qsv;
- }
- if (!vaDisplayIsValid(va_display)) {
- av_log(hwdev, AV_LOG_VERBOSE, "A valid VADisplay is "
- "required on context creation to use QSV to "
- "OpenCL mapping.\n");
- goto no_qsv;
- }
- CL_FUNC(clCreateFromVA_APIMediaSurfaceINTEL,
- "Intel QSV to OpenCL mapping");
- CL_FUNC(clEnqueueAcquireVA_APIMediaSurfacesINTEL,
- "Intel QSV in OpenCL acquire");
- CL_FUNC(clEnqueueReleaseVA_APIMediaSurfacesINTEL,
- "Intel QSV in OpenCL release");
- if (fail) {
- no_qsv:
- av_log(hwdev, AV_LOG_WARNING, "QSV to OpenCL mapping "
- "not usable.\n");
- priv->qsv_mapping_usable = 0;
- } else {
- priv->qsv_mapping_usable = 1;
- }
- av_free(props);
- }
- #endif
- #if HAVE_OPENCL_DXVA2
- {
- int fail = 0;
- CL_FUNC(clCreateFromDX9MediaSurfaceKHR,
- "DXVA2 to OpenCL mapping");
- CL_FUNC(clEnqueueAcquireDX9MediaSurfacesKHR,
- "DXVA2 in OpenCL acquire");
- CL_FUNC(clEnqueueReleaseDX9MediaSurfacesKHR,
- "DXVA2 in OpenCL release");
- if (fail) {
- av_log(hwdev, AV_LOG_WARNING, "DXVA2 to OpenCL mapping "
- "not usable.\n");
- priv->dxva2_mapping_usable = 0;
- } else {
- priv->dx9_media_adapter_type = CL_ADAPTER_D3D9EX_KHR;
- priv->dxva2_mapping_usable = 1;
- }
- }
- #endif
- #if HAVE_OPENCL_D3D11
- {
- const char *d3d11_ext = "cl_khr_d3d11_sharing";
- const char *nv12_ext = "cl_intel_d3d11_nv12_media_sharing";
- int fail = 0;
- if (!opencl_check_extension(hwdev, d3d11_ext)) {
- av_log(hwdev, AV_LOG_VERBOSE, "The %s extension is "
- "required for D3D11 to OpenCL mapping.\n", d3d11_ext);
- fail = 1;
- } else if (!opencl_check_extension(hwdev, nv12_ext)) {
- av_log(hwdev, AV_LOG_VERBOSE, "The %s extension may be "
- "required for D3D11 to OpenCL mapping.\n", nv12_ext);
- // Not fatal.
- }
- CL_FUNC(clCreateFromD3D11Texture2DKHR,
- "D3D11 to OpenCL mapping");
- CL_FUNC(clEnqueueAcquireD3D11ObjectsKHR,
- "D3D11 in OpenCL acquire");
- CL_FUNC(clEnqueueReleaseD3D11ObjectsKHR,
- "D3D11 in OpenCL release");
- if (fail) {
- av_log(hwdev, AV_LOG_WARNING, "D3D11 to OpenCL mapping "
- "not usable.\n");
- priv->d3d11_mapping_usable = 0;
- } else {
- priv->d3d11_mapping_usable = 1;
- }
- }
- #endif
- #if HAVE_OPENCL_DRM_ARM
- {
- const char *drm_arm_ext = "cl_arm_import_memory";
- const char *image_ext = "cl_khr_image2d_from_buffer";
- int fail = 0;
- if (!opencl_check_extension(hwdev, drm_arm_ext)) {
- av_log(hwdev, AV_LOG_VERBOSE, "The %s extension is "
- "required for DRM to OpenCL mapping on ARM.\n",
- drm_arm_ext);
- fail = 1;
- }
- if (!opencl_check_extension(hwdev, image_ext)) {
- av_log(hwdev, AV_LOG_VERBOSE, "The %s extension is "
- "required for DRM to OpenCL mapping on ARM.\n",
- image_ext);
- fail = 1;
- }
- // clImportMemoryARM() is linked statically.
- if (fail) {
- av_log(hwdev, AV_LOG_WARNING, "DRM to OpenCL mapping on ARM "
- "not usable.\n");
- priv->drm_arm_mapping_usable = 0;
- } else {
- priv->drm_arm_mapping_usable = 1;
- }
- }
- #endif
- #undef CL_FUNC
- return 0;
- }
- static void opencl_device_uninit(AVHWDeviceContext *hwdev)
- {
- OpenCLDeviceContext *priv = hwdev->internal->priv;
- cl_int cle;
- if (priv->command_queue) {
- cle = clReleaseCommandQueue(priv->command_queue);
- if (cle != CL_SUCCESS) {
- av_log(hwdev, AV_LOG_ERROR, "Failed to release internal "
- "command queue reference: %d.\n", cle);
- }
- priv->command_queue = NULL;
- }
- }
- #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
- static int opencl_filter_intel_media_vaapi_platform(AVHWDeviceContext *hwdev,
- cl_platform_id platform_id,
- const char *platform_name,
- void *context)
- {
- // This doesn't exist as a platform extension, so just test whether
- // the function we will use for device enumeration exists.
- if (!clGetExtensionFunctionAddressForPlatform(platform_id,
- "clGetDeviceIDsFromVA_APIMediaAdapterINTEL")) {
- av_log(hwdev, AV_LOG_DEBUG, "Platform %s does not export the "
- "VAAPI device enumeration function.\n", platform_name);
- return 1;
- } else {
- return 0;
- }
- }
- static int opencl_enumerate_intel_media_vaapi_devices(AVHWDeviceContext *hwdev,
- cl_platform_id platform_id,
- const char *platform_name,
- cl_uint *nb_devices,
- cl_device_id **devices,
- void *context)
- {
- VADisplay va_display = context;
- clGetDeviceIDsFromVA_APIMediaAdapterINTEL_fn
- clGetDeviceIDsFromVA_APIMediaAdapterINTEL;
- cl_int cle;
- clGetDeviceIDsFromVA_APIMediaAdapterINTEL =
- clGetExtensionFunctionAddressForPlatform(platform_id,
- "clGetDeviceIDsFromVA_APIMediaAdapterINTEL");
- if (!clGetDeviceIDsFromVA_APIMediaAdapterINTEL) {
- av_log(hwdev, AV_LOG_ERROR, "Failed to get address of "
- "clGetDeviceIDsFromVA_APIMediaAdapterINTEL().\n");
- return AVERROR_UNKNOWN;
- }
- cle = clGetDeviceIDsFromVA_APIMediaAdapterINTEL(
- platform_id, CL_VA_API_DISPLAY_INTEL, va_display,
- CL_PREFERRED_DEVICES_FOR_VA_API_INTEL, 0, NULL, nb_devices);
- if (cle == CL_DEVICE_NOT_FOUND) {
- av_log(hwdev, AV_LOG_DEBUG, "No VAAPI-supporting devices found "
- "on platform \"%s\".\n", platform_name);
- *nb_devices = 0;
- return 0;
- } else if (cle != CL_SUCCESS) {
- av_log(hwdev, AV_LOG_ERROR, "Failed to get number of devices "
- "on platform \"%s\": %d.\n", platform_name, cle);
- return AVERROR_UNKNOWN;
- }
- *devices = av_malloc_array(*nb_devices, sizeof(**devices));
- if (!*devices)
- return AVERROR(ENOMEM);
- cle = clGetDeviceIDsFromVA_APIMediaAdapterINTEL(
- platform_id, CL_VA_API_DISPLAY_INTEL, va_display,
- CL_PREFERRED_DEVICES_FOR_VA_API_INTEL, *nb_devices, *devices, NULL);
- if (cle != CL_SUCCESS) {
- av_log(hwdev, AV_LOG_ERROR, "Failed to get list of VAAPI-supporting "
- "devices on platform \"%s\": %d.\n", platform_name, cle);
- av_freep(devices);
- return AVERROR_UNKNOWN;
- }
- return 0;
- }
- static int opencl_filter_intel_media_vaapi_device(AVHWDeviceContext *hwdev,
- cl_device_id device_id,
- const char *device_name,
- void *context)
- {
- const char *va_ext = "cl_intel_va_api_media_sharing";
- if (opencl_check_device_extension(device_id, va_ext)) {
- return 0;
- } else {
- av_log(hwdev, AV_LOG_DEBUG, "Device %s does not support the "
- "%s extension.\n", device_name, va_ext);
- return 1;
- }
- }
- #endif
- #if HAVE_OPENCL_DXVA2
- static int opencl_filter_dxva2_platform(AVHWDeviceContext *hwdev,
- cl_platform_id platform_id,
- const char *platform_name,
- void *context)
- {
- const char *dx9_ext = "cl_khr_dx9_media_sharing";
- if (opencl_check_platform_extension(platform_id, dx9_ext)) {
- return 0;
- } else {
- av_log(hwdev, AV_LOG_DEBUG, "Platform %s does not support the "
- "%s extension.\n", platform_name, dx9_ext);
- return 1;
- }
- }
- static int opencl_enumerate_dxva2_devices(AVHWDeviceContext *hwdev,
- cl_platform_id platform_id,
- const char *platform_name,
- cl_uint *nb_devices,
- cl_device_id **devices,
- void *context)
- {
- IDirect3DDevice9 *device = context;
- clGetDeviceIDsFromDX9MediaAdapterKHR_fn
- clGetDeviceIDsFromDX9MediaAdapterKHR;
- cl_dx9_media_adapter_type_khr media_adapter_type = CL_ADAPTER_D3D9EX_KHR;
- cl_int cle;
- clGetDeviceIDsFromDX9MediaAdapterKHR =
- clGetExtensionFunctionAddressForPlatform(platform_id,
- "clGetDeviceIDsFromDX9MediaAdapterKHR");
- if (!clGetDeviceIDsFromDX9MediaAdapterKHR) {
- av_log(hwdev, AV_LOG_ERROR, "Failed to get address of "
- "clGetDeviceIDsFromDX9MediaAdapterKHR().\n");
- return AVERROR_UNKNOWN;
- }
- cle = clGetDeviceIDsFromDX9MediaAdapterKHR(
- platform_id, 1, &media_adapter_type, (void**)&device,
- CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR,
- 0, NULL, nb_devices);
- if (cle == CL_DEVICE_NOT_FOUND) {
- av_log(hwdev, AV_LOG_DEBUG, "No DXVA2-supporting devices found "
- "on platform \"%s\".\n", platform_name);
- *nb_devices = 0;
- return 0;
- } else if (cle != CL_SUCCESS) {
- av_log(hwdev, AV_LOG_ERROR, "Failed to get number of devices "
- "on platform \"%s\": %d.\n", platform_name, cle);
- return AVERROR_UNKNOWN;
- }
- *devices = av_malloc_array(*nb_devices, sizeof(**devices));
- if (!*devices)
- return AVERROR(ENOMEM);
- cle = clGetDeviceIDsFromDX9MediaAdapterKHR(
- platform_id, 1, &media_adapter_type, (void**)&device,
- CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR,
- *nb_devices, *devices, NULL);
- if (cle != CL_SUCCESS) {
- av_log(hwdev, AV_LOG_ERROR, "Failed to get list of DXVA2-supporting "
- "devices on platform \"%s\": %d.\n", platform_name, cle);
- av_freep(devices);
- return AVERROR_UNKNOWN;
- }
- return 0;
- }
- #endif
- #if HAVE_OPENCL_D3D11
- static int opencl_filter_d3d11_platform(AVHWDeviceContext *hwdev,
- cl_platform_id platform_id,
- const char *platform_name,
- void *context)
- {
- const char *d3d11_ext = "cl_khr_d3d11_sharing";
- if (opencl_check_platform_extension(platform_id, d3d11_ext)) {
- return 0;
- } else {
- av_log(hwdev, AV_LOG_DEBUG, "Platform %s does not support the "
- "%s extension.\n", platform_name, d3d11_ext);
- return 1;
- }
- }
- static int opencl_enumerate_d3d11_devices(AVHWDeviceContext *hwdev,
- cl_platform_id platform_id,
- const char *platform_name,
- cl_uint *nb_devices,
- cl_device_id **devices,
- void *context)
- {
- ID3D11Device *device = context;
- clGetDeviceIDsFromD3D11KHR_fn clGetDeviceIDsFromD3D11KHR;
- cl_int cle;
- clGetDeviceIDsFromD3D11KHR =
- clGetExtensionFunctionAddressForPlatform(platform_id,
- "clGetDeviceIDsFromD3D11KHR");
- if (!clGetDeviceIDsFromD3D11KHR) {
- av_log(hwdev, AV_LOG_ERROR, "Failed to get address of "
- "clGetDeviceIDsFromD3D11KHR().\n");
- return AVERROR_UNKNOWN;
- }
- cle = clGetDeviceIDsFromD3D11KHR(platform_id,
- CL_D3D11_DEVICE_KHR, device,
- CL_PREFERRED_DEVICES_FOR_D3D11_KHR,
- 0, NULL, nb_devices);
- if (cle == CL_DEVICE_NOT_FOUND) {
- av_log(hwdev, AV_LOG_DEBUG, "No D3D11-supporting devices found "
- "on platform \"%s\".\n", platform_name);
- *nb_devices = 0;
- return 0;
- } else if (cle != CL_SUCCESS) {
- av_log(hwdev, AV_LOG_ERROR, "Failed to get number of devices "
- "on platform \"%s\": %d.\n", platform_name, cle);
- return AVERROR_UNKNOWN;
- }
- *devices = av_malloc_array(*nb_devices, sizeof(**devices));
- if (!*devices)
- return AVERROR(ENOMEM);
- cle = clGetDeviceIDsFromD3D11KHR(platform_id,
- CL_D3D11_DEVICE_KHR, device,
- CL_PREFERRED_DEVICES_FOR_D3D11_KHR,
- *nb_devices, *devices, NULL);
- if (cle != CL_SUCCESS) {
- av_log(hwdev, AV_LOG_ERROR, "Failed to get list of D3D11-supporting "
- "devices on platform \"%s\": %d.\n", platform_name, cle);
- av_freep(devices);
- return AVERROR_UNKNOWN;
- }
- return 0;
- }
- #endif
- #if HAVE_OPENCL_DXVA2 || HAVE_OPENCL_D3D11
- static int opencl_filter_gpu_device(AVHWDeviceContext *hwdev,
- cl_device_id device_id,
- const char *device_name,
- void *context)
- {
- cl_device_type device_type;
- cl_int cle;
- cle = clGetDeviceInfo(device_id, CL_DEVICE_TYPE,
- sizeof(device_type), &device_type, NULL);
- if (cle != CL_SUCCESS) {
- av_log(hwdev, AV_LOG_ERROR, "Failed to query device type "
- "of device \"%s\".\n", device_name);
- return AVERROR_UNKNOWN;
- }
- if (!(device_type & CL_DEVICE_TYPE_GPU)) {
- av_log(hwdev, AV_LOG_DEBUG, "Device %s skipped (not GPU).\n",
- device_name);
- return 1;
- }
- return 0;
- }
- #endif
- #if HAVE_OPENCL_DRM_ARM
- static int opencl_filter_drm_arm_platform(AVHWDeviceContext *hwdev,
- cl_platform_id platform_id,
- const char *platform_name,
- void *context)
- {
- const char *drm_arm_ext = "cl_arm_import_memory";
- if (opencl_check_platform_extension(platform_id, drm_arm_ext)) {
- return 0;
- } else {
- av_log(hwdev, AV_LOG_DEBUG, "Platform %s does not support the "
- "%s extension.\n", platform_name, drm_arm_ext);
- return 1;
- }
- }
- static int opencl_filter_drm_arm_device(AVHWDeviceContext *hwdev,
- cl_device_id device_id,
- const char *device_name,
- void *context)
- {
- const char *drm_arm_ext = "cl_arm_import_memory";
- if (opencl_check_device_extension(device_id, drm_arm_ext)) {
- return 0;
- } else {
- av_log(hwdev, AV_LOG_DEBUG, "Device %s does not support the "
- "%s extension.\n", device_name, drm_arm_ext);
- return 1;
- }
- }
- #endif
- static int opencl_device_derive(AVHWDeviceContext *hwdev,
- AVHWDeviceContext *src_ctx,
- int flags)
- {
- int err;
- switch (src_ctx->type) {
- #if HAVE_OPENCL_DRM_BEIGNET
- case AV_HWDEVICE_TYPE_DRM:
- case AV_HWDEVICE_TYPE_VAAPI:
- {
- // Surface mapping works via DRM PRIME fds with no special
- // initialisation required in advance. This just finds the
- // Beignet ICD by name.
- AVDictionary *opts = NULL;
- err = av_dict_set(&opts, "platform_vendor", "Intel", 0);
- if (err >= 0)
- err = av_dict_set(&opts, "platform_version", "beignet", 0);
- if (err >= 0) {
- OpenCLDeviceSelector selector = {
- .platform_index = -1,
- .device_index = 0,
- .context = opts,
- .enumerate_platforms = &opencl_enumerate_platforms,
- .filter_platform = &opencl_filter_platform,
- .enumerate_devices = &opencl_enumerate_devices,
- .filter_device = NULL,
- };
- err = opencl_device_create_internal(hwdev, &selector, NULL);
- }
- av_dict_free(&opts);
- }
- break;
- #endif
- #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
- // The generic code automatically attempts to derive from all
- // ancestors of the given device, so we can ignore QSV devices here
- // and just consider the inner VAAPI device it was derived from.
- case AV_HWDEVICE_TYPE_VAAPI:
- {
- AVVAAPIDeviceContext *src_hwctx = src_ctx->hwctx;
- cl_context_properties props[7] = {
- CL_CONTEXT_PLATFORM,
- 0,
- CL_CONTEXT_VA_API_DISPLAY_INTEL,
- (intptr_t)src_hwctx->display,
- CL_CONTEXT_INTEROP_USER_SYNC,
- CL_FALSE,
- 0,
- };
- OpenCLDeviceSelector selector = {
- .platform_index = -1,
- .device_index = -1,
- .context = src_hwctx->display,
- .enumerate_platforms = &opencl_enumerate_platforms,
- .filter_platform = &opencl_filter_intel_media_vaapi_platform,
- .enumerate_devices = &opencl_enumerate_intel_media_vaapi_devices,
- .filter_device = &opencl_filter_intel_media_vaapi_device,
- };
- err = opencl_device_create_internal(hwdev, &selector, props);
- }
- break;
- #endif
- #if HAVE_OPENCL_DXVA2
- case AV_HWDEVICE_TYPE_DXVA2:
- {
- AVDXVA2DeviceContext *src_hwctx = src_ctx->hwctx;
- IDirect3DDevice9 *device;
- HANDLE device_handle;
- HRESULT hr;
- hr = IDirect3DDeviceManager9_OpenDeviceHandle(src_hwctx->devmgr,
- &device_handle);
- if (FAILED(hr)) {
- av_log(hwdev, AV_LOG_ERROR, "Failed to open device handle "
- "for Direct3D9 device: %lx.\n", (unsigned long)hr);
- err = AVERROR_UNKNOWN;
- break;
- }
- hr = IDirect3DDeviceManager9_LockDevice(src_hwctx->devmgr,
- device_handle,
- &device, FALSE);
- if (SUCCEEDED(hr)) {
- cl_context_properties props[5] = {
- CL_CONTEXT_PLATFORM,
- 0,
- CL_CONTEXT_ADAPTER_D3D9EX_KHR,
- (intptr_t)device,
- 0,
- };
- OpenCLDeviceSelector selector = {
- .platform_index = -1,
- .device_index = -1,
- .context = device,
- .enumerate_platforms = &opencl_enumerate_platforms,
- .filter_platform = &opencl_filter_dxva2_platform,
- .enumerate_devices = &opencl_enumerate_dxva2_devices,
- .filter_device = &opencl_filter_gpu_device,
- };
- err = opencl_device_create_internal(hwdev, &selector, props);
- IDirect3DDeviceManager9_UnlockDevice(src_hwctx->devmgr,
- device_handle, FALSE);
- } else {
- av_log(hwdev, AV_LOG_ERROR, "Failed to lock device handle "
- "for Direct3D9 device: %lx.\n", (unsigned long)hr);
- err = AVERROR_UNKNOWN;
- }
- IDirect3DDeviceManager9_CloseDeviceHandle(src_hwctx->devmgr,
- device_handle);
- }
- break;
- #endif
- #if HAVE_OPENCL_D3D11
- case AV_HWDEVICE_TYPE_D3D11VA:
- {
- AVD3D11VADeviceContext *src_hwctx = src_ctx->hwctx;
- cl_context_properties props[5] = {
- CL_CONTEXT_PLATFORM,
- 0,
- CL_CONTEXT_D3D11_DEVICE_KHR,
- (intptr_t)src_hwctx->device,
- 0,
- };
- OpenCLDeviceSelector selector = {
- .platform_index = -1,
- .device_index = -1,
- .context = src_hwctx->device,
- .enumerate_platforms = &opencl_enumerate_platforms,
- .filter_platform = &opencl_filter_d3d11_platform,
- .enumerate_devices = &opencl_enumerate_d3d11_devices,
- .filter_device = &opencl_filter_gpu_device,
- };
- err = opencl_device_create_internal(hwdev, &selector, props);
- }
- break;
- #endif
- #if HAVE_OPENCL_DRM_ARM
- case AV_HWDEVICE_TYPE_DRM:
- {
- OpenCLDeviceSelector selector = {
- .platform_index = -1,
- .device_index = -1,
- .context = NULL,
- .enumerate_platforms = &opencl_enumerate_platforms,
- .filter_platform = &opencl_filter_drm_arm_platform,
- .enumerate_devices = &opencl_enumerate_devices,
- .filter_device = &opencl_filter_drm_arm_device,
- };
- err = opencl_device_create_internal(hwdev, &selector, NULL);
- }
- break;
- #endif
- default:
- err = AVERROR(ENOSYS);
- break;
- }
- return err;
- }
- static int opencl_get_plane_format(enum AVPixelFormat pixfmt,
- int plane, int width, int height,
- cl_image_format *image_format,
- cl_image_desc *image_desc)
- {
- const AVPixFmtDescriptor *desc;
- const AVComponentDescriptor *comp;
- int channels = 0, order = 0, depth = 0, step = 0;
- int wsub, hsub, alpha;
- int c;
- if (plane >= AV_NUM_DATA_POINTERS)
- return AVERROR(ENOENT);
- desc = av_pix_fmt_desc_get(pixfmt);
- // Only normal images are allowed.
- if (desc->flags & (AV_PIX_FMT_FLAG_BITSTREAM |
- AV_PIX_FMT_FLAG_HWACCEL |
- AV_PIX_FMT_FLAG_PAL))
- return AVERROR(EINVAL);
- wsub = 1 << desc->log2_chroma_w;
- hsub = 1 << desc->log2_chroma_h;
- // Subsampled components must be exact.
- if (width & wsub - 1 || height & hsub - 1)
- return AVERROR(EINVAL);
- for (c = 0; c < desc->nb_components; c++) {
- comp = &desc->comp[c];
- if (comp->plane != plane)
- continue;
- // The step size must be a power of two.
- if (comp->step != 1 && comp->step != 2 &&
- comp->step != 4 && comp->step != 8)
- return AVERROR(EINVAL);
- // The bits in each component must be packed in the
- // most-significant-bits of the relevant bytes.
- if (comp->shift + comp->depth != 8 &&
- comp->shift + comp->depth != 16)
- return AVERROR(EINVAL);
- // The depth must not vary between components.
- if (depth && comp->depth != depth)
- return AVERROR(EINVAL);
- // If a single data element crosses multiple bytes then
- // it must match the native endianness.
- if (comp->depth > 8 &&
- HAVE_BIGENDIAN == !(desc->flags & AV_PIX_FMT_FLAG_BE))
- return AVERROR(EINVAL);
- // A single data element must not contain multiple samples
- // from the same component.
- if (step && comp->step != step)
- return AVERROR(EINVAL);
- order = order * 10 + c + 1;
- depth = comp->depth;
- step = comp->step;
- alpha = (desc->flags & AV_PIX_FMT_FLAG_ALPHA &&
- c == desc->nb_components - 1);
- ++channels;
- }
- if (channels == 0)
- return AVERROR(ENOENT);
- memset(image_format, 0, sizeof(*image_format));
- memset(image_desc, 0, sizeof(*image_desc));
- image_desc->image_type = CL_MEM_OBJECT_IMAGE2D;
- if (plane == 0 || alpha) {
- image_desc->image_width = width;
- image_desc->image_height = height;
- image_desc->image_row_pitch = step * width;
- } else {
- image_desc->image_width = width / wsub;
- image_desc->image_height = height / hsub;
- image_desc->image_row_pitch = step * width / wsub;
- }
- if (depth <= 8) {
- image_format->image_channel_data_type = CL_UNORM_INT8;
- } else {
- if (depth <= 16)
- image_format->image_channel_data_type = CL_UNORM_INT16;
- else
- return AVERROR(EINVAL);
- }
- #define CHANNEL_ORDER(order, type) \
- case order: image_format->image_channel_order = type; break;
- switch (order) {
- CHANNEL_ORDER(1, CL_R);
- CHANNEL_ORDER(2, CL_R);
- CHANNEL_ORDER(3, CL_R);
- CHANNEL_ORDER(4, CL_R);
- CHANNEL_ORDER(12, CL_RG);
- CHANNEL_ORDER(23, CL_RG);
- CHANNEL_ORDER(1234, CL_RGBA);
- CHANNEL_ORDER(3214, CL_BGRA);
- CHANNEL_ORDER(4123, CL_ARGB);
- #ifdef CL_ABGR
- CHANNEL_ORDER(4321, CL_ABGR);
- #endif
- default:
- return AVERROR(EINVAL);
- }
- #undef CHANNEL_ORDER
- return 0;
- }
- static int opencl_frames_get_constraints(AVHWDeviceContext *hwdev,
- const void *hwconfig,
- AVHWFramesConstraints *constraints)
- {
- AVOpenCLDeviceContext *hwctx = hwdev->hwctx;
- cl_uint nb_image_formats;
- cl_image_format *image_formats = NULL;
- cl_int cle;
- enum AVPixelFormat pix_fmt;
- int err, pix_fmts_found;
- size_t max_width, max_height;
- cle = clGetDeviceInfo(hwctx->device_id, CL_DEVICE_IMAGE2D_MAX_WIDTH,
- sizeof(max_width), &max_width, NULL);
- if (cle != CL_SUCCESS) {
- av_log(hwdev, AV_LOG_ERROR, "Failed to query maximum "
- "supported image width: %d.\n", cle);
- } else {
- constraints->max_width = max_width;
- }
- cle = clGetDeviceInfo(hwctx->device_id, CL_DEVICE_IMAGE2D_MAX_HEIGHT,
- sizeof(max_height), &max_height, NULL);
- if (cle != CL_SUCCESS) {
- av_log(hwdev, AV_LOG_ERROR, "Failed to query maximum "
- "supported image height: %d.\n", cle);
- } else {
- constraints->max_height = max_height;
- }
- av_log(hwdev, AV_LOG_DEBUG, "Maximum supported image size %dx%d.\n",
- constraints->max_width, constraints->max_height);
- cle = clGetSupportedImageFormats(hwctx->context,
- CL_MEM_READ_WRITE,
- CL_MEM_OBJECT_IMAGE2D,
- 0, NULL, &nb_image_formats);
- if (cle != CL_SUCCESS) {
- av_log(hwdev, AV_LOG_ERROR, "Failed to query supported "
- "image formats: %d.\n", cle);
- err = AVERROR(ENOSYS);
- goto fail;
- }
- if (nb_image_formats == 0) {
- av_log(hwdev, AV_LOG_ERROR, "No image support in OpenCL "
- "driver (zero supported image formats).\n");
- err = AVERROR(ENOSYS);
- goto fail;
- }
- image_formats =
- av_malloc_array(nb_image_formats, sizeof(*image_formats));
- if (!image_formats) {
- err = AVERROR(ENOMEM);
- goto fail;
- }
- cle = clGetSupportedImageFormats(hwctx->context,
- CL_MEM_READ_WRITE,
- CL_MEM_OBJECT_IMAGE2D,
- nb_image_formats,
- image_formats, NULL);
- if (cle != CL_SUCCESS) {
- av_log(hwdev, AV_LOG_ERROR, "Failed to query supported "
- "image formats: %d.\n", cle);
- err = AVERROR(ENOSYS);
- goto fail;
- }
- pix_fmts_found = 0;
- for (pix_fmt = 0; pix_fmt < AV_PIX_FMT_NB; pix_fmt++) {
- cl_image_format image_format;
- cl_image_desc image_desc;
- int plane, i;
- for (plane = 0;; plane++) {
- err = opencl_get_plane_format(pix_fmt, plane, 0, 0,
- &image_format,
- &image_desc);
- if (err < 0)
- break;
- for (i = 0; i < nb_image_formats; i++) {
- if (image_formats[i].image_channel_order ==
- image_format.image_channel_order &&
- image_formats[i].image_channel_data_type ==
- image_format.image_channel_data_type)
- break;
- }
- if (i == nb_image_formats) {
- err = AVERROR(EINVAL);
- break;
- }
- }
- if (err != AVERROR(ENOENT))
- continue;
- av_log(hwdev, AV_LOG_DEBUG, "Format %s supported.\n",
- av_get_pix_fmt_name(pix_fmt));
- err = av_reallocp_array(&constraints->valid_sw_formats,
- pix_fmts_found + 2,
- sizeof(*constraints->valid_sw_formats));
- if (err < 0)
- goto fail;
- constraints->valid_sw_formats[pix_fmts_found] = pix_fmt;
- constraints->valid_sw_formats[pix_fmts_found + 1] =
- AV_PIX_FMT_NONE;
- ++pix_fmts_found;
- }
- av_freep(&image_formats);
- constraints->valid_hw_formats =
- av_malloc_array(2, sizeof(*constraints->valid_hw_formats));
- if (!constraints->valid_hw_formats) {
- err = AVERROR(ENOMEM);
- goto fail;
- }
- constraints->valid_hw_formats[0] = AV_PIX_FMT_OPENCL;
- constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE;
- return 0;
- fail:
- av_freep(&image_formats);
- return err;
- }
- static void opencl_pool_free(void *opaque, uint8_t *data)
- {
- AVHWFramesContext *hwfc = opaque;
- AVOpenCLFrameDescriptor *desc = (AVOpenCLFrameDescriptor*)data;
- cl_int cle;
- int p;
- for (p = 0; p < desc->nb_planes; p++) {
- cle = clReleaseMemObject(desc->planes[p]);
- if (cle != CL_SUCCESS) {
- av_log(hwfc, AV_LOG_ERROR, "Failed to release plane %d: "
- "%d.\n", p, cle);
- }
- }
- av_free(desc);
- }
- static AVBufferRef *opencl_pool_alloc(void *opaque, int size)
- {
- AVHWFramesContext *hwfc = opaque;
- AVOpenCLDeviceContext *hwctx = hwfc->device_ctx->hwctx;
- AVOpenCLFrameDescriptor *desc;
- cl_int cle;
- cl_mem image;
- cl_image_format image_format;
- cl_image_desc image_desc;
- int err, p;
- AVBufferRef *ref;
- desc = av_mallocz(sizeof(*desc));
- if (!desc)
- return NULL;
- for (p = 0;; p++) {
- err = opencl_get_plane_format(hwfc->sw_format, p,
- hwfc->width, hwfc->height,
- &image_format, &image_desc);
- if (err == AVERROR(ENOENT))
- break;
- if (err < 0)
- goto fail;
- // For generic image objects, the pitch is determined by the
- // implementation.
- image_desc.image_row_pitch = 0;
- image = clCreateImage(hwctx->context, CL_MEM_READ_WRITE,
- &image_format, &image_desc, NULL, &cle);
- if (!image) {
- av_log(hwfc, AV_LOG_ERROR, "Failed to create image for "
- "plane %d: %d.\n", p, cle);
- goto fail;
- }
- desc->planes[p] = image;
- }
- desc->nb_planes = p;
- ref = av_buffer_create((uint8_t*)desc, sizeof(*desc),
- &opencl_pool_free, hwfc, 0);
- if (!ref)
- goto fail;
- return ref;
- fail:
- for (p = 0; desc->planes[p]; p++)
- clReleaseMemObject(desc->planes[p]);
- av_free(desc);
- return NULL;
- }
- static int opencl_frames_init_command_queue(AVHWFramesContext *hwfc)
- {
- AVOpenCLFramesContext *hwctx = hwfc->hwctx;
- OpenCLDeviceContext *devpriv = hwfc->device_ctx->internal->priv;
- OpenCLFramesContext *priv = hwfc->internal->priv;
- cl_int cle;
- priv->command_queue = hwctx->command_queue ? hwctx->command_queue
- : devpriv->command_queue;
- cle = clRetainCommandQueue(priv->command_queue);
- if (cle != CL_SUCCESS) {
- av_log(hwfc, AV_LOG_ERROR, "Failed to retain frame "
- "command queue: %d.\n", cle);
- return AVERROR(EIO);
- }
- return 0;
- }
- static int opencl_frames_init(AVHWFramesContext *hwfc)
- {
- if (!hwfc->pool) {
- hwfc->internal->pool_internal =
- av_buffer_pool_init2(sizeof(cl_mem), hwfc,
- &opencl_pool_alloc, NULL);
- if (!hwfc->internal->pool_internal)
- return AVERROR(ENOMEM);
- }
- return opencl_frames_init_command_queue(hwfc);
- }
- static void opencl_frames_uninit(AVHWFramesContext *hwfc)
- {
- OpenCLFramesContext *priv = hwfc->internal->priv;
- cl_int cle;
- #if HAVE_OPENCL_DXVA2 || HAVE_OPENCL_D3D11
- int i, p;
- for (i = 0; i < priv->nb_mapped_frames; i++) {
- AVOpenCLFrameDescriptor *desc = &priv->mapped_frames[i];
- for (p = 0; p < desc->nb_planes; p++) {
- cle = clReleaseMemObject(desc->planes[p]);
- if (cle != CL_SUCCESS) {
- av_log(hwfc, AV_LOG_ERROR, "Failed to release mapped "
- "frame object (frame %d plane %d): %d.\n",
- i, p, cle);
- }
- }
- }
- av_freep(&priv->mapped_frames);
- #endif
- cle = clReleaseCommandQueue(priv->command_queue);
- if (cle != CL_SUCCESS) {
- av_log(hwfc, AV_LOG_ERROR, "Failed to release frame "
- "command queue: %d.\n", cle);
- }
- }
- static int opencl_get_buffer(AVHWFramesContext *hwfc, AVFrame *frame)
- {
- AVOpenCLFrameDescriptor *desc;
- int p;
- frame->buf[0] = av_buffer_pool_get(hwfc->pool);
- if (!frame->buf[0])
- return AVERROR(ENOMEM);
- desc = (AVOpenCLFrameDescriptor*)frame->buf[0]->data;
- for (p = 0; p < desc->nb_planes; p++)
- frame->data[p] = (uint8_t*)desc->planes[p];
- frame->format = AV_PIX_FMT_OPENCL;
- frame->width = hwfc->width;
- frame->height = hwfc->height;
- return 0;
- }
- static int opencl_transfer_get_formats(AVHWFramesContext *hwfc,
- enum AVHWFrameTransferDirection dir,
- enum AVPixelFormat **formats)
- {
- enum AVPixelFormat *fmts;
- fmts = av_malloc_array(2, sizeof(*fmts));
- if (!fmts)
- return AVERROR(ENOMEM);
- fmts[0] = hwfc->sw_format;
- fmts[1] = AV_PIX_FMT_NONE;
- *formats = fmts;
- return 0;
- }
- static int opencl_wait_events(AVHWFramesContext *hwfc,
- cl_event *events, int nb_events)
- {
- cl_int cle;
- int i;
- cle = clWaitForEvents(nb_events, events);
- if (cle != CL_SUCCESS) {
- av_log(hwfc, AV_LOG_ERROR, "Failed to wait for event "
- "completion: %d.\n", cle);
- return AVERROR(EIO);
- }
- for (i = 0; i < nb_events; i++) {
- cle = clReleaseEvent(events[i]);
- if (cle != CL_SUCCESS) {
- av_log(hwfc, AV_LOG_ERROR, "Failed to release "
- "event: %d.\n", cle);
- }
- }
- return 0;
- }
- static int opencl_transfer_data_from(AVHWFramesContext *hwfc,
- AVFrame *dst, const AVFrame *src)
- {
- OpenCLFramesContext *priv = hwfc->internal->priv;
- cl_image_format image_format;
- cl_image_desc image_desc;
- cl_int cle;
- size_t origin[3] = { 0, 0, 0 };
- size_t region[3];
- cl_event events[AV_NUM_DATA_POINTERS];
- int err, p;
- if (dst->format != hwfc->sw_format)
- return AVERROR(EINVAL);
- for (p = 0;; p++) {
- err = opencl_get_plane_format(hwfc->sw_format, p,
- src->width, src->height,
- &image_format, &image_desc);
- if (err < 0) {
- if (err == AVERROR(ENOENT))
- err = 0;
- break;
- }
- if (!dst->data[p]) {
- av_log(hwfc, AV_LOG_ERROR, "Plane %d missing on "
- "destination frame for transfer.\n", p);
- err = AVERROR(EINVAL);
- break;
- }
- region[0] = image_desc.image_width;
- region[1] = image_desc.image_height;
- region[2] = 1;
- cle = clEnqueueReadImage(priv->command_queue,
- (cl_mem)src->data[p],
- CL_FALSE, origin, region,
- dst->linesize[p], 0,
- dst->data[p],
- 0, NULL, &events[p]);
- if (cle != CL_SUCCESS) {
- av_log(hwfc, AV_LOG_ERROR, "Failed to enqueue read of "
- "OpenCL image plane %d: %d.\n", p, cle);
- err = AVERROR(EIO);
- break;
- }
- }
- opencl_wait_events(hwfc, events, p);
- return err;
- }
- static int opencl_transfer_data_to(AVHWFramesContext *hwfc,
- AVFrame *dst, const AVFrame *src)
- {
- OpenCLFramesContext *priv = hwfc->internal->priv;
- cl_image_format image_format;
- cl_image_desc image_desc;
- cl_int cle;
- size_t origin[3] = { 0, 0, 0 };
- size_t region[3];
- cl_event events[AV_NUM_DATA_POINTERS];
- int err, p;
- if (src->format != hwfc->sw_format)
- return AVERROR(EINVAL);
- for (p = 0;; p++) {
- err = opencl_get_plane_format(hwfc->sw_format, p,
- src->width, src->height,
- &image_format, &image_desc);
- if (err < 0) {
- if (err == AVERROR(ENOENT))
- err = 0;
- break;
- }
- if (!src->data[p]) {
- av_log(hwfc, AV_LOG_ERROR, "Plane %d missing on "
- "source frame for transfer.\n", p);
- err = AVERROR(EINVAL);
- break;
- }
- region[0] = image_desc.image_width;
- region[1] = image_desc.image_height;
- region[2] = 1;
- cle = clEnqueueWriteImage(priv->command_queue,
- (cl_mem)dst->data[p],
- CL_FALSE, origin, region,
- src->linesize[p], 0,
- src->data[p],
- 0, NULL, &events[p]);
- if (cle != CL_SUCCESS) {
- av_log(hwfc, AV_LOG_ERROR, "Failed to enqueue write of "
- "OpenCL image plane %d: %d.\n", p, cle);
- err = AVERROR(EIO);
- break;
- }
- }
- opencl_wait_events(hwfc, events, p);
- return err;
- }
- typedef struct OpenCLMapping {
- // The mapped addresses for each plane.
- // The destination frame is not available when we unmap, so these
- // need to be stored separately.
- void *address[AV_NUM_DATA_POINTERS];
- } OpenCLMapping;
- static void opencl_unmap_frame(AVHWFramesContext *hwfc,
- HWMapDescriptor *hwmap)
- {
- OpenCLFramesContext *priv = hwfc->internal->priv;
- OpenCLMapping *map = hwmap->priv;
- cl_event events[AV_NUM_DATA_POINTERS];
- int p, e;
- cl_int cle;
- for (p = e = 0; p < FF_ARRAY_ELEMS(map->address); p++) {
- if (!map->address[p])
- break;
- cle = clEnqueueUnmapMemObject(priv->command_queue,
- (cl_mem)hwmap->source->data[p],
- map->address[p],
- 0, NULL, &events[e]);
- if (cle != CL_SUCCESS) {
- av_log(hwfc, AV_LOG_ERROR, "Failed to unmap OpenCL "
- "image plane %d: %d.\n", p, cle);
- }
- ++e;
- }
- opencl_wait_events(hwfc, events, e);
- av_free(map);
- }
- static int opencl_map_frame(AVHWFramesContext *hwfc, AVFrame *dst,
- const AVFrame *src, int flags)
- {
- OpenCLFramesContext *priv = hwfc->internal->priv;
- cl_map_flags map_flags;
- cl_image_format image_format;
- cl_image_desc image_desc;
- cl_int cle;
- OpenCLMapping *map;
- size_t origin[3] = { 0, 0, 0 };
- size_t region[3];
- size_t row_pitch;
- cl_event events[AV_NUM_DATA_POINTERS];
- int err, p;
- av_assert0(hwfc->sw_format == dst->format);
- if (flags & AV_HWFRAME_MAP_OVERWRITE &&
- !(flags & AV_HWFRAME_MAP_READ)) {
- // This is mutually exclusive with the read/write flags, so
- // there is no way to map with read here.
- map_flags = CL_MAP_WRITE_INVALIDATE_REGION;
- } else {
- map_flags = 0;
- if (flags & AV_HWFRAME_MAP_READ)
- map_flags |= CL_MAP_READ;
- if (flags & AV_HWFRAME_MAP_WRITE)
- map_flags |= CL_MAP_WRITE;
- }
- map = av_mallocz(sizeof(*map));
- if (!map)
- return AVERROR(ENOMEM);
- for (p = 0;; p++) {
- err = opencl_get_plane_format(hwfc->sw_format, p,
- src->width, src->height,
- &image_format, &image_desc);
- if (err == AVERROR(ENOENT))
- break;
- if (err < 0)
- goto fail;
- region[0] = image_desc.image_width;
- region[1] = image_desc.image_height;
- region[2] = 1;
- map->address[p] =
- clEnqueueMapImage(priv->command_queue,
- (cl_mem)src->data[p],
- CL_FALSE, map_flags, origin, region,
- &row_pitch, NULL, 0, NULL,
- &events[p], &cle);
- if (!map->address[p]) {
- av_log(hwfc, AV_LOG_ERROR, "Failed to map OpenCL "
- "image plane %d: %d.\n", p, cle);
- err = AVERROR(EIO);
- goto fail;
- }
- dst->data[p] = map->address[p];
- av_log(hwfc, AV_LOG_DEBUG, "Map plane %d (%p -> %p).\n",
- p, src->data[p], dst->data[p]);
- }
- err = opencl_wait_events(hwfc, events, p);
- if (err < 0)
- goto fail;
- err = ff_hwframe_map_create(src->hw_frames_ctx, dst, src,
- &opencl_unmap_frame, map);
- if (err < 0)
- goto fail;
- dst->width = src->width;
- dst->height = src->height;
- return 0;
- fail:
- for (p = 0; p < AV_NUM_DATA_POINTERS; p++) {
- if (!map->address[p])
- break;
- clEnqueueUnmapMemObject(priv->command_queue,
- (cl_mem)src->data[p],
- map->address[p],
- 0, NULL, &events[p]);
- }
- if (p > 0)
- opencl_wait_events(hwfc, events, p);
- av_freep(&map);
- return err;
- }
- #if HAVE_OPENCL_DRM_BEIGNET
- typedef struct DRMBeignetToOpenCLMapping {
- AVFrame *drm_frame;
- AVDRMFrameDescriptor *drm_desc;
- AVOpenCLFrameDescriptor frame;
- } DRMBeignetToOpenCLMapping;
- static void opencl_unmap_from_drm_beignet(AVHWFramesContext *dst_fc,
- HWMapDescriptor *hwmap)
- {
- DRMBeignetToOpenCLMapping *mapping = hwmap->priv;
- cl_int cle;
- int i;
- for (i = 0; i < mapping->frame.nb_planes; i++) {
- cle = clReleaseMemObject(mapping->frame.planes[i]);
- if (cle != CL_SUCCESS) {
- av_log(dst_fc, AV_LOG_ERROR, "Failed to release CL image "
- "of plane %d of DRM frame: %d.\n", i, cle);
- }
- }
- av_free(mapping);
- }
- static int opencl_map_from_drm_beignet(AVHWFramesContext *dst_fc,
- AVFrame *dst, const AVFrame *src,
- int flags)
- {
- AVOpenCLDeviceContext *hwctx = dst_fc->device_ctx->hwctx;
- OpenCLDeviceContext *priv = dst_fc->device_ctx->internal->priv;
- DRMBeignetToOpenCLMapping *mapping;
- const AVDRMFrameDescriptor *desc;
- cl_int cle;
- int err, i, j, p;
- desc = (const AVDRMFrameDescriptor*)src->data[0];
- mapping = av_mallocz(sizeof(*mapping));
- if (!mapping)
- return AVERROR(ENOMEM);
- p = 0;
- for (i = 0; i < desc->nb_layers; i++) {
- const AVDRMLayerDescriptor *layer = &desc->layers[i];
- for (j = 0; j < layer->nb_planes; j++) {
- const AVDRMPlaneDescriptor *plane = &layer->planes[j];
- const AVDRMObjectDescriptor *object =
- &desc->objects[plane->object_index];
- cl_import_image_info_intel image_info = {
- .fd = object->fd,
- .size = object->size,
- .type = CL_MEM_OBJECT_IMAGE2D,
- .offset = plane->offset,
- .row_pitch = plane->pitch,
- };
- cl_image_desc image_desc;
- err = opencl_get_plane_format(dst_fc->sw_format, p,
- src->width, src->height,
- &image_info.fmt,
- &image_desc);
- if (err < 0) {
- av_log(dst_fc, AV_LOG_ERROR, "DRM frame layer %d "
- "plane %d is not representable in OpenCL: %d.\n",
- i, j, err);
- goto fail;
- }
- image_info.width = image_desc.image_width;
- image_info.height = image_desc.image_height;
- mapping->frame.planes[p] =
- priv->clCreateImageFromFdINTEL(hwctx->context,
- &image_info, &cle);
- if (!mapping->frame.planes[p]) {
- av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL image "
- "from layer %d plane %d of DRM frame: %d.\n",
- i, j, cle);
- err = AVERROR(EIO);
- goto fail;
- }
- dst->data[p] = (uint8_t*)mapping->frame.planes[p];
- mapping->frame.nb_planes = ++p;
- }
- }
- err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src,
- &opencl_unmap_from_drm_beignet,
- mapping);
- if (err < 0)
- goto fail;
- dst->width = src->width;
- dst->height = src->height;
- return 0;
- fail:
- for (p = 0; p < mapping->frame.nb_planes; p++) {
- if (mapping->frame.planes[p])
- clReleaseMemObject(mapping->frame.planes[p]);
- }
- av_free(mapping);
- return err;
- }
- #if HAVE_OPENCL_VAAPI_BEIGNET
- static int opencl_map_from_vaapi(AVHWFramesContext *dst_fc,
- AVFrame *dst, const AVFrame *src,
- int flags)
- {
- AVFrame *tmp;
- int err;
- tmp = av_frame_alloc();
- if (!tmp)
- return AVERROR(ENOMEM);
- tmp->format = AV_PIX_FMT_DRM_PRIME;
- err = av_hwframe_map(tmp, src, flags);
- if (err < 0)
- goto fail;
- err = opencl_map_from_drm_beignet(dst_fc, dst, tmp, flags);
- if (err < 0)
- goto fail;
- err = ff_hwframe_map_replace(dst, src);
- fail:
- av_frame_free(&tmp);
- return err;
- }
- #endif /* HAVE_OPENCL_VAAPI_BEIGNET */
- #endif /* HAVE_OPENCL_DRM_BEIGNET */
- static inline cl_mem_flags opencl_mem_flags_for_mapping(int map_flags)
- {
- if ((map_flags & AV_HWFRAME_MAP_READ) &&
- (map_flags & AV_HWFRAME_MAP_WRITE))
- return CL_MEM_READ_WRITE;
- else if (map_flags & AV_HWFRAME_MAP_READ)
- return CL_MEM_READ_ONLY;
- else if (map_flags & AV_HWFRAME_MAP_WRITE)
- return CL_MEM_WRITE_ONLY;
- else
- return 0;
- }
- #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
- static void opencl_unmap_from_qsv(AVHWFramesContext *dst_fc,
- HWMapDescriptor *hwmap)
- {
- AVOpenCLFrameDescriptor *desc = hwmap->priv;
- OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv;
- OpenCLFramesContext *frames_priv = dst_fc->internal->priv;
- cl_event event;
- cl_int cle;
- int p;
- av_log(dst_fc, AV_LOG_DEBUG, "Unmap QSV/VAAPI surface from OpenCL.\n");
- cle = device_priv->clEnqueueReleaseVA_APIMediaSurfacesINTEL(
- frames_priv->command_queue, desc->nb_planes, desc->planes,
- 0, NULL, &event);
- if (cle != CL_SUCCESS) {
- av_log(dst_fc, AV_LOG_ERROR, "Failed to release surface "
- "handles: %d.\n", cle);
- }
- opencl_wait_events(dst_fc, &event, 1);
- for (p = 0; p < desc->nb_planes; p++) {
- cle = clReleaseMemObject(desc->planes[p]);
- if (cle != CL_SUCCESS) {
- av_log(dst_fc, AV_LOG_ERROR, "Failed to release CL "
- "image of plane %d of QSV/VAAPI surface: %d\n",
- p, cle);
- }
- }
- av_free(desc);
- }
- static int opencl_map_from_qsv(AVHWFramesContext *dst_fc, AVFrame *dst,
- const AVFrame *src, int flags)
- {
- AVHWFramesContext *src_fc =
- (AVHWFramesContext*)src->hw_frames_ctx->data;
- AVOpenCLDeviceContext *dst_dev = dst_fc->device_ctx->hwctx;
- OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv;
- OpenCLFramesContext *frames_priv = dst_fc->internal->priv;
- AVOpenCLFrameDescriptor *desc;
- VASurfaceID va_surface;
- cl_mem_flags cl_flags;
- cl_event event;
- cl_int cle;
- int err, p;
- #if CONFIG_LIBMFX
- if (src->format == AV_PIX_FMT_QSV) {
- mfxFrameSurface1 *mfx_surface = (mfxFrameSurface1*)src->data[3];
- va_surface = *(VASurfaceID*)mfx_surface->Data.MemId;
- } else
- #endif
- if (src->format == AV_PIX_FMT_VAAPI) {
- va_surface = (VASurfaceID)(uintptr_t)src->data[3];
- } else {
- return AVERROR(ENOSYS);
- }
- cl_flags = opencl_mem_flags_for_mapping(flags);
- if (!cl_flags)
- return AVERROR(EINVAL);
- av_log(src_fc, AV_LOG_DEBUG, "Map QSV/VAAPI surface %#x to "
- "OpenCL.\n", va_surface);
- desc = av_mallocz(sizeof(*desc));
- if (!desc)
- return AVERROR(ENOMEM);
- // The cl_intel_va_api_media_sharing extension only supports NV12
- // surfaces, so for now there are always exactly two planes.
- desc->nb_planes = 2;
- for (p = 0; p < desc->nb_planes; p++) {
- desc->planes[p] =
- device_priv->clCreateFromVA_APIMediaSurfaceINTEL(
- dst_dev->context, cl_flags, &va_surface, p, &cle);
- if (!desc->planes[p]) {
- av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL "
- "image from plane %d of QSV/VAAPI surface "
- "%#x: %d.\n", p, va_surface, cle);
- err = AVERROR(EIO);
- goto fail;
- }
- dst->data[p] = (uint8_t*)desc->planes[p];
- }
- cle = device_priv->clEnqueueAcquireVA_APIMediaSurfacesINTEL(
- frames_priv->command_queue, desc->nb_planes, desc->planes,
- 0, NULL, &event);
- if (cle != CL_SUCCESS) {
- av_log(dst_fc, AV_LOG_ERROR, "Failed to acquire surface "
- "handles: %d.\n", cle);
- err = AVERROR(EIO);
- goto fail;
- }
- err = opencl_wait_events(dst_fc, &event, 1);
- if (err < 0)
- goto fail;
- err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src,
- &opencl_unmap_from_qsv, desc);
- if (err < 0)
- goto fail;
- dst->width = src->width;
- dst->height = src->height;
- return 0;
- fail:
- for (p = 0; p < desc->nb_planes; p++)
- if (desc->planes[p])
- clReleaseMemObject(desc->planes[p]);
- av_freep(&desc);
- return err;
- }
- #endif
- #if HAVE_OPENCL_DXVA2
- static void opencl_unmap_from_dxva2(AVHWFramesContext *dst_fc,
- HWMapDescriptor *hwmap)
- {
- AVOpenCLFrameDescriptor *desc = hwmap->priv;
- OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv;
- OpenCLFramesContext *frames_priv = dst_fc->device_ctx->internal->priv;
- cl_event event;
- cl_int cle;
- av_log(dst_fc, AV_LOG_DEBUG, "Unmap DXVA2 surface from OpenCL.\n");
- cle = device_priv->clEnqueueReleaseDX9MediaSurfacesKHR(
- frames_priv->command_queue, desc->nb_planes, desc->planes,
- 0, NULL, &event);
- if (cle != CL_SUCCESS) {
- av_log(dst_fc, AV_LOG_ERROR, "Failed to release surface "
- "handle: %d.\n", cle);
- return;
- }
- opencl_wait_events(dst_fc, &event, 1);
- }
- static int opencl_map_from_dxva2(AVHWFramesContext *dst_fc, AVFrame *dst,
- const AVFrame *src, int flags)
- {
- AVHWFramesContext *src_fc =
- (AVHWFramesContext*)src->hw_frames_ctx->data;
- AVDXVA2FramesContext *src_hwctx = src_fc->hwctx;
- OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv;
- OpenCLFramesContext *frames_priv = dst_fc->internal->priv;
- AVOpenCLFrameDescriptor *desc;
- cl_event event;
- cl_int cle;
- int err, i;
- av_log(dst_fc, AV_LOG_DEBUG, "Map DXVA2 surface %p to "
- "OpenCL.\n", src->data[3]);
- for (i = 0; i < src_hwctx->nb_surfaces; i++) {
- if (src_hwctx->surfaces[i] == (IDirect3DSurface9*)src->data[3])
- break;
- }
- if (i >= src_hwctx->nb_surfaces) {
- av_log(dst_fc, AV_LOG_ERROR, "Trying to map from a surface which "
- "is not in the mapped frames context.\n");
- return AVERROR(EINVAL);
- }
- desc = &frames_priv->mapped_frames[i];
- cle = device_priv->clEnqueueAcquireDX9MediaSurfacesKHR(
- frames_priv->command_queue, desc->nb_planes, desc->planes,
- 0, NULL, &event);
- if (cle != CL_SUCCESS) {
- av_log(dst_fc, AV_LOG_ERROR, "Failed to acquire surface "
- "handle: %d.\n", cle);
- return AVERROR(EIO);
- }
- err = opencl_wait_events(dst_fc, &event, 1);
- if (err < 0)
- goto fail;
- for (i = 0; i < desc->nb_planes; i++)
- dst->data[i] = (uint8_t*)desc->planes[i];
- err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src,
- &opencl_unmap_from_dxva2, desc);
- if (err < 0)
- goto fail;
- dst->width = src->width;
- dst->height = src->height;
- return 0;
- fail:
- cle = device_priv->clEnqueueReleaseDX9MediaSurfacesKHR(
- frames_priv->command_queue, desc->nb_planes, desc->planes,
- 0, NULL, &event);
- if (cle == CL_SUCCESS)
- opencl_wait_events(dst_fc, &event, 1);
- return err;
- }
- static int opencl_frames_derive_from_dxva2(AVHWFramesContext *dst_fc,
- AVHWFramesContext *src_fc, int flags)
- {
- AVOpenCLDeviceContext *dst_dev = dst_fc->device_ctx->hwctx;
- AVDXVA2FramesContext *src_hwctx = src_fc->hwctx;
- OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv;
- OpenCLFramesContext *frames_priv = dst_fc->internal->priv;
- cl_mem_flags cl_flags;
- cl_int cle;
- int err, i, p, nb_planes;
- if (src_fc->sw_format != AV_PIX_FMT_NV12) {
- av_log(dst_fc, AV_LOG_ERROR, "Only NV12 textures are supported "
- "for DXVA2 to OpenCL mapping.\n");
- return AVERROR(EINVAL);
- }
- nb_planes = 2;
- if (src_fc->initial_pool_size == 0) {
- av_log(dst_fc, AV_LOG_ERROR, "Only fixed-size pools are supported "
- "for DXVA2 to OpenCL mapping.\n");
- return AVERROR(EINVAL);
- }
- cl_flags = opencl_mem_flags_for_mapping(flags);
- if (!cl_flags)
- return AVERROR(EINVAL);
- frames_priv->nb_mapped_frames = src_hwctx->nb_surfaces;
- frames_priv->mapped_frames =
- av_mallocz_array(frames_priv->nb_mapped_frames,
- sizeof(*frames_priv->mapped_frames));
- if (!frames_priv->mapped_frames)
- return AVERROR(ENOMEM);
- for (i = 0; i < frames_priv->nb_mapped_frames; i++) {
- AVOpenCLFrameDescriptor *desc = &frames_priv->mapped_frames[i];
- cl_dx9_surface_info_khr surface_info = {
- .resource = src_hwctx->surfaces[i],
- .shared_handle = NULL,
- };
- desc->nb_planes = nb_planes;
- for (p = 0; p < nb_planes; p++) {
- desc->planes[p] =
- device_priv->clCreateFromDX9MediaSurfaceKHR(
- dst_dev->context, cl_flags,
- device_priv->dx9_media_adapter_type,
- &surface_info, p, &cle);
- if (!desc->planes[p]) {
- av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL "
- "image from plane %d of DXVA2 surface %d: %d.\n",
- p, i, cle);
- err = AVERROR(EIO);
- goto fail;
- }
- }
- }
- return 0;
- fail:
- for (i = 0; i < frames_priv->nb_mapped_frames; i++) {
- AVOpenCLFrameDescriptor *desc = &frames_priv->mapped_frames[i];
- for (p = 0; p < desc->nb_planes; p++) {
- if (desc->planes[p])
- clReleaseMemObject(desc->planes[p]);
- }
- }
- av_freep(&frames_priv->mapped_frames);
- frames_priv->nb_mapped_frames = 0;
- return err;
- }
- #endif
- #if HAVE_OPENCL_D3D11
- static void opencl_unmap_from_d3d11(AVHWFramesContext *dst_fc,
- HWMapDescriptor *hwmap)
- {
- AVOpenCLFrameDescriptor *desc = hwmap->priv;
- OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv;
- OpenCLFramesContext *frames_priv = dst_fc->device_ctx->internal->priv;
- cl_event event;
- cl_int cle;
- cle = device_priv->clEnqueueReleaseD3D11ObjectsKHR(
- frames_priv->command_queue, desc->nb_planes, desc->planes,
- 0, NULL, &event);
- if (cle != CL_SUCCESS) {
- av_log(dst_fc, AV_LOG_ERROR, "Failed to release surface "
- "handle: %d.\n", cle);
- }
- opencl_wait_events(dst_fc, &event, 1);
- }
- static int opencl_map_from_d3d11(AVHWFramesContext *dst_fc, AVFrame *dst,
- const AVFrame *src, int flags)
- {
- OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv;
- OpenCLFramesContext *frames_priv = dst_fc->internal->priv;
- AVOpenCLFrameDescriptor *desc;
- cl_event event;
- cl_int cle;
- int err, index, i;
- index = (intptr_t)src->data[1];
- if (index >= frames_priv->nb_mapped_frames) {
- av_log(dst_fc, AV_LOG_ERROR, "Texture array index out of range for "
- "mapping: %d >= %d.\n", index, frames_priv->nb_mapped_frames);
- return AVERROR(EINVAL);
- }
- av_log(dst_fc, AV_LOG_DEBUG, "Map D3D11 texture %d to OpenCL.\n",
- index);
- desc = &frames_priv->mapped_frames[index];
- cle = device_priv->clEnqueueAcquireD3D11ObjectsKHR(
- frames_priv->command_queue, desc->nb_planes, desc->planes,
- 0, NULL, &event);
- if (cle != CL_SUCCESS) {
- av_log(dst_fc, AV_LOG_ERROR, "Failed to acquire surface "
- "handle: %d.\n", cle);
- return AVERROR(EIO);
- }
- err = opencl_wait_events(dst_fc, &event, 1);
- if (err < 0)
- goto fail;
- for (i = 0; i < desc->nb_planes; i++)
- dst->data[i] = (uint8_t*)desc->planes[i];
- err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src,
- &opencl_unmap_from_d3d11, desc);
- if (err < 0)
- goto fail;
- dst->width = src->width;
- dst->height = src->height;
- return 0;
- fail:
- cle = device_priv->clEnqueueReleaseD3D11ObjectsKHR(
- frames_priv->command_queue, desc->nb_planes, desc->planes,
- 0, NULL, &event);
- if (cle == CL_SUCCESS)
- opencl_wait_events(dst_fc, &event, 1);
- return err;
- }
- static int opencl_frames_derive_from_d3d11(AVHWFramesContext *dst_fc,
- AVHWFramesContext *src_fc, int flags)
- {
- AVOpenCLDeviceContext *dst_dev = dst_fc->device_ctx->hwctx;
- AVD3D11VAFramesContext *src_hwctx = src_fc->hwctx;
- OpenCLDeviceContext *device_priv = dst_fc->device_ctx->internal->priv;
- OpenCLFramesContext *frames_priv = dst_fc->internal->priv;
- cl_mem_flags cl_flags;
- cl_int cle;
- int err, i, p, nb_planes;
- if (src_fc->sw_format != AV_PIX_FMT_NV12) {
- av_log(dst_fc, AV_LOG_ERROR, "Only NV12 textures are supported "
- "for D3D11 to OpenCL mapping.\n");
- return AVERROR(EINVAL);
- }
- nb_planes = 2;
- if (src_fc->initial_pool_size == 0) {
- av_log(dst_fc, AV_LOG_ERROR, "Only fixed-size pools are supported "
- "for D3D11 to OpenCL mapping.\n");
- return AVERROR(EINVAL);
- }
- cl_flags = opencl_mem_flags_for_mapping(flags);
- if (!cl_flags)
- return AVERROR(EINVAL);
- frames_priv->nb_mapped_frames = src_fc->initial_pool_size;
- frames_priv->mapped_frames =
- av_mallocz_array(frames_priv->nb_mapped_frames,
- sizeof(*frames_priv->mapped_frames));
- if (!frames_priv->mapped_frames)
- return AVERROR(ENOMEM);
- for (i = 0; i < frames_priv->nb_mapped_frames; i++) {
- AVOpenCLFrameDescriptor *desc = &frames_priv->mapped_frames[i];
- desc->nb_planes = nb_planes;
- for (p = 0; p < nb_planes; p++) {
- UINT subresource = 2 * i + p;
- desc->planes[p] =
- device_priv->clCreateFromD3D11Texture2DKHR(
- dst_dev->context, cl_flags, src_hwctx->texture,
- subresource, &cle);
- if (!desc->planes[p]) {
- av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL "
- "image from plane %d of D3D texture "
- "index %d (subresource %u): %d.\n",
- p, i, (unsigned int)subresource, cle);
- err = AVERROR(EIO);
- goto fail;
- }
- }
- }
- return 0;
- fail:
- for (i = 0; i < frames_priv->nb_mapped_frames; i++) {
- AVOpenCLFrameDescriptor *desc = &frames_priv->mapped_frames[i];
- for (p = 0; p < desc->nb_planes; p++) {
- if (desc->planes[p])
- clReleaseMemObject(desc->planes[p]);
- }
- }
- av_freep(&frames_priv->mapped_frames);
- frames_priv->nb_mapped_frames = 0;
- return err;
- }
- #endif
- #if HAVE_OPENCL_DRM_ARM
- typedef struct DRMARMtoOpenCLMapping {
- int nb_objects;
- cl_mem object_buffers[AV_DRM_MAX_PLANES];
- int nb_planes;
- cl_mem plane_images[AV_DRM_MAX_PLANES];
- } DRMARMtoOpenCLMapping;
- static void opencl_unmap_from_drm_arm(AVHWFramesContext *dst_fc,
- HWMapDescriptor *hwmap)
- {
- DRMARMtoOpenCLMapping *mapping = hwmap->priv;
- int i;
- for (i = 0; i < mapping->nb_planes; i++)
- clReleaseMemObject(mapping->plane_images[i]);
- for (i = 0; i < mapping->nb_objects; i++)
- clReleaseMemObject(mapping->object_buffers[i]);
- av_free(mapping);
- }
- static int opencl_map_from_drm_arm(AVHWFramesContext *dst_fc, AVFrame *dst,
- const AVFrame *src, int flags)
- {
- AVHWFramesContext *src_fc =
- (AVHWFramesContext*)src->hw_frames_ctx->data;
- AVOpenCLDeviceContext *dst_dev = dst_fc->device_ctx->hwctx;
- const AVDRMFrameDescriptor *desc;
- DRMARMtoOpenCLMapping *mapping = NULL;
- cl_mem_flags cl_flags;
- const cl_import_properties_arm props[3] = {
- CL_IMPORT_TYPE_ARM, CL_IMPORT_TYPE_DMA_BUF_ARM, 0,
- };
- cl_int cle;
- int err, i, j;
- desc = (const AVDRMFrameDescriptor*)src->data[0];
- cl_flags = opencl_mem_flags_for_mapping(flags);
- if (!cl_flags)
- return AVERROR(EINVAL);
- mapping = av_mallocz(sizeof(*mapping));
- if (!mapping)
- return AVERROR(ENOMEM);
- mapping->nb_objects = desc->nb_objects;
- for (i = 0; i < desc->nb_objects; i++) {
- int fd = desc->objects[i].fd;
- av_log(dst_fc, AV_LOG_DEBUG, "Map DRM PRIME fd %d to OpenCL.\n", fd);
- if (desc->objects[i].format_modifier) {
- av_log(dst_fc, AV_LOG_DEBUG, "Warning: object %d fd %d has "
- "nonzero format modifier %"PRId64", result may not "
- "be as expected.\n", i, fd,
- desc->objects[i].format_modifier);
- }
- mapping->object_buffers[i] =
- clImportMemoryARM(dst_dev->context, cl_flags, props,
- &fd, desc->objects[i].size, &cle);
- if (!mapping->object_buffers[i]) {
- av_log(dst_fc, AV_LOG_ERROR, "Failed to create CL buffer "
- "from object %d (fd %d, size %"SIZE_SPECIFIER") of DRM frame: %d.\n",
- i, fd, desc->objects[i].size, cle);
- err = AVERROR(EIO);
- goto fail;
- }
- }
- mapping->nb_planes = 0;
- for (i = 0; i < desc->nb_layers; i++) {
- const AVDRMLayerDescriptor *layer = &desc->layers[i];
- for (j = 0; j < layer->nb_planes; j++) {
- const AVDRMPlaneDescriptor *plane = &layer->planes[j];
- cl_mem plane_buffer;
- cl_image_format image_format;
- cl_image_desc image_desc;
- cl_buffer_region region;
- int p = mapping->nb_planes;
- err = opencl_get_plane_format(src_fc->sw_format, p,
- src_fc->width, src_fc->height,
- &image_format, &image_desc);
- if (err < 0) {
- av_log(dst_fc, AV_LOG_ERROR, "Invalid plane %d (DRM "
- "layer %d plane %d): %d.\n", p, i, j, err);
- goto fail;
- }
- region.origin = plane->offset;
- region.size = image_desc.image_row_pitch *
- image_desc.image_height;
- plane_buffer =
- clCreateSubBuffer(mapping->object_buffers[plane->object_index],
- cl_flags,
- CL_BUFFER_CREATE_TYPE_REGION,
- ®ion, &cle);
- if (!plane_buffer) {
- av_log(dst_fc, AV_LOG_ERROR, "Failed to create sub-buffer "
- "for plane %d: %d.\n", p, cle);
- err = AVERROR(EIO);
- goto fail;
- }
- image_desc.buffer = plane_buffer;
- mapping->plane_images[p] =
- clCreateImage(dst_dev->context, cl_flags,
- &image_format, &image_desc, NULL, &cle);
- // Unreference the sub-buffer immediately - we don't need it
- // directly and a reference is held by the image.
- clReleaseMemObject(plane_buffer);
- if (!mapping->plane_images[p]) {
- av_log(dst_fc, AV_LOG_ERROR, "Failed to create image "
- "for plane %d: %d.\n", p, cle);
- err = AVERROR(EIO);
- goto fail;
- }
- ++mapping->nb_planes;
- }
- }
- for (i = 0; i < mapping->nb_planes; i++)
- dst->data[i] = (uint8_t*)mapping->plane_images[i];
- err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src,
- &opencl_unmap_from_drm_arm, mapping);
- if (err < 0)
- goto fail;
- dst->width = src->width;
- dst->height = src->height;
- return 0;
- fail:
- for (i = 0; i < mapping->nb_planes; i++) {
- clReleaseMemObject(mapping->plane_images[i]);
- }
- for (i = 0; i < mapping->nb_objects; i++) {
- if (mapping->object_buffers[i])
- clReleaseMemObject(mapping->object_buffers[i]);
- }
- av_free(mapping);
- return err;
- }
- #endif
- static int opencl_map_from(AVHWFramesContext *hwfc, AVFrame *dst,
- const AVFrame *src, int flags)
- {
- av_assert0(src->format == AV_PIX_FMT_OPENCL);
- if (hwfc->sw_format != dst->format)
- return AVERROR(ENOSYS);
- return opencl_map_frame(hwfc, dst, src, flags);
- }
- static int opencl_map_to(AVHWFramesContext *hwfc, AVFrame *dst,
- const AVFrame *src, int flags)
- {
- av_unused OpenCLDeviceContext *priv = hwfc->device_ctx->internal->priv;
- av_assert0(dst->format == AV_PIX_FMT_OPENCL);
- switch (src->format) {
- #if HAVE_OPENCL_DRM_BEIGNET
- case AV_PIX_FMT_DRM_PRIME:
- if (priv->beignet_drm_mapping_usable)
- return opencl_map_from_drm_beignet(hwfc, dst, src, flags);
- #endif
- #if HAVE_OPENCL_VAAPI_BEIGNET
- case AV_PIX_FMT_VAAPI:
- if (priv->beignet_drm_mapping_usable)
- return opencl_map_from_vaapi(hwfc, dst, src, flags);
- #endif
- #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
- case AV_PIX_FMT_QSV:
- case AV_PIX_FMT_VAAPI:
- if (priv->qsv_mapping_usable)
- return opencl_map_from_qsv(hwfc, dst, src, flags);
- #endif
- #if HAVE_OPENCL_DXVA2
- case AV_PIX_FMT_DXVA2_VLD:
- if (priv->dxva2_mapping_usable)
- return opencl_map_from_dxva2(hwfc, dst, src, flags);
- #endif
- #if HAVE_OPENCL_D3D11
- case AV_PIX_FMT_D3D11:
- if (priv->d3d11_mapping_usable)
- return opencl_map_from_d3d11(hwfc, dst, src, flags);
- #endif
- #if HAVE_OPENCL_DRM_ARM
- case AV_PIX_FMT_DRM_PRIME:
- if (priv->drm_arm_mapping_usable)
- return opencl_map_from_drm_arm(hwfc, dst, src, flags);
- #endif
- }
- return AVERROR(ENOSYS);
- }
- static int opencl_frames_derive_to(AVHWFramesContext *dst_fc,
- AVHWFramesContext *src_fc, int flags)
- {
- av_unused OpenCLDeviceContext *priv = dst_fc->device_ctx->internal->priv;
- switch (src_fc->device_ctx->type) {
- #if HAVE_OPENCL_DRM_BEIGNET
- case AV_HWDEVICE_TYPE_DRM:
- if (!priv->beignet_drm_mapping_usable)
- return AVERROR(ENOSYS);
- break;
- #endif
- #if HAVE_OPENCL_VAAPI_BEIGNET
- case AV_HWDEVICE_TYPE_VAAPI:
- if (!priv->beignet_drm_mapping_usable)
- return AVERROR(ENOSYS);
- break;
- #endif
- #if HAVE_OPENCL_VAAPI_INTEL_MEDIA
- case AV_HWDEVICE_TYPE_QSV:
- case AV_HWDEVICE_TYPE_VAAPI:
- if (!priv->qsv_mapping_usable)
- return AVERROR(ENOSYS);
- break;
- #endif
- #if HAVE_OPENCL_DXVA2
- case AV_HWDEVICE_TYPE_DXVA2:
- if (!priv->dxva2_mapping_usable)
- return AVERROR(ENOSYS);
- {
- int err;
- err = opencl_frames_derive_from_dxva2(dst_fc, src_fc, flags);
- if (err < 0)
- return err;
- }
- break;
- #endif
- #if HAVE_OPENCL_D3D11
- case AV_HWDEVICE_TYPE_D3D11VA:
- if (!priv->d3d11_mapping_usable)
- return AVERROR(ENOSYS);
- {
- int err;
- err = opencl_frames_derive_from_d3d11(dst_fc, src_fc, flags);
- if (err < 0)
- return err;
- }
- break;
- #endif
- #if HAVE_OPENCL_DRM_ARM
- case AV_HWDEVICE_TYPE_DRM:
- if (!priv->drm_arm_mapping_usable)
- return AVERROR(ENOSYS);
- break;
- #endif
- default:
- return AVERROR(ENOSYS);
- }
- return opencl_frames_init_command_queue(dst_fc);
- }
- const HWContextType ff_hwcontext_type_opencl = {
- .type = AV_HWDEVICE_TYPE_OPENCL,
- .name = "OpenCL",
- .device_hwctx_size = sizeof(AVOpenCLDeviceContext),
- .device_priv_size = sizeof(OpenCLDeviceContext),
- .frames_hwctx_size = sizeof(AVOpenCLFramesContext),
- .frames_priv_size = sizeof(OpenCLFramesContext),
- .device_create = &opencl_device_create,
- .device_derive = &opencl_device_derive,
- .device_init = &opencl_device_init,
- .device_uninit = &opencl_device_uninit,
- .frames_get_constraints = &opencl_frames_get_constraints,
- .frames_init = &opencl_frames_init,
- .frames_uninit = &opencl_frames_uninit,
- .frames_get_buffer = &opencl_get_buffer,
- .transfer_get_formats = &opencl_transfer_get_formats,
- .transfer_data_to = &opencl_transfer_data_to,
- .transfer_data_from = &opencl_transfer_data_from,
- .map_from = &opencl_map_from,
- .map_to = &opencl_map_to,
- .frames_derive_to = &opencl_frames_derive_to,
- .pix_fmts = (const enum AVPixelFormat[]) {
- AV_PIX_FMT_OPENCL,
- AV_PIX_FMT_NONE
- },
- };
|