VALibWrapper.cpp (4489B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #include "VALibWrapper.h" 6 7 #include "FFmpegLog.h" 8 #include "PlatformDecoderModule.h" 9 #include "mozilla/gfx/gfxVars.h" 10 #include "mozilla/widget/DMABufDevice.h" 11 #include "prlink.h" 12 13 namespace mozilla { 14 15 VALibWrapper VALibWrapper::sFuncs; 16 static int (*vaInitialize)(void* dpy, int* major_version, int* minor_version); 17 static int (*vaTerminate)(void* dpy); 18 static void* (*vaGetDisplayDRM)(int fd); 19 20 static VADisplayHolder* sDisplayHolder; 21 static StaticMutex sDisplayHolderMutex; 22 23 void VALibWrapper::Link() { 24 #define VA_FUNC_OPTION_SILENT(func) \ 25 if (!((func) = (decltype(func))PR_FindSymbol(mVALib, #func))) { \ 26 (func) = (decltype(func))nullptr; \ 27 } 28 29 // mVALib is optional and may not be present. 30 if (mVALib) { 31 VA_FUNC_OPTION_SILENT(vaExportSurfaceHandle) 32 VA_FUNC_OPTION_SILENT(vaSyncSurface) 33 VA_FUNC_OPTION_SILENT(vaInitialize) 34 VA_FUNC_OPTION_SILENT(vaTerminate) 35 } 36 #undef VA_FUNC_OPTION_SILENT 37 38 #define VAD_FUNC_OPTION_SILENT(func) \ 39 if (!((func) = (decltype(func))PR_FindSymbol(mVALibDrm, #func))) { \ 40 FFMPEGP_LOG("Couldn't load function " #func); \ 41 } 42 43 // mVALibDrm is optional and may not be present. 44 if (mVALibDrm) { 45 VAD_FUNC_OPTION_SILENT(vaGetDisplayDRM) 46 } 47 #undef VAD_FUNC_OPTION_SILENT 48 } 49 50 bool VALibWrapper::LinkVAAPILibs() { 51 if (!gfx::gfxVars::CanUseHardwareVideoDecoding() || !XRE_IsRDDProcess()) { 52 return false; 53 } 54 55 PRLibSpec lspec; 56 lspec.type = PR_LibSpec_Pathname; 57 const char* libDrm = "libva-drm.so.2"; 58 lspec.value.pathname = libDrm; 59 mVALibDrm = PR_LoadLibraryWithFlags(lspec, PR_LD_NOW | PR_LD_LOCAL); 60 if (!mVALibDrm) { 61 FFMPEGP_LOG("VA-API support: Missing or old %s library.\n", libDrm); 62 return false; 63 } 64 65 const char* lib = "libva.so.2"; 66 lspec.value.pathname = lib; 67 mVALib = PR_LoadLibraryWithFlags(lspec, PR_LD_NOW | PR_LD_LOCAL); 68 // Don't use libva when it's missing vaExportSurfaceHandle. 69 if (mVALib && !PR_FindSymbol(mVALib, "vaExportSurfaceHandle")) { 70 PR_UnloadLibrary(mVALib); 71 mVALib = nullptr; 72 } 73 if (!mVALib) { 74 FFMPEGP_LOG("VA-API support: Missing or old %s library.\n", lib); 75 return false; 76 } 77 78 Link(); 79 return true; 80 } 81 82 bool VALibWrapper::AreVAAPIFuncsAvailable() { 83 #define VA_FUNC_LOADED(func) ((func) != nullptr) 84 return VA_FUNC_LOADED(vaExportSurfaceHandle) && 85 VA_FUNC_LOADED(vaSyncSurface) && VA_FUNC_LOADED(vaInitialize) && 86 VA_FUNC_LOADED(vaTerminate) && VA_FUNC_LOADED(vaGetDisplayDRM); 87 } 88 89 /* static */ 90 bool VALibWrapper::IsVAAPIAvailable() { 91 static bool once = sFuncs.LinkVAAPILibs(); 92 (void)once; 93 94 return sFuncs.AreVAAPIFuncsAvailable(); 95 } 96 97 VADisplayHolder::VADisplayHolder(UniqueVADisplay aDisplay, 98 UniqueFileHandle aDRMFd) 99 : mDRMFd(std::move(aDRMFd)), mDisplay(std::move(aDisplay)) {}; 100 101 VADisplayHolder::~VADisplayHolder() = default; 102 103 /* static */ 104 RefPtr<VADisplayHolder> VADisplayHolder::GetSingleton() { 105 StaticMutexAutoLock lock(sDisplayHolderMutex); 106 107 if (sDisplayHolder) { 108 return RefPtr{sDisplayHolder}; 109 } 110 111 widget::DMABufDeviceLock device; 112 UniqueFileHandle drmFd{device.GetDMABufDevice()->OpenDRMFd()}; 113 UniqueVADisplay display{vaGetDisplayDRM(drmFd.get())}; 114 if (!display) { 115 FFMPEGP_LOG(" Can't get DRM VA-API display."); 116 return nullptr; 117 } 118 119 int major, minor; 120 VAStatus status = vaInitialize(display.get(), &major, &minor); 121 if (status != VA_STATUS_SUCCESS) { 122 FFMPEGP_LOG(" vaInitialize failed."); 123 // |display| is destroyed while sDisplayHolderMutex is still held, to 124 // vaTerminate() before another VADisplay might be accessed. 125 // See Bug 1850615. 126 return nullptr; 127 } 128 129 RefPtr displayHolder = 130 new VADisplayHolder(std::move(display), std::move(drmFd)); 131 sDisplayHolder = displayHolder; 132 133 return displayHolder; 134 } 135 136 void VADisplayHolder::MaybeDestroy() { 137 StaticMutexAutoLock lock(sDisplayHolderMutex); 138 MOZ_ASSERT(int32_t(mRefCnt) >= 0, "dup release"); 139 if (mRefCnt == 0) { 140 // No new reference added before the lock was taken. 141 sDisplayHolder = nullptr; 142 delete this; 143 } 144 } 145 146 void VADisplayHolder::VADisplayDeleter::operator()(VADisplay aDisplay) { 147 vaTerminate(aDisplay); 148 } 149 150 } // namespace mozilla