mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-24 00:24:14 +00:00
Bug 1223333: [ffmpeg] Do not rely on library name to determine the libavcodec's version. r=kentuckyfriedtakahe
Also uses portable way to dynamically open libraries.
This commit is contained in:
parent
7c672a451f
commit
0911f86c44
@ -13,7 +13,7 @@
|
||||
#include "FFmpegLog.h"
|
||||
#include "FFmpegDataDecoder.h"
|
||||
#include "prsystem.h"
|
||||
#include "FFmpegDecoderModule.h"
|
||||
#include "FFmpegRuntimeLinker.h"
|
||||
|
||||
namespace mozilla
|
||||
{
|
||||
@ -89,7 +89,7 @@ FFmpegDataDecoder<LIBAV_VER>::InitDecoder()
|
||||
|
||||
// FFmpeg takes this as a suggestion for what format to use for audio samples.
|
||||
uint32_t major, minor;
|
||||
FFmpegDecoderModule<LIBAV_VER>::GetVersion(major, minor);
|
||||
FFmpegRuntimeLinker::GetVersion(major, minor);
|
||||
// LibAV 0.8 produces rubbish float interlaved samples, request 16 bits audio.
|
||||
mCodecContext->request_sample_fmt = major == 53 && minor <= 34 ?
|
||||
AV_SAMPLE_FMT_S16 : AV_SAMPLE_FMT_FLT;
|
||||
|
@ -26,15 +26,6 @@ public:
|
||||
return pdm.forget();
|
||||
}
|
||||
|
||||
static bool
|
||||
GetVersion(uint32_t& aMajor, uint32_t& aMinor)
|
||||
{
|
||||
uint32_t version = avcodec_version();
|
||||
aMajor = (version >> 16) & 0xff;
|
||||
aMinor = (version >> 8) & 0xff;
|
||||
return true;
|
||||
}
|
||||
|
||||
FFmpegDecoderModule() {}
|
||||
virtual ~FFmpegDecoderModule() {}
|
||||
|
||||
|
@ -16,11 +16,9 @@ AV_FUNC(avcodec_alloc_context3, 0)
|
||||
AV_FUNC(avcodec_get_edge_width, 0)
|
||||
AV_FUNC(avcodec_open2, 0)
|
||||
AV_FUNC(av_init_packet, 0)
|
||||
AV_FUNC(av_dict_get, 0)
|
||||
AV_FUNC(av_parser_init, 0)
|
||||
AV_FUNC(av_parser_close, 0)
|
||||
AV_FUNC(av_parser_parse2, 0)
|
||||
AV_FUNC(avcodec_version, 0)
|
||||
AV_FUNC(avcodec_register_all, 0)
|
||||
|
||||
/* libavutil */
|
||||
|
@ -4,14 +4,11 @@
|
||||
* 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 <dlfcn.h>
|
||||
|
||||
#include "FFmpegRuntimeLinker.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "FFmpegLog.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
#define NUM_ELEMENTS(X) (sizeof(X) / sizeof((X)[0]))
|
||||
#include "prlink.h"
|
||||
|
||||
namespace mozilla
|
||||
{
|
||||
@ -19,35 +16,33 @@ namespace mozilla
|
||||
FFmpegRuntimeLinker::LinkStatus FFmpegRuntimeLinker::sLinkStatus =
|
||||
LinkStatus_INIT;
|
||||
|
||||
struct AvCodecLib
|
||||
{
|
||||
const char* Name;
|
||||
already_AddRefed<PlatformDecoderModule> (*Factory)();
|
||||
uint32_t Version;
|
||||
};
|
||||
|
||||
template <int V> class FFmpegDecoderModule
|
||||
{
|
||||
public:
|
||||
static already_AddRefed<PlatformDecoderModule> Create();
|
||||
};
|
||||
|
||||
static const AvCodecLib sLibs[] = {
|
||||
{ "libavcodec-ffmpeg.so.56", FFmpegDecoderModule<55>::Create, 55 },
|
||||
{ "libavcodec.so.56", FFmpegDecoderModule<55>::Create, 55 },
|
||||
{ "libavcodec.so.55", FFmpegDecoderModule<55>::Create, 55 },
|
||||
{ "libavcodec.so.54", FFmpegDecoderModule<54>::Create, 54 },
|
||||
{ "libavcodec.so.53", FFmpegDecoderModule<53>::Create, 53 },
|
||||
{ "libavcodec.56.dylib", FFmpegDecoderModule<55>::Create, 55 },
|
||||
{ "libavcodec.55.dylib", FFmpegDecoderModule<55>::Create, 55 },
|
||||
{ "libavcodec.54.dylib", FFmpegDecoderModule<54>::Create, 54 },
|
||||
{ "libavcodec.53.dylib", FFmpegDecoderModule<53>::Create, 53 },
|
||||
static const char* sLibs[] = {
|
||||
#if defined(XP_DARWIN)
|
||||
"libavcodec.56.dylib",
|
||||
"libavcodec.55.dylib",
|
||||
"libavcodec.54.dylib",
|
||||
"libavcodec.53.dylib",
|
||||
#else
|
||||
"libavcodec-ffmpeg.so.56",
|
||||
"libavcodec.so.56",
|
||||
"libavcodec.so.55",
|
||||
"libavcodec.so.54",
|
||||
"libavcodec.so.53",
|
||||
#endif
|
||||
};
|
||||
|
||||
void* FFmpegRuntimeLinker::sLinkedLib = nullptr;
|
||||
const AvCodecLib* FFmpegRuntimeLinker::sLib = nullptr;
|
||||
PRLibrary* FFmpegRuntimeLinker::sLinkedLib = nullptr;
|
||||
const char* FFmpegRuntimeLinker::sLib = nullptr;
|
||||
static unsigned (*avcodec_version)() = nullptr;
|
||||
|
||||
#define AV_FUNC(func, ver) void (*func)();
|
||||
|
||||
#define LIBAVCODEC_ALLVERSION
|
||||
#include "FFmpegFunctionList.h"
|
||||
#undef LIBAVCODEC_ALLVERSION
|
||||
@ -63,10 +58,13 @@ FFmpegRuntimeLinker::Link()
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
for (size_t i = 0; i < ArrayLength(sLibs); i++) {
|
||||
const AvCodecLib* lib = &sLibs[i];
|
||||
sLinkedLib = dlopen(lib->Name, RTLD_NOW | RTLD_LOCAL);
|
||||
const char* lib = sLibs[i];
|
||||
PRLibSpec lspec;
|
||||
lspec.type = PR_LibSpec_Pathname;
|
||||
lspec.value.pathname = lib;
|
||||
sLinkedLib = PR_LoadLibraryWithFlags(lspec, PR_LD_NOW | PR_LD_LOCAL);
|
||||
if (sLinkedLib) {
|
||||
if (Bind(lib->Name, lib->Version)) {
|
||||
if (Bind(lib)) {
|
||||
sLib = lib;
|
||||
sLinkStatus = LinkStatus_SUCCEEDED;
|
||||
return true;
|
||||
@ -78,7 +76,7 @@ FFmpegRuntimeLinker::Link()
|
||||
|
||||
FFMPEG_LOG("H264/AAC codecs unsupported without [");
|
||||
for (size_t i = 0; i < ArrayLength(sLibs); i++) {
|
||||
FFMPEG_LOG("%s %s", i ? "," : "", sLibs[i].Name);
|
||||
FFMPEG_LOG("%s %s", i ? "," : "", sLibs[i]);
|
||||
}
|
||||
FFMPEG_LOG(" ]\n");
|
||||
|
||||
@ -89,12 +87,23 @@ FFmpegRuntimeLinker::Link()
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
FFmpegRuntimeLinker::Bind(const char* aLibName, uint32_t Version)
|
||||
FFmpegRuntimeLinker::Bind(const char* aLibName)
|
||||
{
|
||||
avcodec_version = (typeof(avcodec_version))PR_FindSymbol(sLinkedLib,
|
||||
"avcodec_version");
|
||||
uint32_t major, minor;
|
||||
if (!GetVersion(major, minor)) {
|
||||
return false;
|
||||
}
|
||||
if (major > 55) {
|
||||
// All major greater than 56 currently use the same ABI as 55.
|
||||
major = 55;
|
||||
}
|
||||
|
||||
#define LIBAVCODEC_ALLVERSION
|
||||
#define AV_FUNC(func, ver) \
|
||||
if (ver == 0 || ver == Version) { \
|
||||
if (!(func = (typeof(func))dlsym(sLinkedLib, #func))) { \
|
||||
if (ver == 0 || ver == major) { \
|
||||
if (!(func = (typeof(func))PR_FindSymbol(sLinkedLib, #func))) { \
|
||||
FFMPEG_LOG("Couldn't load function " #func " from %s.", aLibName); \
|
||||
return false; \
|
||||
} \
|
||||
@ -111,7 +120,17 @@ FFmpegRuntimeLinker::CreateDecoderModule()
|
||||
if (!Link()) {
|
||||
return nullptr;
|
||||
}
|
||||
RefPtr<PlatformDecoderModule> module = sLib->Factory();
|
||||
uint32_t major, minor;
|
||||
if (!GetVersion(major, minor)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<PlatformDecoderModule> module;
|
||||
switch (major) {
|
||||
case 53: module = FFmpegDecoderModule<53>::Create(); break;
|
||||
case 54: module = FFmpegDecoderModule<54>::Create(); break;
|
||||
default: module = FFmpegDecoderModule<55>::Create(); break;
|
||||
}
|
||||
return module.forget();
|
||||
}
|
||||
|
||||
@ -119,11 +138,24 @@ FFmpegRuntimeLinker::CreateDecoderModule()
|
||||
FFmpegRuntimeLinker::Unlink()
|
||||
{
|
||||
if (sLinkedLib) {
|
||||
dlclose(sLinkedLib);
|
||||
PR_UnloadLibrary(sLinkedLib);
|
||||
sLinkedLib = nullptr;
|
||||
sLib = nullptr;
|
||||
sLinkStatus = LinkStatus_INIT;
|
||||
avcodec_version = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
FFmpegRuntimeLinker::GetVersion(uint32_t& aMajor, uint32_t& aMinor)
|
||||
{
|
||||
if (!avcodec_version) {
|
||||
return false;
|
||||
}
|
||||
uint32_t version = avcodec_version();
|
||||
aMajor = (version >> 16) & 0xff;
|
||||
aMinor = (version >> 8) & 0xff;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -10,23 +10,24 @@
|
||||
#include "PlatformDecoderModule.h"
|
||||
#include <stdint.h>
|
||||
|
||||
struct PRLibrary;
|
||||
|
||||
namespace mozilla
|
||||
{
|
||||
|
||||
struct AvCodecLib;
|
||||
|
||||
class FFmpegRuntimeLinker
|
||||
{
|
||||
public:
|
||||
static bool Link();
|
||||
static void Unlink();
|
||||
static already_AddRefed<PlatformDecoderModule> CreateDecoderModule();
|
||||
static bool GetVersion(uint32_t& aMajor, uint32_t& aMinor);
|
||||
|
||||
private:
|
||||
static void* sLinkedLib;
|
||||
static const AvCodecLib* sLib;
|
||||
static PRLibrary* sLinkedLib;
|
||||
static const char* sLib;
|
||||
|
||||
static bool Bind(const char* aLibName, uint32_t Version);
|
||||
static bool Bind(const char* aLibName);
|
||||
|
||||
static enum LinkStatus {
|
||||
LinkStatus_INIT = 0,
|
||||
|
Loading…
Reference in New Issue
Block a user