Bug 1850615 Share the same VADisplay across all FFmpegVideoDecoders a=pascalc

Rebased from https://hg.mozilla.org/mozilla-central/rev/9d547b90a407
with https://hg.mozilla.org/mozilla-central/rev/47d823d94067

Differential Revision: https://phabricator.services.mozilla.com/D241145
This commit is contained in:
Karl Tomlinson 2025-03-13 11:07:02 +00:00
parent c7ed87060f
commit 493943a59b
3 changed files with 85 additions and 47 deletions

View file

@ -25,7 +25,6 @@
# include "H264.h"
# include "mozilla/gfx/gfxVars.h"
# include "mozilla/layers/DMABUFSurfaceImage.h"
# include "mozilla/widget/DMABufLibWrapper.h"
# include "FFmpegVideoFramePool.h"
# include "va/va.h"
#endif
@ -66,13 +65,6 @@
# include "mozilla/gfx/gfxVars.h"
#endif
// Forward declare from va.h
#ifdef MOZ_USE_HWDECODE
typedef int VAStatus;
# define VA_EXPORT_SURFACE_READ_ONLY 0x0001
# define VA_EXPORT_SURFACE_SEPARATE_LAYERS 0x0004
# define VA_STATUS_SUCCESS 0x00000000
#endif
// Use some extra HW frames for potential rendering lags.
#define EXTRA_HW_FRAMES 6
@ -205,31 +197,9 @@ AVCodec* FFmpegVideoDecoder<LIBAV_VER>::FindVAAPICodec() {
return nullptr;
}
template <int V>
class VAAPIDisplayHolder {};
template <>
class VAAPIDisplayHolder<LIBAV_VER>;
template <>
class VAAPIDisplayHolder<LIBAV_VER> {
public:
VAAPIDisplayHolder(VADisplay aDisplay, int aDRMFd)
: mDisplay(aDisplay), mDRMFd(aDRMFd) {};
~VAAPIDisplayHolder() {
VALibWrapper::sFuncs.vaTerminate(mDisplay);
close(mDRMFd);
}
private:
VADisplay mDisplay;
int mDRMFd;
};
static void VAAPIDisplayReleaseCallback(struct AVHWDeviceContext* hwctx) {
auto displayHolder =
static_cast<VAAPIDisplayHolder<LIBAV_VER>*>(hwctx->user_opaque);
delete displayHolder;
auto displayHolder = static_cast<VADisplayHolder*>(hwctx->user_opaque);
displayHolder->Release();
}
bool FFmpegVideoDecoder<LIBAV_VER>::CreateVAAPIDeviceContext() {
@ -245,23 +215,15 @@ bool FFmpegVideoDecoder<LIBAV_VER>::CreateVAAPIDeviceContext() {
AVHWDeviceContext* hwctx = (AVHWDeviceContext*)mVAAPIDeviceContext->data;
AVVAAPIDeviceContext* vactx = (AVVAAPIDeviceContext*)hwctx->hwctx;
int drmFd = widget::GetDMABufDevice()->OpenDRMFd();
mDisplay = VALibWrapper::sFuncs.vaGetDisplayDRM(drmFd);
if (!mDisplay) {
FFMPEG_LOG(" Can't get DRM VA-API display.");
RefPtr displayHolder = VADisplayHolder::GetSingleton();
if (!displayHolder) {
return false;
}
hwctx->user_opaque = new VAAPIDisplayHolder<LIBAV_VER>(mDisplay, drmFd);
mDisplay = displayHolder->mDisplay;
hwctx->user_opaque = displayHolder.forget().take();
hwctx->free = VAAPIDisplayReleaseCallback;
int major, minor;
int status = VALibWrapper::sFuncs.vaInitialize(mDisplay, &major, &minor);
if (status != VA_STATUS_SUCCESS) {
FFMPEG_LOG(" vaInitialize failed.");
return false;
}
vactx->display = mDisplay;
if (mLib->av_hwdevice_ctx_init(mVAAPIDeviceContext) < 0) {
FFMPEG_LOG(" av_hwdevice_ctx_init failed.");

View file

@ -8,10 +8,17 @@
#include "PlatformDecoderModule.h"
#include "prlink.h"
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/widget/DMABufLibWrapper.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) \
@ -87,4 +94,48 @@ bool VALibWrapper::IsVAAPIAvailable() {
return sFuncs.AreVAAPIFuncsAvailable();
}
/* static */
RefPtr<VADisplayHolder> VADisplayHolder::GetSingleton() {
StaticMutexAutoLock lock(sDisplayHolderMutex);
if (sDisplayHolder) {
return RefPtr{sDisplayHolder};
}
int drmFd = widget::GetDMABufDevice()->OpenDRMFd();
VADisplay display = vaGetDisplayDRM(drmFd);
if (!display) {
FFMPEGP_LOG(" Can't get DRM VA-API display.");
return nullptr;
}
RefPtr displayHolder = new VADisplayHolder(display, drmFd);
int major, minor;
VAStatus status = vaInitialize(display, &major, &minor);
if (status != VA_STATUS_SUCCESS) {
FFMPEGP_LOG(" vaInitialize failed.");
return nullptr;
}
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;
}
}
VADisplayHolder::~VADisplayHolder() {
vaTerminate(mDisplay);
close(mDRMFd);
}
} // namespace mozilla

View file

@ -7,10 +7,19 @@
#include "mozilla/Attributes.h"
#include "mozilla/Types.h"
#include "nsISupportsImpl.h"
struct PRLibrary;
#ifdef MOZ_WIDGET_GTK
// Forward declare from va.h
typedef void* VADisplay;
typedef int VAStatus;
# define VA_EXPORT_SURFACE_READ_ONLY 0x0001
# define VA_EXPORT_SURFACE_SEPARATE_LAYERS 0x0004
# define VA_STATUS_SUCCESS 0x00000000
namespace mozilla {
class MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS VALibWrapper {
@ -39,15 +48,31 @@ class MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS VALibWrapper {
public:
int (*vaExportSurfaceHandle)(void*, unsigned int, uint32_t, uint32_t, void*);
int (*vaSyncSurface)(void*, unsigned int);
int (*vaInitialize)(void* dpy, int* major_version, int* minor_version);
int (*vaTerminate)(void* dpy);
void* (*vaGetDisplayDRM)(int fd);
private:
PRLibrary* mVALib;
PRLibrary* mVALibDrm;
};
class VADisplayHolder {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_DESTROY(VADisplayHolder,
MaybeDestroy())
static RefPtr<VADisplayHolder> GetSingleton();
const VADisplay mDisplay;
private:
VADisplayHolder(VADisplay aDisplay, int aDRMFd)
: mDisplay(aDisplay), mDRMFd(aDRMFd) {};
~VADisplayHolder();
void MaybeDestroy();
const int mDRMFd;
};
} // namespace mozilla
#endif // MOZ_WIDGET_GTK