149 lines
4.4 KiB
C++
149 lines
4.4 KiB
C++
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "VALibWrapper.h"
|
|
|
|
#include "FFmpegLog.h"
|
|
#include "PlatformDecoderModule.h"
|
|
#include "prlink.h"
|
|
#include "mozilla/gfx/gfxVars.h"
|
|
#include "mozilla/widget/DMABufDevice.h"
|
|
|
|
namespace mozilla {
|
|
|
|
VALibWrapper VALibWrapper::sFuncs;
|
|
static int (*vaInitialize)(void* dpy, int* major_version, int* minor_version);
|
|
static int (*vaTerminate)(void* dpy);
|
|
static void* (*vaGetDisplayDRM)(int fd);
|
|
|
|
static VADisplayHolder* sDisplayHolder;
|
|
static StaticMutex sDisplayHolderMutex;
|
|
|
|
void VALibWrapper::Link() {
|
|
#define VA_FUNC_OPTION_SILENT(func) \
|
|
if (!((func) = (decltype(func))PR_FindSymbol(mVALib, #func))) { \
|
|
(func) = (decltype(func))nullptr; \
|
|
}
|
|
|
|
// mVALib is optional and may not be present.
|
|
if (mVALib) {
|
|
VA_FUNC_OPTION_SILENT(vaExportSurfaceHandle)
|
|
VA_FUNC_OPTION_SILENT(vaSyncSurface)
|
|
VA_FUNC_OPTION_SILENT(vaInitialize)
|
|
VA_FUNC_OPTION_SILENT(vaTerminate)
|
|
}
|
|
#undef VA_FUNC_OPTION_SILENT
|
|
|
|
#define VAD_FUNC_OPTION_SILENT(func) \
|
|
if (!((func) = (decltype(func))PR_FindSymbol(mVALibDrm, #func))) { \
|
|
FFMPEGP_LOG("Couldn't load function " #func); \
|
|
}
|
|
|
|
// mVALibDrm is optional and may not be present.
|
|
if (mVALibDrm) {
|
|
VAD_FUNC_OPTION_SILENT(vaGetDisplayDRM)
|
|
}
|
|
#undef VAD_FUNC_OPTION_SILENT
|
|
}
|
|
|
|
bool VALibWrapper::LinkVAAPILibs() {
|
|
if (!gfx::gfxVars::CanUseHardwareVideoDecoding() || !XRE_IsRDDProcess()) {
|
|
return false;
|
|
}
|
|
|
|
PRLibSpec lspec;
|
|
lspec.type = PR_LibSpec_Pathname;
|
|
const char* libDrm = "libva-drm.so.2";
|
|
lspec.value.pathname = libDrm;
|
|
mVALibDrm = PR_LoadLibraryWithFlags(lspec, PR_LD_NOW | PR_LD_LOCAL);
|
|
if (!mVALibDrm) {
|
|
FFMPEGP_LOG("VA-API support: Missing or old %s library.\n", libDrm);
|
|
return false;
|
|
}
|
|
|
|
const char* lib = "libva.so.2";
|
|
lspec.value.pathname = lib;
|
|
mVALib = PR_LoadLibraryWithFlags(lspec, PR_LD_NOW | PR_LD_LOCAL);
|
|
// Don't use libva when it's missing vaExportSurfaceHandle.
|
|
if (mVALib && !PR_FindSymbol(mVALib, "vaExportSurfaceHandle")) {
|
|
PR_UnloadLibrary(mVALib);
|
|
mVALib = nullptr;
|
|
}
|
|
if (!mVALib) {
|
|
FFMPEGP_LOG("VA-API support: Missing or old %s library.\n", lib);
|
|
return false;
|
|
}
|
|
|
|
Link();
|
|
return true;
|
|
}
|
|
|
|
bool VALibWrapper::AreVAAPIFuncsAvailable() {
|
|
#define VA_FUNC_LOADED(func) ((func) != nullptr)
|
|
return VA_FUNC_LOADED(vaExportSurfaceHandle) &&
|
|
VA_FUNC_LOADED(vaSyncSurface) && VA_FUNC_LOADED(vaInitialize) &&
|
|
VA_FUNC_LOADED(vaTerminate) && VA_FUNC_LOADED(vaGetDisplayDRM);
|
|
}
|
|
|
|
/* static */
|
|
bool VALibWrapper::IsVAAPIAvailable() {
|
|
static bool once = sFuncs.LinkVAAPILibs();
|
|
(void)once;
|
|
|
|
return sFuncs.AreVAAPIFuncsAvailable();
|
|
}
|
|
|
|
VADisplayHolder::VADisplayHolder(UniqueVADisplay aDisplay,
|
|
UniqueFileHandle aDRMFd)
|
|
: mDRMFd(std::move(aDRMFd)), mDisplay(std::move(aDisplay)) {};
|
|
|
|
VADisplayHolder::~VADisplayHolder() = default;
|
|
|
|
/* static */
|
|
RefPtr<VADisplayHolder> VADisplayHolder::GetSingleton() {
|
|
StaticMutexAutoLock lock(sDisplayHolderMutex);
|
|
|
|
if (sDisplayHolder) {
|
|
return RefPtr{sDisplayHolder};
|
|
}
|
|
|
|
UniqueFileHandle drmFd{widget::GetDMABufDevice()->OpenDRMFd()};
|
|
UniqueVADisplay display{vaGetDisplayDRM(drmFd.get())};
|
|
if (!display) {
|
|
FFMPEGP_LOG(" Can't get DRM VA-API display.");
|
|
return nullptr;
|
|
}
|
|
|
|
int major, minor;
|
|
VAStatus status = vaInitialize(display.get(), &major, &minor);
|
|
if (status != VA_STATUS_SUCCESS) {
|
|
FFMPEGP_LOG(" vaInitialize failed.");
|
|
// |display| is destroyed while sDisplayHolderMutex is still held, to
|
|
// vaTerminate() before another VADisplay might be accessed.
|
|
// See Bug 1850615.
|
|
return nullptr;
|
|
}
|
|
|
|
RefPtr displayHolder =
|
|
new VADisplayHolder(std::move(display), std::move(drmFd));
|
|
sDisplayHolder = displayHolder;
|
|
|
|
return displayHolder;
|
|
}
|
|
|
|
void VADisplayHolder::MaybeDestroy() {
|
|
StaticMutexAutoLock lock(sDisplayHolderMutex);
|
|
MOZ_ASSERT(int32_t(mRefCnt) >= 0, "dup release");
|
|
if (mRefCnt == 0) {
|
|
// No new reference added before the lock was taken.
|
|
sDisplayHolder = nullptr;
|
|
delete this;
|
|
}
|
|
}
|
|
|
|
void VADisplayHolder::VADisplayDeleter::operator()(VADisplay aDisplay) {
|
|
vaTerminate(aDisplay);
|
|
}
|
|
|
|
} // namespace mozilla
|