mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1240995: [ffmpeg] Refactor FFmpeg PDM. r=kentuckyfriedtakahe
This greatly simplify how the external libavcodec and libavutil are linked.
This commit is contained in:
parent
5470d295d0
commit
c5e7055a40
@ -58,7 +58,6 @@ bool PDMFactory::sAndroidMCDecoderPreferred = false;
|
||||
bool PDMFactory::sGMPDecoderEnabled = false;
|
||||
#ifdef MOZ_FFVPX
|
||||
bool PDMFactory::sFFVPXDecoderEnabled = false;
|
||||
using namespace ffvpx;
|
||||
#endif
|
||||
#ifdef MOZ_FFMPEG
|
||||
bool PDMFactory::sFFmpegDecoderEnabled = false;
|
||||
@ -124,10 +123,10 @@ PDMFactory::Init()
|
||||
AppleDecoderModule::Init();
|
||||
#endif
|
||||
#ifdef MOZ_FFVPX
|
||||
FFVPXRuntimeLinker::Link();
|
||||
FFVPXRuntimeLinker::Init();
|
||||
#endif
|
||||
#ifdef MOZ_FFMPEG
|
||||
FFmpegRuntimeLinker::Link();
|
||||
FFmpegRuntimeLinker::Init();
|
||||
#endif
|
||||
GMPDecoderModule::Init();
|
||||
}
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
#include "mozilla/TaskQueue.h"
|
||||
|
||||
#include "FFmpegRuntimeLinker.h"
|
||||
#include "FFmpegAudioDecoder.h"
|
||||
#include "TimeUnits.h"
|
||||
|
||||
@ -15,10 +14,10 @@
|
||||
namespace mozilla
|
||||
{
|
||||
|
||||
FFmpegAudioDecoder<LIBAV_VER>::FFmpegAudioDecoder(
|
||||
FFmpegAudioDecoder<LIBAV_VER>::FFmpegAudioDecoder(FFmpegLibWrapper* aLib,
|
||||
FlushableTaskQueue* aTaskQueue, MediaDataDecoderCallback* aCallback,
|
||||
const AudioInfo& aConfig)
|
||||
: FFmpegDataDecoder(aTaskQueue, aCallback, GetCodecId(aConfig.mMimeType))
|
||||
: FFmpegDataDecoder(aLib, aTaskQueue, aCallback, GetCodecId(aConfig.mMimeType))
|
||||
{
|
||||
MOZ_COUNT_CTOR(FFmpegAudioDecoder);
|
||||
// Use a new MediaByteBuffer as the object will be modified during initialization.
|
||||
@ -44,11 +43,9 @@ FFmpegAudioDecoder<LIBAV_VER>::InitCodecContext()
|
||||
// isn't implemented.
|
||||
mCodecContext->thread_count = 1;
|
||||
// FFmpeg takes this as a suggestion for what format to use for audio samples.
|
||||
uint32_t major, minor, micro;
|
||||
FFmpegRuntimeLinker::GetVersion(major, minor, micro);
|
||||
// LibAV 0.8 produces rubbish float interleaved samples, request 16 bits audio.
|
||||
mCodecContext->request_sample_fmt =
|
||||
(major == 53) ? AV_SAMPLE_FMT_S16 : AV_SAMPLE_FMT_FLT;
|
||||
(mLib->mVersion == 53) ? AV_SAMPLE_FMT_S16 : AV_SAMPLE_FMT_FLT;
|
||||
}
|
||||
|
||||
static UniquePtr<AudioDataValue[]>
|
||||
@ -101,7 +98,7 @@ FFmpegAudioDecoder<LIBAV_VER>::DecodePacket(MediaRawData* aSample)
|
||||
{
|
||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||
AVPacket packet;
|
||||
AV_CALL(av_init_packet(&packet));
|
||||
mLib->av_init_packet(&packet);
|
||||
|
||||
packet.data = const_cast<uint8_t*>(aSample->Data());
|
||||
packet.size = aSample->Size();
|
||||
@ -118,7 +115,7 @@ FFmpegAudioDecoder<LIBAV_VER>::DecodePacket(MediaRawData* aSample)
|
||||
while (packet.size > 0) {
|
||||
int decoded;
|
||||
int bytesConsumed =
|
||||
AV_CALL(avcodec_decode_audio4(mCodecContext, mFrame, &decoded, &packet));
|
||||
mLib->avcodec_decode_audio4(mCodecContext, mFrame, &decoded, &packet);
|
||||
|
||||
if (bytesConsumed < 0) {
|
||||
NS_WARNING("FFmpeg audio decoder error.");
|
||||
|
@ -7,6 +7,7 @@
|
||||
#ifndef __FFmpegAACDecoder_h__
|
||||
#define __FFmpegAACDecoder_h__
|
||||
|
||||
#include "FFmpegLibWrapper.h"
|
||||
#include "FFmpegDataDecoder.h"
|
||||
|
||||
namespace mozilla
|
||||
@ -20,7 +21,7 @@ template <>
|
||||
class FFmpegAudioDecoder<LIBAV_VER> : public FFmpegDataDecoder<LIBAV_VER>
|
||||
{
|
||||
public:
|
||||
FFmpegAudioDecoder(FlushableTaskQueue* aTaskQueue,
|
||||
FFmpegAudioDecoder(FFmpegLibWrapper* aLib, FlushableTaskQueue* aTaskQueue,
|
||||
MediaDataDecoderCallback* aCallback,
|
||||
const AudioInfo& aConfig);
|
||||
virtual ~FFmpegAudioDecoder();
|
||||
|
@ -18,13 +18,14 @@
|
||||
namespace mozilla
|
||||
{
|
||||
|
||||
bool FFmpegDataDecoder<LIBAV_VER>::sFFmpegInitDone = false;
|
||||
StaticMutex FFmpegDataDecoder<LIBAV_VER>::sMonitor;
|
||||
|
||||
FFmpegDataDecoder<LIBAV_VER>::FFmpegDataDecoder(FlushableTaskQueue* aTaskQueue,
|
||||
MediaDataDecoderCallback* aCallback,
|
||||
AVCodecID aCodecID)
|
||||
: mTaskQueue(aTaskQueue)
|
||||
FFmpegDataDecoder<LIBAV_VER>::FFmpegDataDecoder(FFmpegLibWrapper* aLib,
|
||||
FlushableTaskQueue* aTaskQueue,
|
||||
MediaDataDecoderCallback* aCallback,
|
||||
AVCodecID aCodecID)
|
||||
: mLib(aLib)
|
||||
, mTaskQueue(aTaskQueue)
|
||||
, mCallback(aCallback)
|
||||
, mCodecContext(nullptr)
|
||||
, mFrame(NULL)
|
||||
@ -33,6 +34,7 @@ FFmpegDataDecoder<LIBAV_VER>::FFmpegDataDecoder(FlushableTaskQueue* aTaskQueue,
|
||||
, mMonitor("FFMpegaDataDecoder")
|
||||
, mIsFlushing(false)
|
||||
{
|
||||
MOZ_ASSERT(aLib);
|
||||
MOZ_COUNT_CTOR(FFmpegDataDecoder);
|
||||
}
|
||||
|
||||
@ -46,7 +48,7 @@ FFmpegDataDecoder<LIBAV_VER>::InitDecoder()
|
||||
{
|
||||
FFMPEG_LOG("Initialising FFmpeg decoder.");
|
||||
|
||||
AVCodec* codec = FindAVCodec(mCodecID);
|
||||
AVCodec* codec = FindAVCodec(mLib, mCodecID);
|
||||
if (!codec) {
|
||||
NS_WARNING("Couldn't find ffmpeg decoder");
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -54,7 +56,7 @@ FFmpegDataDecoder<LIBAV_VER>::InitDecoder()
|
||||
|
||||
StaticMutexAutoLock mon(sMonitor);
|
||||
|
||||
if (!(mCodecContext = AV_CALL(avcodec_alloc_context3(codec)))) {
|
||||
if (!(mCodecContext = mLib->avcodec_alloc_context3(codec))) {
|
||||
NS_WARNING("Couldn't init ffmpeg context");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
@ -77,10 +79,10 @@ FFmpegDataDecoder<LIBAV_VER>::InitDecoder()
|
||||
mCodecContext->flags |= CODEC_FLAG_EMU_EDGE;
|
||||
}
|
||||
|
||||
if (AV_CALL(avcodec_open2(mCodecContext, codec, nullptr)) < 0) {
|
||||
if (mLib->avcodec_open2(mCodecContext, codec, nullptr) < 0) {
|
||||
NS_WARNING("Couldn't initialise ffmpeg decoder");
|
||||
AV_CALL(avcodec_close(mCodecContext));
|
||||
AV_CALL(av_freep(&mCodecContext));
|
||||
mLib->avcodec_close(mCodecContext);
|
||||
mLib->av_freep(&mCodecContext);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
@ -141,7 +143,7 @@ FFmpegDataDecoder<LIBAV_VER>::ProcessFlush()
|
||||
{
|
||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||
if (mCodecContext) {
|
||||
AV_CALL(avcodec_flush_buffers(mCodecContext));
|
||||
mLib->avcodec_flush_buffers(mCodecContext);
|
||||
}
|
||||
MonitorAutoLock mon(mMonitor);
|
||||
mIsFlushing = false;
|
||||
@ -153,13 +155,13 @@ FFmpegDataDecoder<LIBAV_VER>::ProcessShutdown()
|
||||
{
|
||||
StaticMutexAutoLock mon(sMonitor);
|
||||
|
||||
if (sFFmpegInitDone && mCodecContext) {
|
||||
AV_CALL(avcodec_close(mCodecContext));
|
||||
AV_CALL(av_freep(&mCodecContext));
|
||||
if (mCodecContext) {
|
||||
mLib->avcodec_close(mCodecContext);
|
||||
mLib->av_freep(&mCodecContext);
|
||||
#if LIBAVCODEC_VERSION_MAJOR >= 55
|
||||
AV_CALL(av_frame_free(&mFrame));
|
||||
mLib->av_frame_free(&mFrame);
|
||||
#elif LIBAVCODEC_VERSION_MAJOR == 54
|
||||
AV_CALL(avcodec_free_frame(&mFrame));
|
||||
mLib->avcodec_free_frame(&mFrame);
|
||||
#else
|
||||
delete mFrame;
|
||||
mFrame = nullptr;
|
||||
@ -173,36 +175,29 @@ FFmpegDataDecoder<LIBAV_VER>::PrepareFrame()
|
||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||
#if LIBAVCODEC_VERSION_MAJOR >= 55
|
||||
if (mFrame) {
|
||||
AV_CALL(av_frame_unref(mFrame));
|
||||
mLib->av_frame_unref(mFrame);
|
||||
} else {
|
||||
mFrame = AV_CALL(av_frame_alloc());
|
||||
mFrame = mLib->av_frame_alloc();
|
||||
}
|
||||
#elif LIBAVCODEC_VERSION_MAJOR == 54
|
||||
if (mFrame) {
|
||||
AV_CALL(avcodec_get_frame_defaults(mFrame));
|
||||
mLib->avcodec_get_frame_defaults(mFrame);
|
||||
} else {
|
||||
mFrame = AV_CALL(avcodec_alloc_frame());
|
||||
mFrame = mLib->avcodec_alloc_frame();
|
||||
}
|
||||
#else
|
||||
delete mFrame;
|
||||
mFrame = new AVFrame;
|
||||
AV_CALL(avcodec_get_frame_defaults(mFrame));
|
||||
mLib->avcodec_get_frame_defaults(mFrame);
|
||||
#endif
|
||||
return mFrame;
|
||||
}
|
||||
|
||||
/* static */ AVCodec*
|
||||
FFmpegDataDecoder<LIBAV_VER>::FindAVCodec(AVCodecID aCodec)
|
||||
FFmpegDataDecoder<LIBAV_VER>::FindAVCodec(FFmpegLibWrapper* aLib,
|
||||
AVCodecID aCodec)
|
||||
{
|
||||
StaticMutexAutoLock mon(sMonitor);
|
||||
if (!sFFmpegInitDone) {
|
||||
AV_CALL(avcodec_register_all());
|
||||
#ifdef DEBUG
|
||||
AV_CALL(av_log_set_level(AV_LOG_DEBUG));
|
||||
#endif
|
||||
sFFmpegInitDone = true;
|
||||
}
|
||||
return AV_CALL(avcodec_find_decoder(aCodec));
|
||||
return aLib->avcodec_find_decoder(aCodec);
|
||||
}
|
||||
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -8,9 +8,9 @@
|
||||
#define __FFmpegDataDecoder_h__
|
||||
|
||||
#include "PlatformDecoderModule.h"
|
||||
#include "FFmpegLibs.h"
|
||||
#include "FFmpegRuntimeLinker.h"
|
||||
#include "FFmpegLibWrapper.h"
|
||||
#include "mozilla/StaticMutex.h"
|
||||
#include "FFmpegLibs.h"
|
||||
|
||||
namespace mozilla
|
||||
{
|
||||
@ -24,7 +24,7 @@ template <>
|
||||
class FFmpegDataDecoder<LIBAV_VER> : public MediaDataDecoder
|
||||
{
|
||||
public:
|
||||
FFmpegDataDecoder(FlushableTaskQueue* aTaskQueue,
|
||||
FFmpegDataDecoder(FFmpegLibWrapper* aLib, FlushableTaskQueue* aTaskQueue,
|
||||
MediaDataDecoderCallback* aCallback,
|
||||
AVCodecID aCodecID);
|
||||
virtual ~FFmpegDataDecoder();
|
||||
@ -37,7 +37,7 @@ public:
|
||||
nsresult Drain() override;
|
||||
nsresult Shutdown() override;
|
||||
|
||||
static AVCodec* FindAVCodec(AVCodecID aCodec);
|
||||
static AVCodec* FindAVCodec(FFmpegLibWrapper* aLib, AVCodecID aCodec);
|
||||
|
||||
protected:
|
||||
// Flush and Drain operation, always run
|
||||
@ -48,6 +48,7 @@ protected:
|
||||
AVFrame* PrepareFrame();
|
||||
nsresult InitDecoder();
|
||||
|
||||
FFmpegLibWrapper* mLib;
|
||||
RefPtr<FlushableTaskQueue> mTaskQueue;
|
||||
MediaDataDecoderCallback* mCallback;
|
||||
|
||||
@ -65,7 +66,6 @@ protected:
|
||||
Atomic<bool> mIsFlushing;
|
||||
|
||||
private:
|
||||
static bool sFFmpegInitDone;
|
||||
static StaticMutex sMonitor;
|
||||
};
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
#define __FFmpegDecoderModule_h__
|
||||
|
||||
#include "PlatformDecoderModule.h"
|
||||
#include "FFmpegLibWrapper.h"
|
||||
#include "FFmpegAudioDecoder.h"
|
||||
#include "FFmpegVideoDecoder.h"
|
||||
|
||||
@ -19,14 +20,14 @@ class FFmpegDecoderModule : public PlatformDecoderModule
|
||||
{
|
||||
public:
|
||||
static already_AddRefed<PlatformDecoderModule>
|
||||
Create()
|
||||
Create(FFmpegLibWrapper* aLib)
|
||||
{
|
||||
RefPtr<PlatformDecoderModule> pdm = new FFmpegDecoderModule();
|
||||
RefPtr<PlatformDecoderModule> pdm = new FFmpegDecoderModule(aLib);
|
||||
|
||||
return pdm.forget();
|
||||
}
|
||||
|
||||
FFmpegDecoderModule() {}
|
||||
explicit FFmpegDecoderModule(FFmpegLibWrapper* aLib) : mLib(aLib) {}
|
||||
virtual ~FFmpegDecoderModule() {}
|
||||
|
||||
already_AddRefed<MediaDataDecoder>
|
||||
@ -37,7 +38,7 @@ public:
|
||||
MediaDataDecoderCallback* aCallback) override
|
||||
{
|
||||
RefPtr<MediaDataDecoder> decoder =
|
||||
new FFmpegVideoDecoder<V>(aVideoTaskQueue, aCallback, aConfig,
|
||||
new FFmpegVideoDecoder<V>(mLib, aVideoTaskQueue, aCallback, aConfig,
|
||||
aImageContainer);
|
||||
return decoder.forget();
|
||||
}
|
||||
@ -51,7 +52,7 @@ public:
|
||||
return nullptr;
|
||||
#else
|
||||
RefPtr<MediaDataDecoder> decoder =
|
||||
new FFmpegAudioDecoder<V>(aAudioTaskQueue, aCallback, aConfig);
|
||||
new FFmpegAudioDecoder<V>(mLib, aAudioTaskQueue, aCallback, aConfig);
|
||||
return decoder.forget();
|
||||
#endif
|
||||
}
|
||||
@ -68,7 +69,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
AVCodecID codec = audioCodec != AV_CODEC_ID_NONE ? audioCodec : videoCodec;
|
||||
return !!FFmpegDataDecoder<V>::FindAVCodec(codec);
|
||||
return !!FFmpegDataDecoder<V>::FindAVCodec(mLib, codec);
|
||||
}
|
||||
|
||||
ConversionRequired
|
||||
@ -83,6 +84,8 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
FFmpegLibWrapper* mLib;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -1,39 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
/* libavcodec */
|
||||
AV_FUNC(avcodec_alloc_context3, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_close, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_decode_audio4, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_decode_video2, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_find_decoder, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_flush_buffers, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_open2, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_register_all, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(av_init_packet, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(av_parser_init, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(av_parser_close, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(av_parser_parse2, AV_FUNC_AVCODEC_ALL)
|
||||
#if LIBAVCODEC_VERSION_MAJOR <= 54 || defined(LIBAVCODEC_ALLVERSION)
|
||||
AV_FUNC(avcodec_get_frame_defaults, (AV_FUNC_53 | AV_FUNC_54))
|
||||
#endif
|
||||
|
||||
/* libavutil */
|
||||
AV_FUNC(av_log_set_level, AV_FUNC_AVUTIL_ALL)
|
||||
AV_FUNC(av_malloc, AV_FUNC_AVUTIL_ALL)
|
||||
AV_FUNC(av_freep, AV_FUNC_AVUTIL_ALL)
|
||||
|
||||
#if defined(LIBAVCODEC_VERSION_MAJOR) || defined(LIBAVCODEC_ALLVERSION)
|
||||
#if LIBAVCODEC_VERSION_MAJOR == 54 || defined(LIBAVCODEC_ALLVERSION)
|
||||
/* libavutil v54 only */
|
||||
AV_FUNC(avcodec_alloc_frame, AV_FUNC_AVUTIL_54)
|
||||
AV_FUNC(avcodec_free_frame, AV_FUNC_AVUTIL_54)
|
||||
#endif
|
||||
#if LIBAVCODEC_VERSION_MAJOR >= 55 || defined(LIBAVCODEC_ALLVERSION)
|
||||
/* libavutil v55 and later only */
|
||||
AV_FUNC(av_frame_alloc, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57))
|
||||
AV_FUNC(av_frame_free, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57))
|
||||
AV_FUNC(av_frame_unref, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57))
|
||||
#endif
|
||||
#endif
|
142
dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp
Normal file
142
dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp
Normal file
@ -0,0 +1,142 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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 "FFmpegLibWrapper.h"
|
||||
#include "FFmpegLog.h"
|
||||
#include "mozilla/PodOperations.h"
|
||||
#include "mozilla/Types.h"
|
||||
#include "prlink.h"
|
||||
|
||||
#define AV_LOG_DEBUG 48
|
||||
|
||||
namespace mozilla
|
||||
{
|
||||
|
||||
FFmpegLibWrapper::FFmpegLibWrapper()
|
||||
{
|
||||
PodZero(this);
|
||||
}
|
||||
|
||||
FFmpegLibWrapper::~FFmpegLibWrapper()
|
||||
{
|
||||
Unlink();
|
||||
}
|
||||
|
||||
bool
|
||||
FFmpegLibWrapper::Link()
|
||||
{
|
||||
if (!mAVCodecLib || !mAVUtilLib) {
|
||||
Unlink();
|
||||
return false;
|
||||
}
|
||||
|
||||
avcodec_version =
|
||||
(decltype(avcodec_version))PR_FindSymbol(mAVCodecLib, "avcodec_version");
|
||||
if (!avcodec_version) {
|
||||
Unlink();
|
||||
return false;
|
||||
}
|
||||
uint32_t version = avcodec_version();
|
||||
mVersion = (version >> 16) & 0xff;
|
||||
uint32_t micro = version & 0xff;
|
||||
if (mVersion == 57 && micro != 100) {
|
||||
// a micro version of 100 indicates that it's FFmpeg (as opposed to LibAV).
|
||||
// Due to current AVCodecContext binary incompatibility we can only
|
||||
// support FFmpeg 57 at this stage.
|
||||
Unlink();
|
||||
return false;
|
||||
}
|
||||
|
||||
enum {
|
||||
AV_FUNC_AVUTIL_MASK = 1 << 8,
|
||||
AV_FUNC_53 = 1 << 0,
|
||||
AV_FUNC_54 = 1 << 1,
|
||||
AV_FUNC_55 = 1 << 2,
|
||||
AV_FUNC_56 = 1 << 3,
|
||||
AV_FUNC_57 = 1 << 4,
|
||||
AV_FUNC_AVUTIL_53 = AV_FUNC_53 | AV_FUNC_AVUTIL_MASK,
|
||||
AV_FUNC_AVUTIL_54 = AV_FUNC_54 | AV_FUNC_AVUTIL_MASK,
|
||||
AV_FUNC_AVUTIL_55 = AV_FUNC_55 | AV_FUNC_AVUTIL_MASK,
|
||||
AV_FUNC_AVUTIL_56 = AV_FUNC_56 | AV_FUNC_AVUTIL_MASK,
|
||||
AV_FUNC_AVUTIL_57 = AV_FUNC_57 | AV_FUNC_AVUTIL_MASK,
|
||||
AV_FUNC_AVCODEC_ALL = AV_FUNC_53 | AV_FUNC_54 | AV_FUNC_55 | AV_FUNC_56 | AV_FUNC_57,
|
||||
AV_FUNC_AVUTIL_ALL = AV_FUNC_AVCODEC_ALL | AV_FUNC_AVUTIL_MASK
|
||||
};
|
||||
|
||||
switch (mVersion) {
|
||||
case 53:
|
||||
version = AV_FUNC_53;
|
||||
break;
|
||||
case 54:
|
||||
version = AV_FUNC_54;
|
||||
break;
|
||||
case 55:
|
||||
version = AV_FUNC_55;
|
||||
break;
|
||||
case 56:
|
||||
version = AV_FUNC_56;
|
||||
break;
|
||||
case 57:
|
||||
version = AV_FUNC_57;
|
||||
break;
|
||||
default:
|
||||
FFMPEG_LOG("Unknown avcodec version");
|
||||
Unlink();
|
||||
return false;
|
||||
}
|
||||
|
||||
#define AV_FUNC(func, ver) \
|
||||
if ((ver) & version) { \
|
||||
if (!(func = (decltype(func))PR_FindSymbol(((ver) & AV_FUNC_AVUTIL_MASK) ? mAVUtilLib : mAVCodecLib, #func))) { \
|
||||
FFMPEG_LOG("Couldn't load function " # func); \
|
||||
Unlink(); \
|
||||
return false; \
|
||||
} \
|
||||
} else { \
|
||||
func = (decltype(func))nullptr; \
|
||||
}
|
||||
AV_FUNC(avcodec_alloc_context3, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_close, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_decode_audio4, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_decode_video2, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_find_decoder, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_flush_buffers, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_open2, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_register_all, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(av_init_packet, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(av_parser_init, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(av_parser_close, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(av_parser_parse2, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_get_frame_defaults, (AV_FUNC_53 | AV_FUNC_54))
|
||||
AV_FUNC(av_log_set_level, AV_FUNC_AVUTIL_ALL)
|
||||
AV_FUNC(av_malloc, AV_FUNC_AVUTIL_ALL)
|
||||
AV_FUNC(av_freep, AV_FUNC_AVUTIL_ALL)
|
||||
AV_FUNC(avcodec_alloc_frame, AV_FUNC_AVUTIL_54)
|
||||
AV_FUNC(avcodec_free_frame, AV_FUNC_AVUTIL_54)
|
||||
AV_FUNC(av_frame_alloc, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57))
|
||||
AV_FUNC(av_frame_free, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57))
|
||||
AV_FUNC(av_frame_unref, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57))
|
||||
#undef AV_FUNC
|
||||
|
||||
avcodec_register_all();
|
||||
#ifdef DEBUG
|
||||
av_log_set_level(AV_LOG_DEBUG);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
FFmpegLibWrapper::Unlink()
|
||||
{
|
||||
if (mAVUtilLib && mAVUtilLib != mAVCodecLib) {
|
||||
PR_UnloadLibrary(mAVUtilLib);
|
||||
}
|
||||
if (mAVCodecLib) {
|
||||
PR_UnloadLibrary(mAVCodecLib);
|
||||
}
|
||||
PodZero(this);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
78
dom/media/platforms/ffmpeg/FFmpegLibWrapper.h
Normal file
78
dom/media/platforms/ffmpeg/FFmpegLibWrapper.h
Normal file
@ -0,0 +1,78 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#ifndef __FFmpegLibWrapper_h__
|
||||
#define __FFmpegLibWrapper_h__
|
||||
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
struct AVCodec;
|
||||
struct AVCodecContext;
|
||||
struct AVFrame;
|
||||
struct AVPacket;
|
||||
struct AVDictionary;
|
||||
struct AVCodecParserContext;
|
||||
struct PRLibrary;
|
||||
|
||||
namespace mozilla
|
||||
{
|
||||
|
||||
struct FFmpegLibWrapper
|
||||
{
|
||||
FFmpegLibWrapper();
|
||||
~FFmpegLibWrapper();
|
||||
|
||||
// Attempt to resolve all symbols. Return true of successful.
|
||||
// Upon failure, the entire object will be reset and any attached libraries
|
||||
// will be unlinked.
|
||||
bool Link();
|
||||
|
||||
// Reset the wrapper and unlink all attached libraries.
|
||||
void Unlink();
|
||||
|
||||
// indicate the version of libavcodec linked to.
|
||||
// 0 indicates that the function wasn't initialized with Link().
|
||||
int mVersion;
|
||||
|
||||
// libavcodec
|
||||
unsigned (*avcodec_version)();
|
||||
AVCodecContext* (*avcodec_alloc_context3)(const AVCodec* codec);
|
||||
int (*avcodec_close)(AVCodecContext* avctx);
|
||||
int (*avcodec_decode_audio4)(AVCodecContext* avctx, AVFrame* frame, int* got_frame_ptr, const AVPacket* avpkt);
|
||||
int (*avcodec_decode_video2)(AVCodecContext* avctx, AVFrame* picture, int* got_picture_ptr, const AVPacket* avpkt);
|
||||
AVCodec* (*avcodec_find_decoder)(int id);
|
||||
void (*avcodec_flush_buffers)(AVCodecContext *avctx);
|
||||
int (*avcodec_open2)(AVCodecContext *avctx, const AVCodec* codec, AVDictionary** options);
|
||||
void (*avcodec_register_all)();
|
||||
void (*av_init_packet)(AVPacket* pkt);
|
||||
AVCodecParserContext* (*av_parser_init)(int codec_id);
|
||||
void (*av_parser_close)(AVCodecParserContext* s);
|
||||
int (*av_parser_parse2)(AVCodecParserContext* s, AVCodecContext* avctx, uint8_t** poutbuf, int* poutbuf_size, const uint8_t* buf, int buf_size, int64_t pts, int64_t dts, int64_t pos);
|
||||
|
||||
// only used in libavcodec <= 54
|
||||
void (*avcodec_get_frame_defaults)(AVFrame* pic);
|
||||
|
||||
// libavutil
|
||||
void (*av_log_set_level)(int level);
|
||||
void* (*av_malloc)(size_t size);
|
||||
void (*av_freep)(void *ptr);
|
||||
|
||||
// libavutil v54 only
|
||||
AVFrame* (*avcodec_alloc_frame)();
|
||||
void (*avcodec_free_frame)(AVFrame** frame);
|
||||
|
||||
// libavutil v55 and later only
|
||||
AVFrame* (*av_frame_alloc)();
|
||||
void (*av_frame_free)(AVFrame** frame);
|
||||
void (*av_frame_unref)(AVFrame* frame);
|
||||
|
||||
PRLibrary* mAVCodecLib;
|
||||
PRLibrary* mAVUtilLib;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // FFmpegLibWrapper
|
@ -7,8 +7,6 @@
|
||||
#ifndef __FFmpegLibs_h__
|
||||
#define __FFmpegLibs_h__
|
||||
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
extern "C" {
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC visibility push(default)
|
||||
@ -37,23 +35,4 @@ enum { LIBAV_VER = FFVPX_VERSION };
|
||||
enum { LIBAV_VER = LIBAVCODEC_VERSION_MAJOR };
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
#ifdef USING_MOZFFVPX
|
||||
namespace ffvpx {
|
||||
#endif
|
||||
|
||||
#define AV_FUNC(func, ver) extern decltype(func)* func;
|
||||
#include "FFmpegFunctionList.h"
|
||||
#undef AV_FUNC
|
||||
|
||||
#ifdef USING_MOZFFVPX
|
||||
} // namespace ffvpx
|
||||
#define AV_CALL(func) mozilla::ffvpx::func
|
||||
#else
|
||||
#define AV_CALL(func) mozilla::func
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif // __FFmpegLibs_h__
|
||||
|
@ -7,6 +7,8 @@
|
||||
#ifndef __FFmpegLog_h__
|
||||
#define __FFmpegLog_h__
|
||||
|
||||
#include "mozilla/Logging.h"
|
||||
|
||||
extern mozilla::LogModule* GetPDMLog();
|
||||
#define FFMPEG_LOG(...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
|
||||
|
@ -5,9 +5,9 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "FFmpegRuntimeLinker.h"
|
||||
#include "FFmpegLibWrapper.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "FFmpegLog.h"
|
||||
#include "mozilla/Types.h"
|
||||
#include "prlink.h"
|
||||
|
||||
namespace mozilla
|
||||
@ -19,9 +19,11 @@ FFmpegRuntimeLinker::LinkStatus FFmpegRuntimeLinker::sLinkStatus =
|
||||
template <int V> class FFmpegDecoderModule
|
||||
{
|
||||
public:
|
||||
static already_AddRefed<PlatformDecoderModule> Create();
|
||||
static already_AddRefed<PlatformDecoderModule> Create(FFmpegLibWrapper*);
|
||||
};
|
||||
|
||||
static FFmpegLibWrapper sLibAV;
|
||||
|
||||
static const char* sLibs[] = {
|
||||
#if defined(XP_DARWIN)
|
||||
"libavcodec.57.dylib",
|
||||
@ -40,30 +42,8 @@ static const char* sLibs[] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
PRLibrary* FFmpegRuntimeLinker::sLinkedLib = nullptr;
|
||||
PRLibrary* FFmpegRuntimeLinker::sLinkedUtilLib = nullptr;
|
||||
static unsigned (*avcodec_version)() = nullptr;
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define AV_FUNC(func, ver) void (*func)();
|
||||
#define LIBAVCODEC_ALLVERSION
|
||||
#else
|
||||
#define AV_FUNC(func, ver) decltype(func)* func;
|
||||
#endif
|
||||
#include "FFmpegFunctionList.h"
|
||||
#undef AV_FUNC
|
||||
|
||||
static PRLibrary*
|
||||
MozAVLink(const char* aName)
|
||||
{
|
||||
PRLibSpec lspec;
|
||||
lspec.type = PR_LibSpec_Pathname;
|
||||
lspec.value.pathname = aName;
|
||||
return PR_LoadLibraryWithFlags(lspec, PR_LD_NOW | PR_LD_LOCAL);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
FFmpegRuntimeLinker::Link()
|
||||
FFmpegRuntimeLinker::Init()
|
||||
{
|
||||
if (sLinkStatus) {
|
||||
return sLinkStatus == LinkStatus_SUCCEEDED;
|
||||
@ -72,15 +52,16 @@ FFmpegRuntimeLinker::Link()
|
||||
|
||||
for (size_t i = 0; i < ArrayLength(sLibs); i++) {
|
||||
const char* lib = sLibs[i];
|
||||
sLinkedLib = MozAVLink(lib);
|
||||
if (sLinkedLib) {
|
||||
sLinkedUtilLib = sLinkedLib;
|
||||
if (Bind(lib)) {
|
||||
PRLibSpec lspec;
|
||||
lspec.type = PR_LibSpec_Pathname;
|
||||
lspec.value.pathname = lib;
|
||||
sLibAV.mAVCodecLib = PR_LoadLibraryWithFlags(lspec, PR_LD_NOW | PR_LD_LOCAL);
|
||||
if (sLibAV.mAVCodecLib) {
|
||||
sLibAV.mAVUtilLib = sLibAV.mAVCodecLib;
|
||||
if (sLibAV.Link()) {
|
||||
sLinkStatus = LinkStatus_SUCCEEDED;
|
||||
return true;
|
||||
}
|
||||
// Shouldn't happen but if it does then we try the next lib..
|
||||
Unlink();
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,113 +71,26 @@ FFmpegRuntimeLinker::Link()
|
||||
}
|
||||
FFMPEG_LOG(" ]\n");
|
||||
|
||||
Unlink();
|
||||
|
||||
sLinkStatus = LinkStatus_FAILED;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
FFmpegRuntimeLinker::Bind(const char* aLibName)
|
||||
{
|
||||
avcodec_version = (decltype(avcodec_version))PR_FindSymbol(sLinkedLib,
|
||||
"avcodec_version");
|
||||
uint32_t major, minor, micro;
|
||||
if (!GetVersion(major, minor, micro)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int version;
|
||||
switch (major) {
|
||||
case 53:
|
||||
version = AV_FUNC_53;
|
||||
break;
|
||||
case 54:
|
||||
version = AV_FUNC_54;
|
||||
break;
|
||||
case 56:
|
||||
// We use libavcodec 55 code instead. Fallback
|
||||
case 55:
|
||||
version = AV_FUNC_55;
|
||||
break;
|
||||
case 57:
|
||||
if (micro != 100) {
|
||||
// a micro version of 100 indicates that it's FFmpeg (as opposed to LibAV.
|
||||
// Due to current AVCodecContext binary incompatibility we can only
|
||||
// support FFmpeg at this stage.
|
||||
return false;
|
||||
}
|
||||
version = AV_FUNC_57;
|
||||
break;
|
||||
default:
|
||||
// Not supported at this stage.
|
||||
return false;
|
||||
}
|
||||
|
||||
#define AV_FUNC(func, ver) \
|
||||
if ((ver) & version) { \
|
||||
if (!(func = (decltype(func))PR_FindSymbol(((ver) & AV_FUNC_AVUTIL_MASK) ? sLinkedUtilLib : sLinkedLib, #func))) { \
|
||||
FFMPEG_LOG("Couldn't load function " #func " from %s.", aLibName); \
|
||||
return false; \
|
||||
} \
|
||||
} else { \
|
||||
func = (decltype(func))nullptr; \
|
||||
}
|
||||
#include "FFmpegFunctionList.h"
|
||||
#undef AV_FUNC
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<PlatformDecoderModule>
|
||||
FFmpegRuntimeLinker::CreateDecoderModule()
|
||||
{
|
||||
if (!Link()) {
|
||||
if (!Init()) {
|
||||
return nullptr;
|
||||
}
|
||||
uint32_t major, minor, micro;
|
||||
if (!GetVersion(major, minor, micro)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<PlatformDecoderModule> module;
|
||||
switch (major) {
|
||||
case 53: module = FFmpegDecoderModule<53>::Create(); break;
|
||||
case 54: module = FFmpegDecoderModule<54>::Create(); break;
|
||||
switch (sLibAV.mVersion) {
|
||||
case 53: module = FFmpegDecoderModule<53>::Create(&sLibAV); break;
|
||||
case 54: module = FFmpegDecoderModule<54>::Create(&sLibAV); break;
|
||||
case 55:
|
||||
case 56: module = FFmpegDecoderModule<55>::Create(); break;
|
||||
case 57: module = FFmpegDecoderModule<57>::Create(); break;
|
||||
case 56: module = FFmpegDecoderModule<55>::Create(&sLibAV); break;
|
||||
case 57: module = FFmpegDecoderModule<57>::Create(&sLibAV); break;
|
||||
default: module = nullptr;
|
||||
}
|
||||
return module.forget();
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
FFmpegRuntimeLinker::Unlink()
|
||||
{
|
||||
if (sLinkedUtilLib && sLinkedUtilLib != sLinkedLib) {
|
||||
PR_UnloadLibrary(sLinkedUtilLib);
|
||||
}
|
||||
if (sLinkedLib) {
|
||||
PR_UnloadLibrary(sLinkedLib);
|
||||
sLinkedLib = nullptr;
|
||||
sLinkStatus = LinkStatus_INIT;
|
||||
avcodec_version = nullptr;
|
||||
}
|
||||
sLinkedUtilLib = nullptr;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
FFmpegRuntimeLinker::GetVersion(uint32_t& aMajor, uint32_t& aMinor, uint32_t& aMicro)
|
||||
{
|
||||
if (!avcodec_version) {
|
||||
return false;
|
||||
}
|
||||
uint32_t version = avcodec_version();
|
||||
aMajor = (version >> 16) & 0xff;
|
||||
aMinor = (version >> 8) & 0xff;
|
||||
aMicro = version & 0xff;
|
||||
return true;
|
||||
}
|
||||
|
||||
#undef LIBAVCODEC_ALLVERSION
|
||||
} // namespace mozilla
|
||||
|
@ -8,43 +8,17 @@
|
||||
#define __FFmpegRuntimeLinker_h__
|
||||
|
||||
#include "PlatformDecoderModule.h"
|
||||
#include <stdint.h>
|
||||
|
||||
struct PRLibrary;
|
||||
|
||||
namespace mozilla
|
||||
{
|
||||
|
||||
enum {
|
||||
AV_FUNC_AVUTIL_MASK = 1 << 8,
|
||||
AV_FUNC_53 = 1 << 0,
|
||||
AV_FUNC_54 = 1 << 1,
|
||||
AV_FUNC_55 = 1 << 2,
|
||||
AV_FUNC_56 = 1 << 3,
|
||||
AV_FUNC_57 = 1 << 4,
|
||||
AV_FUNC_AVUTIL_53 = AV_FUNC_53 | AV_FUNC_AVUTIL_MASK,
|
||||
AV_FUNC_AVUTIL_54 = AV_FUNC_54 | AV_FUNC_AVUTIL_MASK,
|
||||
AV_FUNC_AVUTIL_55 = AV_FUNC_55 | AV_FUNC_AVUTIL_MASK,
|
||||
AV_FUNC_AVUTIL_56 = AV_FUNC_56 | AV_FUNC_AVUTIL_MASK,
|
||||
AV_FUNC_AVUTIL_57 = AV_FUNC_57 | AV_FUNC_AVUTIL_MASK,
|
||||
AV_FUNC_AVCODEC_ALL = AV_FUNC_53 | AV_FUNC_54 | AV_FUNC_55 | AV_FUNC_56 | AV_FUNC_57,
|
||||
AV_FUNC_AVUTIL_ALL = AV_FUNC_AVCODEC_ALL | AV_FUNC_AVUTIL_MASK
|
||||
};
|
||||
|
||||
class FFmpegRuntimeLinker
|
||||
{
|
||||
public:
|
||||
static bool Link();
|
||||
static void Unlink();
|
||||
static bool Init();
|
||||
static already_AddRefed<PlatformDecoderModule> CreateDecoderModule();
|
||||
static bool GetVersion(uint32_t& aMajor, uint32_t& aMinor, uint32_t& aMicro);
|
||||
|
||||
private:
|
||||
static PRLibrary* sLinkedLib;
|
||||
static PRLibrary* sLinkedUtilLib;
|
||||
|
||||
static bool Bind(const char* aLibName);
|
||||
|
||||
static enum LinkStatus {
|
||||
LinkStatus_INIT = 0,
|
||||
LinkStatus_FAILED,
|
||||
|
@ -98,11 +98,11 @@ FFmpegVideoDecoder<LIBAV_VER>::PtsCorrectionContext::Reset()
|
||||
mLastDts = INT64_MIN;
|
||||
}
|
||||
|
||||
FFmpegVideoDecoder<LIBAV_VER>::FFmpegVideoDecoder(
|
||||
FFmpegVideoDecoder<LIBAV_VER>::FFmpegVideoDecoder(FFmpegLibWrapper* aLib,
|
||||
FlushableTaskQueue* aTaskQueue, MediaDataDecoderCallback* aCallback,
|
||||
const VideoInfo& aConfig,
|
||||
ImageContainer* aImageContainer)
|
||||
: FFmpegDataDecoder(aTaskQueue, aCallback, GetCodecId(aConfig.mMimeType))
|
||||
: FFmpegDataDecoder(aLib, aTaskQueue, aCallback, GetCodecId(aConfig.mMimeType))
|
||||
, mImageContainer(aImageContainer)
|
||||
, mDisplay(aConfig.mDisplay)
|
||||
, mImage(aConfig.mImage)
|
||||
@ -151,7 +151,7 @@ FFmpegVideoDecoder<LIBAV_VER>::InitCodecContext()
|
||||
// FFmpeg will call back to this to negotiate a video pixel format.
|
||||
mCodecContext->get_format = ChoosePixelFormat;
|
||||
|
||||
mCodecParser = AV_CALL(av_parser_init(mCodecID));
|
||||
mCodecParser = mLib->av_parser_init(mCodecID);
|
||||
if (mCodecParser) {
|
||||
mCodecParser->flags |= PARSER_FLAG_COMPLETE_FRAMES;
|
||||
}
|
||||
@ -175,10 +175,10 @@ FFmpegVideoDecoder<LIBAV_VER>::DoDecodeFrame(MediaRawData* aSample)
|
||||
while (inputSize) {
|
||||
uint8_t* data;
|
||||
int size;
|
||||
int len = AV_CALL(av_parser_parse2(mCodecParser, mCodecContext, &data, &size,
|
||||
inputData, inputSize,
|
||||
aSample->mTime, aSample->mTimecode,
|
||||
aSample->mOffset));
|
||||
int len = mLib->av_parser_parse2(mCodecParser, mCodecContext, &data, &size,
|
||||
inputData, inputSize,
|
||||
aSample->mTime, aSample->mTimecode,
|
||||
aSample->mOffset);
|
||||
if (size_t(len) > inputSize) {
|
||||
mCallback->Error();
|
||||
return DecodeResult::DECODE_ERROR;
|
||||
@ -210,7 +210,7 @@ FFmpegVideoDecoder<LIBAV_VER>::DoDecodeFrame(MediaRawData* aSample,
|
||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||
|
||||
AVPacket packet;
|
||||
AV_CALL(av_init_packet(&packet));
|
||||
mLib->av_init_packet(&packet);
|
||||
|
||||
packet.data = aData;
|
||||
packet.size = aSize;
|
||||
@ -237,7 +237,7 @@ FFmpegVideoDecoder<LIBAV_VER>::DoDecodeFrame(MediaRawData* aSample,
|
||||
|
||||
int decoded;
|
||||
int bytesConsumed =
|
||||
AV_CALL(avcodec_decode_video2(mCodecContext, mFrame, &decoded, &packet));
|
||||
mLib->avcodec_decode_video2(mCodecContext, mFrame, &decoded, &packet);
|
||||
|
||||
FFMPEG_LOG("DoDecodeFrame:decode_video: rv=%d decoded=%d "
|
||||
"(Input: pts(%lld) dts(%lld) Output: pts(%lld) "
|
||||
@ -361,7 +361,7 @@ FFmpegVideoDecoder<LIBAV_VER>::~FFmpegVideoDecoder()
|
||||
{
|
||||
MOZ_COUNT_DTOR(FFmpegVideoDecoder);
|
||||
if (mCodecParser) {
|
||||
AV_CALL(av_parser_close(mCodecParser));
|
||||
mLib->av_parser_close(mCodecParser);
|
||||
mCodecParser = nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
#ifndef __FFmpegVideoDecoder_h__
|
||||
#define __FFmpegVideoDecoder_h__
|
||||
|
||||
#include "FFmpegLibWrapper.h"
|
||||
#include "FFmpegDataDecoder.h"
|
||||
#include "mozilla/Pair.h"
|
||||
#include "nsTArray.h"
|
||||
@ -32,10 +33,10 @@ class FFmpegVideoDecoder<LIBAV_VER> : public FFmpegDataDecoder<LIBAV_VER>
|
||||
};
|
||||
|
||||
public:
|
||||
FFmpegVideoDecoder(FlushableTaskQueue* aTaskQueue,
|
||||
MediaDataDecoderCallback* aCallback,
|
||||
const VideoInfo& aConfig,
|
||||
ImageContainer* aImageContainer);
|
||||
FFmpegVideoDecoder(FFmpegLibWrapper* aLib, FlushableTaskQueue* aTaskQueue,
|
||||
MediaDataDecoderCallback* aCallback,
|
||||
const VideoInfo& aConfig,
|
||||
ImageContainer* aImageContainer);
|
||||
virtual ~FFmpegVideoDecoder();
|
||||
|
||||
RefPtr<InitPromise> Init() override;
|
||||
|
@ -5,47 +5,27 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "FFVPXRuntimeLinker.h"
|
||||
#include "FFmpegRuntimeLinker.h"
|
||||
#include "FFmpegLibWrapper.h"
|
||||
#include "FFmpegLog.h"
|
||||
#include "mozilla/Types.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsXPCOMPrivate.h" // for XUL_DLL
|
||||
#include "prmem.h"
|
||||
#include "prlink.h"
|
||||
|
||||
#if defined(XP_WIN)
|
||||
#include "libavcodec/avcodec.h"
|
||||
#include "libavutil/avutil.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla
|
||||
{
|
||||
|
||||
template <int V> class FFmpegDecoderModule
|
||||
{
|
||||
public:
|
||||
static already_AddRefed<PlatformDecoderModule> Create();
|
||||
static already_AddRefed<PlatformDecoderModule> Create(FFmpegLibWrapper*);
|
||||
};
|
||||
|
||||
namespace ffvpx
|
||||
{
|
||||
static FFmpegLibWrapper sFFVPXLib;
|
||||
|
||||
FFVPXRuntimeLinker::LinkStatus FFVPXRuntimeLinker::sLinkStatus =
|
||||
LinkStatus_INIT;
|
||||
|
||||
PRLibrary* FFVPXRuntimeLinker::sLinkedLib = nullptr;
|
||||
PRLibrary* FFVPXRuntimeLinker::sLinkedUtilLib = nullptr;
|
||||
static unsigned (*avcodec_version)() = nullptr;
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define AV_FUNC(func, ver) void (*func)();
|
||||
#define LIBAVCODEC_ALLVERSION
|
||||
#else
|
||||
#define AV_FUNC(func, ver) decltype(func)* func;
|
||||
#endif
|
||||
#include "FFmpegFunctionList.h"
|
||||
#undef AV_FUNC
|
||||
|
||||
static PRLibrary*
|
||||
MozAVLink(const char* aName)
|
||||
{
|
||||
@ -56,7 +36,7 @@ MozAVLink(const char* aName)
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
FFVPXRuntimeLinker::Link()
|
||||
FFVPXRuntimeLinker::Init()
|
||||
{
|
||||
if (sLinkStatus) {
|
||||
return sLinkStatus == LinkStatus_SUCCEEDED;
|
||||
@ -67,7 +47,7 @@ FFVPXRuntimeLinker::Link()
|
||||
// We retrieve the path of the XUL library as this is where mozavcodec and
|
||||
// mozavutil libs are located.
|
||||
char* path =
|
||||
PR_GetLibraryFilePathname(XUL_DLL, (PRFuncPtr)&FFVPXRuntimeLinker::Link);
|
||||
PR_GetLibraryFilePathname(XUL_DLL, (PRFuncPtr)&FFVPXRuntimeLinker::Init);
|
||||
if (!path) {
|
||||
return false;
|
||||
}
|
||||
@ -94,69 +74,29 @@ FFVPXRuntimeLinker::Link()
|
||||
if (!libname) {
|
||||
return false;
|
||||
}
|
||||
sLinkedUtilLib = MozAVLink(libname);
|
||||
sFFVPXLib.mAVUtilLib = MozAVLink(libname);
|
||||
PR_FreeLibraryName(libname);
|
||||
libname = PR_GetLibraryName(rootPath.get(), "mozavcodec");
|
||||
if (libname) {
|
||||
sLinkedLib = MozAVLink(libname);
|
||||
sFFVPXLib.mAVCodecLib = MozAVLink(libname);
|
||||
PR_FreeLibraryName(libname);
|
||||
if (sLinkedLib && sLinkedUtilLib) {
|
||||
if (Bind("mozavcodec")) {
|
||||
sLinkStatus = LinkStatus_SUCCEEDED;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Unlink();
|
||||
|
||||
if (sFFVPXLib.Link()) {
|
||||
sLinkStatus = LinkStatus_SUCCEEDED;
|
||||
return true;
|
||||
}
|
||||
sLinkStatus = LinkStatus_FAILED;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
FFVPXRuntimeLinker::Bind(const char* aLibName)
|
||||
{
|
||||
int version = AV_FUNC_57;
|
||||
|
||||
#define AV_FUNC(func, ver) \
|
||||
if ((ver) & version) { \
|
||||
if (!(func = (decltype(func))PR_FindSymbol(((ver) & AV_FUNC_AVUTIL_MASK) ? sLinkedUtilLib : sLinkedLib, #func))) { \
|
||||
FFMPEG_LOG("Couldn't load function " #func " from %s.", aLibName); \
|
||||
return false; \
|
||||
} \
|
||||
} else { \
|
||||
func = (decltype(func))nullptr; \
|
||||
}
|
||||
#include "FFmpegFunctionList.h"
|
||||
#undef AV_FUNC
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<PlatformDecoderModule>
|
||||
FFVPXRuntimeLinker::CreateDecoderModule()
|
||||
{
|
||||
if (!Link()) {
|
||||
if (!Init()) {
|
||||
return nullptr;
|
||||
}
|
||||
return FFmpegDecoderModule<FFVPX_VERSION>::Create();
|
||||
return FFmpegDecoderModule<FFVPX_VERSION>::Create(&sFFVPXLib);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
FFVPXRuntimeLinker::Unlink()
|
||||
{
|
||||
if (sLinkedUtilLib && sLinkedUtilLib != sLinkedLib) {
|
||||
PR_UnloadLibrary(sLinkedUtilLib);
|
||||
}
|
||||
if (sLinkedLib) {
|
||||
PR_UnloadLibrary(sLinkedLib);
|
||||
sLinkedLib = nullptr;
|
||||
sLinkStatus = LinkStatus_INIT;
|
||||
avcodec_version = nullptr;
|
||||
}
|
||||
sLinkedUtilLib = nullptr;
|
||||
}
|
||||
|
||||
#undef LIBAVCODEC_ALLVERSION
|
||||
} // namespace ffvpx
|
||||
} // namespace mozilla
|
||||
|
@ -9,35 +9,23 @@
|
||||
|
||||
#include "PlatformDecoderModule.h"
|
||||
|
||||
struct PRLibrary;
|
||||
|
||||
namespace mozilla
|
||||
{
|
||||
namespace ffvpx
|
||||
{
|
||||
|
||||
class FFVPXRuntimeLinker
|
||||
{
|
||||
public:
|
||||
static bool Link();
|
||||
static void Unlink();
|
||||
static bool Init();
|
||||
static already_AddRefed<PlatformDecoderModule> CreateDecoderModule();
|
||||
|
||||
private:
|
||||
static PRLibrary* sLinkedLib;
|
||||
static PRLibrary* sLinkedUtilLib;
|
||||
static enum LinkStatus {
|
||||
LinkStatus_INIT = 0,
|
||||
LinkStatus_FAILED,
|
||||
LinkStatus_SUCCEEDED
|
||||
} sLinkStatus;
|
||||
|
||||
static bool Bind(const char* aLibName);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /* __FFVPXRuntimeLinker_h__ */
|
||||
|
22
dom/media/platforms/ffmpeg/moz.build
Normal file
22
dom/media/platforms/ffmpeg/moz.build
Normal file
@ -0,0 +1,22 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# 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/.
|
||||
|
||||
EXPORTS += [
|
||||
'FFmpegRuntimeLinker.h',
|
||||
]
|
||||
|
||||
DIRS += [
|
||||
'libav53',
|
||||
'libav54',
|
||||
'libav55',
|
||||
'ffmpeg57',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'FFmpegRuntimeLinker.cpp',
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
@ -38,23 +38,20 @@ if CONFIG['MOZ_WMF']:
|
||||
if CONFIG['MOZ_EME']:
|
||||
DIRS += ['agnostic/eme']
|
||||
|
||||
if CONFIG['MOZ_FFVPX'] or CONFIG['MOZ_FFMPEG']:
|
||||
# common code to either FFmpeg or FFVPX
|
||||
UNIFIED_SOURCES += [
|
||||
'ffmpeg/FFmpegLibWrapper.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_FFVPX']:
|
||||
DIRS += [
|
||||
'ffmpeg/ffvpx',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_FFMPEG']:
|
||||
EXPORTS += [
|
||||
'ffmpeg/FFmpegRuntimeLinker.h',
|
||||
]
|
||||
UNIFIED_SOURCES += [
|
||||
'ffmpeg/FFmpegRuntimeLinker.cpp',
|
||||
]
|
||||
DIRS += [
|
||||
'ffmpeg/libav53',
|
||||
'ffmpeg/libav54',
|
||||
'ffmpeg/libav55',
|
||||
'ffmpeg/ffmpeg57',
|
||||
'ffmpeg',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_APPLEMEDIA']:
|
||||
|
@ -97,10 +97,6 @@
|
||||
#include "AndroidMediaPluginHost.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_FFMPEG
|
||||
#include "FFmpegRuntimeLinker.h"
|
||||
#endif
|
||||
|
||||
#include "CubebUtils.h"
|
||||
#include "Latency.h"
|
||||
#include "WebAudioUtils.h"
|
||||
@ -394,10 +390,6 @@ nsLayoutStatics::Shutdown()
|
||||
AndroidMediaPluginHost::Shutdown();
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_FFMPEG
|
||||
FFmpegRuntimeLinker::Unlink();
|
||||
#endif
|
||||
|
||||
CubebUtils::ShutdownLibrary();
|
||||
AsyncLatencyLogger::ShutdownLogger();
|
||||
WebAudioUtils::Shutdown();
|
||||
|
Loading…
Reference in New Issue
Block a user