299 lines
11 KiB
Diff
299 lines
11 KiB
Diff
|
diff --git a/dom/media/platforms/ffmpeg/FFmpegLibWrapper.h b/dom/media/platforms/ffmpeg/FFmpegLibWrapper.h
|
||
|
--- a/dom/media/platforms/ffmpeg/FFmpegLibWrapper.h
|
||
|
+++ b/dom/media/platforms/ffmpeg/FFmpegLibWrapper.h
|
||
|
@@ -116,9 +116,9 @@
|
||
|
#ifdef MOZ_WAYLAND
|
||
|
const AVCodecHWConfig* (*avcodec_get_hw_config)(const AVCodec* codec,
|
||
|
int index);
|
||
|
- int (*av_hwdevice_ctx_create)(AVBufferRef** device_ctx, int type,
|
||
|
- const char* device, AVDictionary* opts,
|
||
|
- int flags);
|
||
|
+ AVBufferRef* (*av_hwdevice_ctx_alloc)(int);
|
||
|
+ int (*av_hwdevice_ctx_init)(AVBufferRef* ref);
|
||
|
+
|
||
|
AVBufferRef* (*av_buffer_ref)(AVBufferRef* buf);
|
||
|
void (*av_buffer_unref)(AVBufferRef** buf);
|
||
|
int (*av_hwframe_transfer_get_formats)(AVBufferRef* hwframe_ctx, int dir,
|
||
|
@@ -132,12 +132,16 @@
|
||
|
|
||
|
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* (*vaGetDisplayWl)(struct wl_display* display);
|
||
|
#endif
|
||
|
|
||
|
PRLibrary* mAVCodecLib;
|
||
|
PRLibrary* mAVUtilLib;
|
||
|
#ifdef MOZ_WAYLAND
|
||
|
PRLibrary* mVALib;
|
||
|
+ PRLibrary* mVALibWayland;
|
||
|
#endif
|
||
|
|
||
|
private:
|
||
|
diff --git a/dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp b/dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp
|
||
|
--- a/dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp
|
||
|
+++ b/dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp
|
||
|
@@ -159,7 +159,8 @@
|
||
|
AV_FUNC_OPTION(av_frame_get_color_range, AV_FUNC_AVUTIL_ALL)
|
||
|
#ifdef MOZ_WAYLAND
|
||
|
AV_FUNC_OPTION_SILENT(avcodec_get_hw_config, AV_FUNC_58)
|
||
|
- AV_FUNC_OPTION_SILENT(av_hwdevice_ctx_create, AV_FUNC_58)
|
||
|
+ AV_FUNC_OPTION_SILENT(av_hwdevice_ctx_init, AV_FUNC_58)
|
||
|
+ AV_FUNC_OPTION_SILENT(av_hwdevice_ctx_alloc, AV_FUNC_58)
|
||
|
AV_FUNC_OPTION_SILENT(av_buffer_ref, AV_FUNC_AVUTIL_58)
|
||
|
AV_FUNC_OPTION_SILENT(av_buffer_unref, AV_FUNC_AVUTIL_58)
|
||
|
AV_FUNC_OPTION_SILENT(av_hwframe_transfer_get_formats, AV_FUNC_58)
|
||
|
@@ -181,8 +182,21 @@
|
||
|
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
|
||
|
+# undef VA_FUNC_OPTION_SILENT
|
||
|
+
|
||
|
+# define VAW_FUNC_OPTION_SILENT(func) \
|
||
|
+ if (!(func = (decltype(func))PR_FindSymbol(mVALibWayland, #func))) { \
|
||
|
+ FFMPEG_LOG("Couldn't load function " #func); \
|
||
|
+ }
|
||
|
+
|
||
|
+ // mVALibWayland is optional and may not be present.
|
||
|
+ if (mVALibWayland) {
|
||
|
+ VAW_FUNC_OPTION_SILENT(vaGetDisplayWl)
|
||
|
+ }
|
||
|
+# undef VAW_FUNC_OPTION_SILENT
|
||
|
#endif
|
||
|
|
||
|
avcodec_register_all();
|
||
|
@@ -218,6 +232,9 @@
|
||
|
if (mVALib) {
|
||
|
PR_UnloadLibrary(mVALib);
|
||
|
}
|
||
|
+ if (mVALibWayland) {
|
||
|
+ PR_UnloadLibrary(mVALibWayland);
|
||
|
+ }
|
||
|
#endif
|
||
|
PodZero(this);
|
||
|
}
|
||
|
@@ -226,13 +243,16 @@
|
||
|
bool FFmpegLibWrapper::IsVAAPIAvailable() {
|
||
|
# define VA_FUNC_LOADED(func) (func != nullptr)
|
||
|
return VA_FUNC_LOADED(avcodec_get_hw_config) &&
|
||
|
- VA_FUNC_LOADED(av_hwdevice_ctx_create) &&
|
||
|
+ VA_FUNC_LOADED(av_hwdevice_ctx_alloc) &&
|
||
|
+ VA_FUNC_LOADED(av_hwdevice_ctx_init) &&
|
||
|
VA_FUNC_LOADED(av_buffer_ref) && VA_FUNC_LOADED(av_buffer_unref) &&
|
||
|
VA_FUNC_LOADED(av_hwframe_transfer_get_formats) &&
|
||
|
VA_FUNC_LOADED(av_hwdevice_ctx_create_derived) &&
|
||
|
VA_FUNC_LOADED(av_hwframe_ctx_alloc) && VA_FUNC_LOADED(av_dict_set) &&
|
||
|
VA_FUNC_LOADED(av_dict_free) &&
|
||
|
- VA_FUNC_LOADED(vaExportSurfaceHandle) && VA_FUNC_LOADED(vaSyncSurface);
|
||
|
+ VA_FUNC_LOADED(vaExportSurfaceHandle) &&
|
||
|
+ VA_FUNC_LOADED(vaSyncSurface) && VA_FUNC_LOADED(vaInitialize) &&
|
||
|
+ VA_FUNC_LOADED(vaTerminate) && VA_FUNC_LOADED(vaGetDisplayWl);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
diff --git a/dom/media/platforms/ffmpeg/FFmpegRuntimeLinker.cpp b/dom/media/platforms/ffmpeg/FFmpegRuntimeLinker.cpp
|
||
|
--- a/dom/media/platforms/ffmpeg/FFmpegRuntimeLinker.cpp
|
||
|
+++ b/dom/media/platforms/ffmpeg/FFmpegRuntimeLinker.cpp
|
||
|
@@ -9,6 +9,9 @@
|
||
|
#include "mozilla/ArrayUtils.h"
|
||
|
#include "FFmpegLog.h"
|
||
|
#include "prlink.h"
|
||
|
+#ifdef MOZ_WAYLAND
|
||
|
+# include "gfxPlatformGtk.h"
|
||
|
+#endif
|
||
|
|
||
|
namespace mozilla {
|
||
|
|
||
|
@@ -54,21 +57,33 @@
|
||
|
}
|
||
|
|
||
|
#ifdef MOZ_WAYLAND
|
||
|
- {
|
||
|
- const char* lib = "libva.so.2";
|
||
|
+ if (gfxPlatformGtk::GetPlatform()->UseWaylandHardwareVideoDecoding()) {
|
||
|
+ const char* libWayland = "libva-wayland.so.2";
|
||
|
PRLibSpec lspec;
|
||
|
lspec.type = PR_LibSpec_Pathname;
|
||
|
- lspec.value.pathname = lib;
|
||
|
- sLibAV.mVALib = PR_LoadLibraryWithFlags(lspec, PR_LD_NOW | PR_LD_LOCAL);
|
||
|
- // Don't use libva when it's missing vaExportSurfaceHandle.
|
||
|
- if (sLibAV.mVALib &&
|
||
|
- !PR_FindSymbol(sLibAV.mVALib, "vaExportSurfaceHandle")) {
|
||
|
- PR_UnloadLibrary(sLibAV.mVALib);
|
||
|
- sLibAV.mVALib = nullptr;
|
||
|
+ lspec.value.pathname = libWayland;
|
||
|
+ sLibAV.mVALibWayland =
|
||
|
+ PR_LoadLibraryWithFlags(lspec, PR_LD_NOW | PR_LD_LOCAL);
|
||
|
+ if (!sLibAV.mVALibWayland) {
|
||
|
+ FFMPEG_LOG("VA-API support: Missing or old %s library.\n", libWayland);
|
||
|
}
|
||
|
- if (!sLibAV.mVALib) {
|
||
|
- FFMPEG_LOG("VA-API support: Missing or old %s library.\n", lib);
|
||
|
+
|
||
|
+ if (sLibAV.mVALibWayland) {
|
||
|
+ const char* lib = "libva.so.2";
|
||
|
+ lspec.value.pathname = lib;
|
||
|
+ sLibAV.mVALib = PR_LoadLibraryWithFlags(lspec, PR_LD_NOW | PR_LD_LOCAL);
|
||
|
+ // Don't use libva when it's missing vaExportSurfaceHandle.
|
||
|
+ if (sLibAV.mVALib &&
|
||
|
+ !PR_FindSymbol(sLibAV.mVALib, "vaExportSurfaceHandle")) {
|
||
|
+ PR_UnloadLibrary(sLibAV.mVALib);
|
||
|
+ sLibAV.mVALib = nullptr;
|
||
|
+ }
|
||
|
+ if (!sLibAV.mVALib) {
|
||
|
+ FFMPEG_LOG("VA-API support: Missing or old %s library.\n", lib);
|
||
|
+ }
|
||
|
}
|
||
|
+ } else {
|
||
|
+ FFMPEG_LOG("VA-API FFmpeg is disabled by platform");
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h
|
||
|
--- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h
|
||
|
+++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h
|
||
|
@@ -111,6 +111,7 @@
|
||
|
#ifdef MOZ_WAYLAND_USE_VAAPI
|
||
|
AVBufferRef* mVAAPIDeviceContext;
|
||
|
const bool mDisableHardwareDecoding;
|
||
|
+ VADisplay mDisplay;
|
||
|
#endif
|
||
|
RefPtr<KnowsCompositor> mImageAllocator;
|
||
|
RefPtr<ImageContainer> mImageContainer;
|
||
|
diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp
|
||
|
--- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp
|
||
|
+++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp
|
||
|
@@ -154,14 +154,44 @@
|
||
|
return nullptr;
|
||
|
}
|
||
|
|
||
|
+class VAAPIDisplayHolder {
|
||
|
+ public:
|
||
|
+ VAAPIDisplayHolder(FFmpegLibWrapper* aLib, VADisplay aDisplay)
|
||
|
+ : mLib(aLib), mDisplay(aDisplay){};
|
||
|
+ ~VAAPIDisplayHolder() { mLib->vaTerminate(mDisplay); }
|
||
|
+
|
||
|
+ private:
|
||
|
+ FFmpegLibWrapper* mLib;
|
||
|
+ VADisplay mDisplay;
|
||
|
+};
|
||
|
+
|
||
|
+static void VAAPIDisplayReleaseCallback(struct AVHWDeviceContext* hwctx) {
|
||
|
+ auto displayHolder = static_cast<VAAPIDisplayHolder*>(hwctx->user_opaque);
|
||
|
+ delete displayHolder;
|
||
|
+}
|
||
|
+
|
||
|
bool FFmpegVideoDecoder<LIBAV_VER>::CreateVAAPIDeviceContext() {
|
||
|
- AVDictionary* opts = nullptr;
|
||
|
- mLib->av_dict_set(&opts, "connection_type", "drm", 0);
|
||
|
- bool ret =
|
||
|
- (mLib->av_hwdevice_ctx_create(
|
||
|
- &mVAAPIDeviceContext, AV_HWDEVICE_TYPE_VAAPI, NULL, NULL, 0) == 0);
|
||
|
- mLib->av_dict_free(&opts);
|
||
|
- if (!ret) {
|
||
|
+ mVAAPIDeviceContext = mLib->av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_VAAPI);
|
||
|
+ if (!mVAAPIDeviceContext) {
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+ AVHWDeviceContext* hwctx = (AVHWDeviceContext*)mVAAPIDeviceContext->data;
|
||
|
+ AVVAAPIDeviceContext* vactx = (AVVAAPIDeviceContext*)hwctx->hwctx;
|
||
|
+
|
||
|
+ mDisplay = mLib->vaGetDisplayWl(widget::WaylandDisplayGet()->GetDisplay());
|
||
|
+
|
||
|
+ hwctx->user_opaque = new VAAPIDisplayHolder(mLib, mDisplay);
|
||
|
+ hwctx->free = VAAPIDisplayReleaseCallback;
|
||
|
+
|
||
|
+ int major, minor;
|
||
|
+ int status = mLib->vaInitialize(mDisplay, &major, &minor);
|
||
|
+ if (status != VA_STATUS_SUCCESS) {
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+
|
||
|
+ vactx->display = mDisplay;
|
||
|
+
|
||
|
+ if (mLib->av_hwdevice_ctx_init(mVAAPIDeviceContext) < 0) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
@@ -172,6 +202,11 @@
|
||
|
MediaResult FFmpegVideoDecoder<LIBAV_VER>::InitVAAPIDecoder() {
|
||
|
FFMPEG_LOG("Initialising VA-API FFmpeg decoder");
|
||
|
|
||
|
+ if (!mLib->IsVAAPIAvailable()) {
|
||
|
+ FFMPEG_LOG("libva library or symbols are missing.");
|
||
|
+ return NS_ERROR_NOT_AVAILABLE;
|
||
|
+ }
|
||
|
+
|
||
|
auto layersBackend = mImageAllocator
|
||
|
? mImageAllocator->GetCompositorBackendType()
|
||
|
: layers::LayersBackend::LAYERS_BASIC;
|
||
|
@@ -181,16 +216,6 @@
|
||
|
return NS_ERROR_NOT_AVAILABLE;
|
||
|
}
|
||
|
|
||
|
- if (!mLib->IsVAAPIAvailable()) {
|
||
|
- FFMPEG_LOG("libva library or symbols are missing.");
|
||
|
- return NS_ERROR_NOT_AVAILABLE;
|
||
|
- }
|
||
|
-
|
||
|
- if (!gfxPlatformGtk::GetPlatform()->UseWaylandHardwareVideoDecoding()) {
|
||
|
- FFMPEG_LOG("VA-API FFmpeg is disabled by platform");
|
||
|
- return NS_ERROR_NOT_AVAILABLE;
|
||
|
- }
|
||
|
-
|
||
|
AVCodec* codec = FindVAAPICodec();
|
||
|
if (!codec) {
|
||
|
FFMPEG_LOG("Couldn't find ffmpeg VA-API decoder");
|
||
|
@@ -275,6 +300,7 @@
|
||
|
#ifdef MOZ_WAYLAND_USE_VAAPI
|
||
|
mVAAPIDeviceContext(nullptr),
|
||
|
mDisableHardwareDecoding(aDisableHardwareDecoding),
|
||
|
+ mDisplay(nullptr),
|
||
|
#endif
|
||
|
mImageAllocator(aAllocator),
|
||
|
mImageContainer(aImageContainer),
|
||
|
@@ -606,16 +632,10 @@
|
||
|
" duration=%" PRId64 " opaque=%" PRId64,
|
||
|
aPts, mFrame->pkt_dts, aDuration, mCodecContext->reordered_opaque);
|
||
|
|
||
|
- AVHWDeviceContext* device_ctx = (AVHWDeviceContext*)mVAAPIDeviceContext->data;
|
||
|
- AVVAAPIDeviceContext* VAAPIDeviceContext =
|
||
|
- (AVVAAPIDeviceContext*)device_ctx->hwctx;
|
||
|
VADRMPRIMESurfaceDescriptor va_desc;
|
||
|
-
|
||
|
VASurfaceID surface_id = (VASurfaceID)(uintptr_t)mFrame->data[3];
|
||
|
-
|
||
|
VAStatus vas = mLib->vaExportSurfaceHandle(
|
||
|
- VAAPIDeviceContext->display, surface_id,
|
||
|
- VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
|
||
|
+ mDisplay, surface_id, VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
|
||
|
VA_EXPORT_SURFACE_READ_ONLY | VA_EXPORT_SURFACE_SEPARATE_LAYERS,
|
||
|
&va_desc);
|
||
|
if (vas != VA_STATUS_SUCCESS) {
|
||
|
@@ -623,7 +643,7 @@
|
||
|
NS_ERROR_OUT_OF_MEMORY,
|
||
|
RESULT_DETAIL("Unable to get frame by vaExportSurfaceHandle()"));
|
||
|
}
|
||
|
- vas = mLib->vaSyncSurface(VAAPIDeviceContext->display, surface_id);
|
||
|
+ vas = mLib->vaSyncSurface(mDisplay, surface_id);
|
||
|
if (vas != VA_STATUS_SUCCESS) {
|
||
|
NS_WARNING("vaSyncSurface() failed.");
|
||
|
}
|
||
|
diff --git a/dom/media/platforms/ffmpeg/moz.build b/dom/media/platforms/ffmpeg/moz.build
|
||
|
--- a/dom/media/platforms/ffmpeg/moz.build
|
||
|
+++ b/dom/media/platforms/ffmpeg/moz.build
|
||
|
@@ -20,4 +20,7 @@
|
||
|
'FFmpegRuntimeLinker.cpp',
|
||
|
]
|
||
|
|
||
|
+if CONFIG['MOZ_WAYLAND']:
|
||
|
+ include('/ipc/chromium/chromium-config.mozbuild')
|
||
|
+
|
||
|
FINAL_LIBRARY = 'xul'
|
||
|
|