tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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