summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
Diffstat (limited to 'media')
-rw-r--r--media/base/mock_ffmpeg.cc10
-rw-r--r--media/base/mock_ffmpeg.h1
-rw-r--r--media/ffmpeg/ffmpeg_common.cc10
-rw-r--r--media/ffmpeg/ffmpeg_common.h26
-rw-r--r--media/filters/ffmpeg_audio_decoder.cc7
-rw-r--r--media/filters/ffmpeg_demuxer.cc18
-rw-r--r--media/filters/ffmpeg_glue.cc26
-rw-r--r--media/filters/ffmpeg_video_decode_engine.cc16
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;
+ }
}
}