diff options
Diffstat (limited to 'media')
-rw-r--r-- | media/base/mock_ffmpeg.cc | 10 | ||||
-rw-r--r-- | media/base/mock_ffmpeg.h | 1 | ||||
-rw-r--r-- | media/ffmpeg/ffmpeg_common.cc | 10 | ||||
-rw-r--r-- | media/ffmpeg/ffmpeg_common.h | 26 | ||||
-rw-r--r-- | media/filters/ffmpeg_audio_decoder.cc | 7 | ||||
-rw-r--r-- | media/filters/ffmpeg_demuxer.cc | 18 | ||||
-rw-r--r-- | media/filters/ffmpeg_glue.cc | 26 | ||||
-rw-r--r-- | media/filters/ffmpeg_video_decode_engine.cc | 16 |
8 files changed, 60 insertions, 54 deletions
diff --git a/media/base/mock_ffmpeg.cc b/media/base/mock_ffmpeg.cc index 9c30938..0d872068 100644 --- a/media/base/mock_ffmpeg.cc +++ b/media/base/mock_ffmpeg.cc @@ -92,16 +92,6 @@ void av_register_all() { media::MockFFmpeg::get()->AVRegisterAll(); } -int av_lockmgr_register(int (*cb)(void**, enum AVLockOp)) { - media::MockFFmpeg* mock = media::MockFFmpeg::get(); - // Here |mock| may be NULL when this function is called from ~FFmpegGlue(). - if (mock != NULL) { - return media::MockFFmpeg::get()->AVRegisterLockManager(cb); - } else { - return 0; - } -} - AVCodec* avcodec_find_decoder(enum CodecID id) { return media::MockFFmpeg::get()->AVCodecFindDecoder(id); } diff --git a/media/base/mock_ffmpeg.h b/media/base/mock_ffmpeg.h index 836e02b..a4a9f1a 100644 --- a/media/base/mock_ffmpeg.h +++ b/media/base/mock_ffmpeg.h @@ -21,7 +21,6 @@ class MockFFmpeg { MOCK_METHOD0(AVCodecInit, void()); MOCK_METHOD1(AVRegisterProtocol, int(URLProtocol* protocol)); MOCK_METHOD0(AVRegisterAll, void()); - MOCK_METHOD1(AVRegisterLockManager, int(int (*cb)(void**, enum AVLockOp))); MOCK_METHOD1(AVCodecFindDecoder, AVCodec*(enum CodecID id)); MOCK_METHOD2(AVCodecOpen, int(AVCodecContext* avctx, AVCodec* codec)); diff --git a/media/ffmpeg/ffmpeg_common.cc b/media/ffmpeg/ffmpeg_common.cc index 08228fd..5100b31 100644 --- a/media/ffmpeg/ffmpeg_common.cc +++ b/media/ffmpeg/ffmpeg_common.cc @@ -6,6 +6,16 @@ namespace media { +FFmpegLock::FFmpegLock() { +} + +FFmpegLock::~FFmpegLock() { +} + +Lock& FFmpegLock::lock() { + return lock_; +} + namespace mime_type { const char kFFmpegAudio[] = "audio/x-ffmpeg"; diff --git a/media/ffmpeg/ffmpeg_common.h b/media/ffmpeg/ffmpeg_common.h index 4b60046..9be245f 100644 --- a/media/ffmpeg/ffmpeg_common.h +++ b/media/ffmpeg/ffmpeg_common.h @@ -19,14 +19,34 @@ extern "C" { // Temporarily disable possible loss of data warning. // TODO(scherkus): fix and upstream the compiler warnings. MSVC_PUSH_DISABLE_WARNING(4244); -#include "third_party/ffmpeg/source/patched-ffmpeg-mt/libavcodec/avcodec.h" -#include "third_party/ffmpeg/source/patched-ffmpeg-mt/libavformat/avformat.h" -#include "third_party/ffmpeg/source/patched-ffmpeg-mt/libavutil/log.h" +#include "third_party/ffmpeg/include/libavcodec/avcodec.h" +#include "third_party/ffmpeg/include/libavformat/avformat.h" +#include "third_party/ffmpeg/include/libavutil/log.h" MSVC_POP_WARNING(); } // extern "C" namespace media { +// FFmpegLock is used to serialize calls to avcodec_open(), avcodec_close(), +// and av_find_stream_info() for an entire process because for whatever reason +// it does Very Bad Things to other FFmpeg instances. +// +// TODO(scherkus): track down and upstream a fix to FFmpeg, if possible. +class FFmpegLock : public Singleton<FFmpegLock> { + public: + Lock& lock(); + + private: + // Only allow Singleton to create and delete FFmpegLock. + friend struct DefaultSingletonTraits<FFmpegLock>; + FFmpegLock(); + virtual ~FFmpegLock(); + + Lock lock_; + DISALLOW_COPY_AND_ASSIGN(FFmpegLock); +}; + + // Wraps FFmpeg's av_free() in a class that can be passed as a template argument // to scoped_ptr_malloc. class ScopedPtrAVFree { diff --git a/media/filters/ffmpeg_audio_decoder.cc b/media/filters/ffmpeg_audio_decoder.cc index 82e36f2..b7a828b 100644 --- a/media/filters/ffmpeg_audio_decoder.cc +++ b/media/filters/ffmpeg_audio_decoder.cc @@ -61,8 +61,11 @@ void FFmpegAudioDecoder::DoInitialize(DemuxerStream* demuxer_stream, // Serialize calls to avcodec_open(). AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); - if (!codec || avcodec_open(codec_context_, codec) < 0) { - return; + { + AutoLock auto_lock(FFmpegLock::get()->lock()); + if (!codec || avcodec_open(codec_context_, codec) < 0) { + return; + } } // When calling avcodec_find_decoder(), |codec_context_| might be altered by diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc index 94ce91c..2e020ba 100644 --- a/media/filters/ffmpeg_demuxer.cc +++ b/media/filters/ffmpeg_demuxer.cc @@ -235,6 +235,7 @@ FFmpegDemuxer::~FFmpegDemuxer() { // in the decoder filters. By reaching this point, all filters should have // stopped, so this is the only safe place to do the global clean up. // TODO(hclam): close the codecs in the corresponding decoders. + AutoLock auto_lock(FFmpegLock::get()->lock()); if (!format_context_) return; @@ -396,12 +397,17 @@ void FFmpegDemuxer::InitializeTask(DataSource* data_source, DCHECK(context); format_context_ = context; - // Fully initialize AVFormatContext by parsing the stream a little. - result = av_find_stream_info(format_context_); - if (result < 0) { - host()->SetError(DEMUXER_ERROR_COULD_NOT_PARSE); - callback->Run(); - return; + // Serialize calls to av_find_stream_info(). + { + AutoLock auto_lock(FFmpegLock::get()->lock()); + + // Fully initialize AVFormatContext by parsing the stream a little. + result = av_find_stream_info(format_context_); + if (result < 0) { + host()->SetError(DEMUXER_ERROR_COULD_NOT_PARSE); + callback->Run(); + return; + } } // Create demuxer streams for all supported streams. diff --git a/media/filters/ffmpeg_glue.cc b/media/filters/ffmpeg_glue.cc index a920f58..0b2ee4b 100644 --- a/media/filters/ffmpeg_glue.cc +++ b/media/filters/ffmpeg_glue.cc @@ -81,30 +81,6 @@ int CloseContext(URLContext* h) { return 0; } -int LockManagerOperation(void** lock, enum AVLockOp op) { - switch (op) { - case AV_LOCK_CREATE: - *lock = new Lock(); - if (!*lock) - return 1; - return 0; - - case AV_LOCK_OBTAIN: - static_cast<Lock*>(*lock)->Acquire(); - return 0; - - case AV_LOCK_RELEASE: - static_cast<Lock*>(*lock)->Release(); - return 0; - - case AV_LOCK_DESTROY: - delete static_cast<Lock*>(*lock); - *lock = NULL; - return 0; - } - return 1; -} - } // namespace //------------------------------------------------------------------------------ @@ -131,14 +107,12 @@ FFmpegGlue::FFmpegGlue() { // Register our protocol glue code with FFmpeg. avcodec_init(); av_register_protocol(&kFFmpegURLProtocol); - av_lockmgr_register(&LockManagerOperation); // Now register the rest of FFmpeg. av_register_all(); } FFmpegGlue::~FFmpegGlue() { - av_lockmgr_register(NULL); } std::string FFmpegGlue::AddProtocol(FFmpegURLProtocol* protocol) { diff --git a/media/filters/ffmpeg_video_decode_engine.cc b/media/filters/ffmpeg_video_decode_engine.cc index 92523fa2..b6adec2 100644 --- a/media/filters/ffmpeg_video_decode_engine.cc +++ b/media/filters/ffmpeg_video_decode_engine.cc @@ -47,13 +47,17 @@ void FFmpegVideoDecodeEngine::Initialize(AVStream* stream, Task* done_cb) { codec_context_->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK; codec_context_->error_recognition = FF_ER_CAREFUL; + // Serialize calls to avcodec_open(). AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); - if (codec && - avcodec_thread_init(codec_context_, kDecodeThreads) >= 0 && - avcodec_open(codec_context_, codec) >= 0) { - state_ = kNormal; - } else { - state_ = kError; + { + AutoLock auto_lock(FFmpegLock::get()->lock()); + if (codec && + avcodec_thread_init(codec_context_, kDecodeThreads) >= 0 && + avcodec_open(codec_context_, codec) >= 0) { + state_ = kNormal; + } else { + state_ = kError; + } } } |