From 284830e5ef2e6fb1ccb83f24bcd3b17fe6375227 Mon Sep 17 00:00:00 2001 From: Cameron Kaiser Date: Fri, 15 Mar 2019 23:20:18 -0700 Subject: [PATCH] Olga's basic libav framework (#550) --- .../platforms/ffmpeg/FFmpegRuntimeLinker.cpp | 54 +++++++++++++++++++ .../platforms/ffmpeg/FFmpegRuntimeLinker.h | 4 ++ 2 files changed, 58 insertions(+) diff --git a/dom/media/platforms/ffmpeg/FFmpegRuntimeLinker.cpp b/dom/media/platforms/ffmpeg/FFmpegRuntimeLinker.cpp index f38c35a1c..0f442b5b5 100644 --- a/dom/media/platforms/ffmpeg/FFmpegRuntimeLinker.cpp +++ b/dom/media/platforms/ffmpeg/FFmpegRuntimeLinker.cpp @@ -10,6 +10,12 @@ #include "mozilla/Preferences.h" #include "prlink.h" +#ifdef XP_DARWIN + #include + #include + #include +#endif /* XP_DARWIN */ + namespace mozilla { @@ -40,7 +46,11 @@ static const char* sLibs[] = { #endif }; +#ifdef XP_DARWIN +void* FFmpegRuntimeLinker::sLinkedLib = nullptr; +#else PRLibrary* FFmpegRuntimeLinker::sLinkedLib = nullptr; +#endif /* XP_DARWIN */ const char* FFmpegRuntimeLinker::sLib = nullptr; static unsigned (*avcodec_version)() = nullptr; @@ -60,12 +70,36 @@ FFmpegRuntimeLinker::Link() MOZ_ASSERT(NS_IsMainThread()); +#ifdef XP_DARWIN // Explanation below. + char execPath[PATH_MAX]; + execPath[0] = '\0'; + uint32_t pathlen = PATH_MAX; + _NSGetExecutablePath(execPath, &pathlen); + char *execDir = dirname(execPath); +#endif /* XP_DARWIN */ + for (size_t i = 0; i < ArrayLength(sLibs); i++) { const char* lib = sLibs[i]; +#ifdef XP_DARWIN + /* Loading FFMPEG on Mac OS X (macOS is a typo) fails because mozilla + searches for sybols defined in libavutil with a handle to libavcodec. + This is due to the fact that NSPR uses NSAddressOfSymbol & cie who limits + its researches only to libavcodec and not its dependencies. We don't have + this issue with dlsym(). */ + if (!(sLinkedLib = dlopen(lib, RTLD_NOW | RTLD_LOCAL))) { + /* Bonus time: if we don't find libavcodec in standard locations, we look + if our venerable FFMPEG's libraries are in the same folder as XUL. */ + char *libFullPath = NULL; + if (asprintf(&libFullPath, "%s/%s", execDir, lib) > 0 && libFullPath) + sLinkedLib = dlopen(libFullPath, RTLD_NOW | RTLD_LOCAL); + free(libFullPath); + } +#else PRLibSpec lspec; lspec.type = PR_LibSpec_Pathname; lspec.value.pathname = lib; sLinkedLib = PR_LoadLibraryWithFlags(lspec, PR_LD_NOW | PR_LD_LOCAL); +#endif /* XP_DARWIN */ if (sLinkedLib) { if (Bind(lib)) { sLib = lib; @@ -92,7 +126,11 @@ FFmpegRuntimeLinker::Link() /* static */ bool FFmpegRuntimeLinker::Bind(const char* aLibName) { +#ifdef XP_DARWIN + avcodec_version = (typeof(avcodec_version))dlsym(sLinkedLib, +#else avcodec_version = (typeof(avcodec_version))PR_FindSymbol(sLinkedLib, +#endif /* XP_DARWIN */ "avcodec_version"); uint32_t fullVersion, major, minor, micro; fullVersion = GetVersion(major, minor, micro); @@ -139,6 +177,17 @@ FFmpegRuntimeLinker::Bind(const char* aLibName) } #define LIBAVCODEC_ALLVERSION +#ifdef XP_DARWIN +#define AV_FUNC(func, ver) \ + if ((ver) & version) { \ + if (!(func = (typeof(func))dlsym(sLinkedLib, #func))) { \ + FFMPEG_LOG("Couldn't load function " #func " from %s.", aLibName); \ + return false; \ + } \ + } else { \ + func = (typeof(func))nullptr; \ + } +#else #define AV_FUNC(func, ver) \ if ((ver) & version) { \ if (!(func = (typeof(func))PR_FindSymbol(sLinkedLib, #func))) { \ @@ -148,6 +197,7 @@ FFmpegRuntimeLinker::Bind(const char* aLibName) } else { \ func = (typeof(func))nullptr; \ } +#endif /* XP_DARWIN */ #include "FFmpegFunctionList.h" #undef AV_FUNC #undef LIBAVCODEC_ALLVERSION @@ -181,7 +231,11 @@ FFmpegRuntimeLinker::CreateDecoderModule() FFmpegRuntimeLinker::Unlink() { if (sLinkedLib) { +#ifdef XP_DARWIN + dlclose(sLinkedLib); +#else PR_UnloadLibrary(sLinkedLib); +#endif /* XP_DARWIN */ sLinkedLib = nullptr; sLib = nullptr; sLinkStatus = LinkStatus_INIT; diff --git a/dom/media/platforms/ffmpeg/FFmpegRuntimeLinker.h b/dom/media/platforms/ffmpeg/FFmpegRuntimeLinker.h index 05ee8a874..6b7324908 100644 --- a/dom/media/platforms/ffmpeg/FFmpegRuntimeLinker.h +++ b/dom/media/platforms/ffmpeg/FFmpegRuntimeLinker.h @@ -40,7 +40,11 @@ public: static uint32_t GetVersion(uint32_t& aMajor, uint32_t& aMinor, uint32_t& aMicro); private: +#ifdef XP_DARWIN + static void* sLinkedLib; +#else static PRLibrary* sLinkedLib; +#endif /* XP_DARWIN */ static const char* sLib; static bool Bind(const char* aLibName);