summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-07 21:55:33 +0000
committerscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-07 21:55:33 +0000
commit1276cc16c2ffd7c4dc2ed516791df93b8cefec22 (patch)
tree99bee9a3b0485f953483aef2a84e079f61f176a4 /media
parentbf04734290b2e2453a0a5e25578114aa31447893 (diff)
downloadchromium_src-1276cc16c2ffd7c4dc2ed516791df93b8cefec22.zip
chromium_src-1276cc16c2ffd7c4dc2ed516791df93b8cefec22.tar.gz
chromium_src-1276cc16c2ffd7c4dc2ed516791df93b8cefec22.tar.bz2
Pass in media message loop to VideoRendererBase and enforce calling on the right thread.
As a result VideoDecoder implementations have been updated to expect they get called on the correct thread instead of trampolining. The newly added media::WrapCB() facilitates running callbacks on separate execution stacks to avoid reentrancy in calling code. BUG=162917 Review URL: https://codereview.chromium.org/11428095 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@171854 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r--media/base/bind_to_loop.h7
-rw-r--r--media/filters/decrypting_video_decoder.cc177
-rw-r--r--media/filters/decrypting_video_decoder.h17
-rw-r--r--media/filters/ffmpeg_video_decoder.cc94
-rw-r--r--media/filters/ffmpeg_video_decoder.h17
-rw-r--r--media/filters/ffmpeg_video_decoder_unittest.cc46
-rw-r--r--media/filters/gpu_video_decoder.cc66
-rw-r--r--media/filters/pipeline_integration_test_base.cc1
-rw-r--r--media/filters/video_renderer_base.cc45
-rw-r--r--media/filters/video_renderer_base.h16
-rw-r--r--media/filters/video_renderer_base_unittest.cc19
-rw-r--r--media/tools/player_x11/player_x11.cc1
12 files changed, 185 insertions, 321 deletions
diff --git a/media/base/bind_to_loop.h b/media/base/bind_to_loop.h
index 013389a..5b9c694 100644
--- a/media/base/bind_to_loop.h
+++ b/media/base/bind_to_loop.h
@@ -161,6 +161,13 @@ static base::Callback<T> BindToLoop(
return base::Bind(&internal::TrampolineHelper<T>::Run, loop, cb);
}
+template<typename T>
+static base::Callback<T> BindToCurrentLoop(
+ const base::Callback<T>& cb) {
+ return base::Bind(&internal::TrampolineHelper<T>::Run,
+ base::MessageLoopProxy::current(), cb);
+}
+
} // namespace media
#endif // MEDIA_BASE_BIND_TO_LOOP_H_
diff --git a/media/filters/decrypting_video_decoder.cc b/media/filters/decrypting_video_decoder.cc
index bc42ffa..466ed99 100644
--- a/media/filters/decrypting_video_decoder.cc
+++ b/media/filters/decrypting_video_decoder.cc
@@ -20,9 +20,6 @@
namespace media {
-#define BIND_TO_LOOP(function) \
- media::BindToLoop(message_loop_, base::Bind(function, this))
-
DecryptingVideoDecoder::DecryptingVideoDecoder(
const scoped_refptr<base::MessageLoopProxy>& message_loop,
const RequestDecryptorNotificationCB& request_decryptor_notification_cb)
@@ -38,30 +35,56 @@ void DecryptingVideoDecoder::Initialize(
const scoped_refptr<DemuxerStream>& stream,
const PipelineStatusCB& status_cb,
const StatisticsCB& statistics_cb) {
- if (!message_loop_->BelongsToCurrentThread()) {
- message_loop_->PostTask(FROM_HERE, base::Bind(
- &DecryptingVideoDecoder::DoInitialize, this,
- stream, status_cb, statistics_cb));
+ DVLOG(2) << "Initialize()";
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ DCHECK_EQ(state_, kUninitialized) << state_;
+ DCHECK(stream);
+ init_cb_ = BindToCurrentLoop(status_cb);
+
+ const VideoDecoderConfig& config = stream->video_decoder_config();
+ if (!config.IsValidConfig()) {
+ DLOG(ERROR) << "Invalid video stream config: "
+ << config.AsHumanReadableString();
+ base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_DECODE);
return;
}
- DoInitialize(stream, status_cb, statistics_cb);
+
+ // DecryptingVideoDecoder only accepts potentially encrypted stream.
+ if (!config.is_encrypted()) {
+ base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
+ return;
+ }
+
+ DCHECK(!demuxer_stream_);
+ demuxer_stream_ = stream;
+ statistics_cb_ = statistics_cb;
+
+ state_ = kDecryptorRequested;
+ request_decryptor_notification_cb_.Run(BindToCurrentLoop(base::Bind(
+ &DecryptingVideoDecoder::SetDecryptor, this)));
}
void DecryptingVideoDecoder::Read(const ReadCB& read_cb) {
- // Complete operation asynchronously on different stack of execution as per
- // the API contract of VideoDecoder::Read()
- message_loop_->PostTask(FROM_HERE, base::Bind(
- &DecryptingVideoDecoder::DoRead, this, read_cb));
-}
+ DVLOG(3) << "Read()";
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_;
+ DCHECK(!read_cb.is_null());
+ CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported.";
+ read_cb_ = BindToCurrentLoop(read_cb);
-void DecryptingVideoDecoder::Reset(const base::Closure& closure) {
- if (!message_loop_->BelongsToCurrentThread()) {
- message_loop_->PostTask(FROM_HERE, base::Bind(
- &DecryptingVideoDecoder::Reset, this, closure));
+ // Return empty frames if decoding has finished.
+ if (state_ == kDecodeFinished) {
+ base::ResetAndReturn(&read_cb_).Run(kOk, VideoFrame::CreateEmptyFrame());
return;
}
+ state_ = kPendingDemuxerRead;
+ ReadFromDemuxerStream();
+}
+
+void DecryptingVideoDecoder::Reset(const base::Closure& closure) {
DVLOG(2) << "Reset() - state: " << state_;
+ DCHECK(message_loop_->BelongsToCurrentThread());
DCHECK(state_ == kIdle ||
state_ == kPendingDemuxerRead ||
state_ == kPendingDecode ||
@@ -70,14 +93,14 @@ void DecryptingVideoDecoder::Reset(const base::Closure& closure) {
DCHECK(init_cb_.is_null()); // No Reset() during pending initialization.
DCHECK(reset_cb_.is_null());
- reset_cb_ = closure;
+ reset_cb_ = BindToCurrentLoop(closure);
decryptor_->ResetDecoder(Decryptor::kVideo);
// Reset() cannot complete if the read callback is still pending.
// Defer the resetting process in this case. The |reset_cb_| will be fired
- // after the read callback is fired - see DoDecryptAndDecodeBuffer() and
- // DoDeliverFrame().
+ // after the read callback is fired - see DecryptAndDecodeBuffer() and
+ // DeliverFrame().
if (state_ == kPendingDemuxerRead || state_ == kPendingDecode) {
DCHECK(!read_cb_.is_null());
return;
@@ -94,12 +117,7 @@ void DecryptingVideoDecoder::Reset(const base::Closure& closure) {
}
void DecryptingVideoDecoder::Stop(const base::Closure& closure) {
- if (!message_loop_->BelongsToCurrentThread()) {
- message_loop_->PostTask(FROM_HERE, base::Bind(
- &DecryptingVideoDecoder::Stop, this, closure));
- return;
- }
-
+ DCHECK(message_loop_->BelongsToCurrentThread());
DVLOG(2) << "Stop() - state: " << state_;
// At this point the render thread is likely paused (in WebMediaPlayerImpl's
@@ -123,47 +141,13 @@ void DecryptingVideoDecoder::Stop(const base::Closure& closure) {
if (!reset_cb_.is_null())
base::ResetAndReturn(&reset_cb_).Run();
state_ = kStopped;
- closure.Run();
+ BindToCurrentLoop(closure).Run();
}
DecryptingVideoDecoder::~DecryptingVideoDecoder() {
DCHECK(state_ == kUninitialized || state_ == kStopped) << state_;
}
-void DecryptingVideoDecoder::DoInitialize(
- const scoped_refptr<DemuxerStream>& stream,
- const PipelineStatusCB& status_cb,
- const StatisticsCB& statistics_cb) {
- DVLOG(2) << "DoInitialize()";
- DCHECK(message_loop_->BelongsToCurrentThread());
- DCHECK_EQ(state_, kUninitialized) << state_;
- DCHECK(stream);
-
- const VideoDecoderConfig& config = stream->video_decoder_config();
- if (!config.IsValidConfig()) {
- DLOG(ERROR) << "Invalid video stream config: "
- << config.AsHumanReadableString();
- status_cb.Run(PIPELINE_ERROR_DECODE);
- return;
- }
-
- // DecryptingVideoDecoder only accepts potentially encrypted stream.
- if (!config.is_encrypted()) {
- status_cb.Run(DECODER_ERROR_NOT_SUPPORTED);
- return;
- }
-
- DCHECK(!demuxer_stream_);
- demuxer_stream_ = stream;
- statistics_cb_ = statistics_cb;
-
- init_cb_ = status_cb;
-
- state_ = kDecryptorRequested;
- request_decryptor_notification_cb_.Run(
- BIND_TO_LOOP(&DecryptingVideoDecoder::SetDecryptor));
-}
-
void DecryptingVideoDecoder::SetDecryptor(Decryptor* decryptor) {
DVLOG(2) << "SetDecryptor()";
DCHECK(message_loop_->BelongsToCurrentThread());
@@ -183,8 +167,8 @@ void DecryptingVideoDecoder::SetDecryptor(Decryptor* decryptor) {
state_ = kPendingDecoderInit;
decryptor_->InitializeVideoDecoder(
- scoped_config.Pass(),
- BIND_TO_LOOP(&DecryptingVideoDecoder::FinishInitialization));
+ scoped_config.Pass(), BindToCurrentLoop(base::Bind(
+ &DecryptingVideoDecoder::FinishInitialization, this)));
}
void DecryptingVideoDecoder::FinishInitialization(bool success) {
@@ -205,52 +189,28 @@ void DecryptingVideoDecoder::FinishInitialization(bool success) {
return;
}
- decryptor_->RegisterKeyAddedCB(
- Decryptor::kVideo, BIND_TO_LOOP(&DecryptingVideoDecoder::OnKeyAdded));
+ decryptor_->RegisterKeyAddedCB(Decryptor::kVideo, BindToCurrentLoop(
+ base::Bind(&DecryptingVideoDecoder::OnKeyAdded, this)));
// Success!
state_ = kIdle;
base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
}
-void DecryptingVideoDecoder::DoRead(const ReadCB& read_cb) {
- DVLOG(3) << "DoRead()";
- DCHECK(message_loop_->BelongsToCurrentThread());
- DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_;
- DCHECK(!read_cb.is_null());
- CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported.";
-
- // Return empty frames if decoding has finished.
- if (state_ == kDecodeFinished) {
- read_cb.Run(kOk, VideoFrame::CreateEmptyFrame());
- return;
- }
-
- read_cb_ = read_cb;
- state_ = kPendingDemuxerRead;
- ReadFromDemuxerStream();
-}
-
void DecryptingVideoDecoder::ReadFromDemuxerStream() {
DCHECK(message_loop_->BelongsToCurrentThread());
DCHECK_EQ(state_, kPendingDemuxerRead) << state_;
DCHECK(!read_cb_.is_null());
demuxer_stream_->Read(
- base::Bind(&DecryptingVideoDecoder::DoDecryptAndDecodeBuffer, this));
+ base::Bind(&DecryptingVideoDecoder::DecryptAndDecodeBuffer, this));
}
-void DecryptingVideoDecoder::DoDecryptAndDecodeBuffer(
+void DecryptingVideoDecoder::DecryptAndDecodeBuffer(
DemuxerStream::Status status,
const scoped_refptr<DecoderBuffer>& buffer) {
- if (!message_loop_->BelongsToCurrentThread()) {
- message_loop_->PostTask(FROM_HERE, base::Bind(
- &DecryptingVideoDecoder::DoDecryptAndDecodeBuffer, this,
- status, buffer));
- return;
- }
-
- DVLOG(3) << "DoDecryptAndDecodeBuffer()";
+ DVLOG(3) << "DecryptAndDecodeBuffer()";
+ DCHECK(message_loop_->BelongsToCurrentThread());
if (state_ == kStopped)
return;
@@ -267,7 +227,7 @@ void DecryptingVideoDecoder::DoDecryptAndDecodeBuffer(
}
if (status == DemuxerStream::kAborted) {
- DVLOG(2) << "DoDecryptAndDecodeBuffer() - kAborted";
+ DVLOG(2) << "DecryptAndDecodeBuffer() - kAborted";
state_ = kIdle;
base::ResetAndReturn(&read_cb_).Run(kOk, NULL);
return;
@@ -277,7 +237,7 @@ void DecryptingVideoDecoder::DoDecryptAndDecodeBuffer(
// TODO(xhwang): Add config change support.
// The |state_| is chosen to be kDecodeFinished here to be consistent with
// the implementation of FFmpegVideoDecoder.
- DVLOG(2) << "DoDecryptAndDecodeBuffer() - kConfigChanged";
+ DVLOG(2) << "DecryptAndDecodeBuffer() - kConfigChanged";
state_ = kDecodeFinished;
base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL);
return;
@@ -295,29 +255,16 @@ void DecryptingVideoDecoder::DecodePendingBuffer() {
TRACE_EVENT_ASYNC_BEGIN0(
"eme", "DecryptingVideoDecoder::DecodePendingBuffer", ++trace_id_);
decryptor_->DecryptAndDecodeVideo(
- pending_buffer_to_decode_,
- base::Bind(&DecryptingVideoDecoder::DeliverFrame, this,
- pending_buffer_to_decode_->GetDataSize()));
+ pending_buffer_to_decode_, BindToCurrentLoop(base::Bind(
+ &DecryptingVideoDecoder::DeliverFrame, this,
+ pending_buffer_to_decode_->GetDataSize())));
}
void DecryptingVideoDecoder::DeliverFrame(
int buffer_size,
Decryptor::Status status,
const scoped_refptr<VideoFrame>& frame) {
- // We need to force task post here because the VideoDecodeCB can be executed
- // synchronously in Reset()/Stop(). Instead of using more complicated logic in
- // those function to fix it, why not force task post here to make everything
- // simple and clear?
- message_loop_->PostTask(FROM_HERE, base::Bind(
- &DecryptingVideoDecoder::DoDeliverFrame, this,
- buffer_size, status, frame));
-}
-
-void DecryptingVideoDecoder::DoDeliverFrame(
- int buffer_size,
- Decryptor::Status status,
- const scoped_refptr<VideoFrame>& frame) {
- DVLOG(3) << "DoDeliverFrame() - status: " << status;
+ DVLOG(3) << "DeliverFrame() - status: " << status;
DCHECK(message_loop_->BelongsToCurrentThread());
TRACE_EVENT_ASYNC_END0(
"eme", "DecryptingVideoDecoder::DecodePendingBuffer", trace_id_);
@@ -345,14 +292,14 @@ void DecryptingVideoDecoder::DoDeliverFrame(
DCHECK_EQ(status == Decryptor::kSuccess, frame != NULL);
if (status == Decryptor::kError) {
- DVLOG(2) << "DoDeliverFrame() - kError";
+ DVLOG(2) << "DeliverFrame() - kError";
state_ = kDecodeFinished;
base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL);
return;
}
if (status == Decryptor::kNoKey) {
- DVLOG(2) << "DoDeliverFrame() - kNoKey";
+ DVLOG(2) << "DeliverFrame() - kNoKey";
// Set |pending_buffer_to_decode_| back as we need to try decoding the
// pending buffer again when new key is added to the decryptor.
pending_buffer_to_decode_ = scoped_pending_buffer_to_decode;
@@ -375,7 +322,7 @@ void DecryptingVideoDecoder::DoDeliverFrame(
}
if (status == Decryptor::kNeedMoreData) {
- DVLOG(2) << "DoDeliverFrame() - kNeedMoreData";
+ DVLOG(2) << "DeliverFrame() - kNeedMoreData";
if (scoped_pending_buffer_to_decode->IsEndOfStream()) {
state_ = kDecodeFinished;
base::ResetAndReturn(&read_cb_).Run(
diff --git a/media/filters/decrypting_video_decoder.h b/media/filters/decrypting_video_decoder.h
index 1d8996a..45a8058 100644
--- a/media/filters/decrypting_video_decoder.h
+++ b/media/filters/decrypting_video_decoder.h
@@ -74,25 +74,17 @@ class MEDIA_EXPORT DecryptingVideoDecoder : public VideoDecoder {
kStopped
};
- // Carries out the initialization operation scheduled by Initialize().
- void DoInitialize(const scoped_refptr<DemuxerStream>& stream,
- const PipelineStatusCB& status_cb,
- const StatisticsCB& statistics_cb);
-
// Callback for DecryptorHost::RequestDecryptor().
void SetDecryptor(Decryptor* decryptor);
// Callback for Decryptor::InitializeVideoDecoder().
void FinishInitialization(bool success);
- // Carries out the buffer reading operation scheduled by Read().
- void DoRead(const ReadCB& read_cb);
-
void ReadFromDemuxerStream();
// Callback for DemuxerStream::Read().
- void DoDecryptAndDecodeBuffer(DemuxerStream::Status status,
- const scoped_refptr<DecoderBuffer>& buffer);
+ void DecryptAndDecodeBuffer(DemuxerStream::Status status,
+ const scoped_refptr<DecoderBuffer>& buffer);
void DecodePendingBuffer();
@@ -101,11 +93,6 @@ class MEDIA_EXPORT DecryptingVideoDecoder : public VideoDecoder {
Decryptor::Status status,
const scoped_refptr<VideoFrame>& frame);
- // Carries out the frame delivery operation scheduled by DeliverFrame().
- void DoDeliverFrame(int buffer_size,
- Decryptor::Status status,
- const scoped_refptr<VideoFrame>& frame);
-
// Callback for the |decryptor_| to notify this object that a new key has been
// added.
void OnKeyAdded();
diff --git a/media/filters/ffmpeg_video_decoder.cc b/media/filters/ffmpeg_video_decoder.cc
index 0cc5573..b51ac66 100644
--- a/media/filters/ffmpeg_video_decoder.cc
+++ b/media/filters/ffmpeg_video_decoder.cc
@@ -13,6 +13,7 @@
#include "base/location.h"
#include "base/message_loop_proxy.h"
#include "base/string_number_conversions.h"
+#include "media/base/bind_to_loop.h"
#include "media/base/decoder_buffer.h"
#include "media/base/demuxer_stream.h"
#include "media/base/limits.h"
@@ -133,18 +134,14 @@ static void ReleaseVideoBufferImpl(AVCodecContext* s, AVFrame* frame) {
void FFmpegVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream,
const PipelineStatusCB& status_cb,
const StatisticsCB& statistics_cb) {
- if (!message_loop_->BelongsToCurrentThread()) {
- message_loop_->PostTask(FROM_HERE, base::Bind(
- &FFmpegVideoDecoder::Initialize, this,
- stream, status_cb, statistics_cb));
- return;
- }
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ PipelineStatusCB initialize_cb = BindToCurrentLoop(status_cb);
FFmpegGlue::InitializeFFmpeg();
DCHECK(!demuxer_stream_) << "Already initialized.";
if (!stream) {
- status_cb.Run(PIPELINE_ERROR_DECODE);
+ initialize_cb.Run(PIPELINE_ERROR_DECODE);
return;
}
@@ -152,31 +149,35 @@ void FFmpegVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream,
statistics_cb_ = statistics_cb;
if (!ConfigureDecoder()) {
- status_cb.Run(DECODER_ERROR_NOT_SUPPORTED);
+ initialize_cb.Run(DECODER_ERROR_NOT_SUPPORTED);
return;
}
// Success!
state_ = kNormal;
- status_cb.Run(PIPELINE_OK);
+ initialize_cb.Run(PIPELINE_OK);
}
void FFmpegVideoDecoder::Read(const ReadCB& read_cb) {
- // Complete operation asynchronously on different stack of execution as per
- // the API contract of VideoDecoder::Read()
- message_loop_->PostTask(FROM_HERE, base::Bind(
- &FFmpegVideoDecoder::DoRead, this, read_cb));
-}
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ DCHECK(!read_cb.is_null());
+ CHECK_NE(state_, kUninitialized);
+ CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported.";
+ read_cb_ = BindToCurrentLoop(read_cb);
-void FFmpegVideoDecoder::Reset(const base::Closure& closure) {
- if (!message_loop_->BelongsToCurrentThread()) {
- message_loop_->PostTask(FROM_HERE, base::Bind(
- &FFmpegVideoDecoder::Reset, this, closure));
+ // Return empty frames if decoding has finished.
+ if (state_ == kDecodeFinished) {
+ base::ResetAndReturn(&read_cb_).Run(kOk, VideoFrame::CreateEmptyFrame());
return;
}
+ ReadFromDemuxerStream();
+}
+
+void FFmpegVideoDecoder::Reset(const base::Closure& closure) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
DCHECK(reset_cb_.is_null());
- reset_cb_ = closure;
+ reset_cb_ = BindToCurrentLoop(closure);
if (decryptor_)
decryptor_->CancelDecrypt(Decryptor::kVideo);
@@ -193,21 +194,15 @@ void FFmpegVideoDecoder::DoReset() {
avcodec_flush_buffers(codec_context_);
state_ = kNormal;
- reset_cb_.Run();
- reset_cb_.Reset();
+ base::ResetAndReturn(&reset_cb_).Run();
}
void FFmpegVideoDecoder::Stop(const base::Closure& closure) {
- if (!message_loop_->BelongsToCurrentThread()) {
- message_loop_->PostTask(FROM_HERE, base::Bind(
- &FFmpegVideoDecoder::Stop, this, closure));
- return;
- }
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ base::ScopedClosureRunner runner(BindToCurrentLoop(closure));
- if (state_ == kUninitialized) {
- closure.Run();
+ if (state_ == kUninitialized)
return;
- }
if (decryptor_)
decryptor_->CancelDecrypt(Decryptor::kVideo);
@@ -217,7 +212,6 @@ void FFmpegVideoDecoder::Stop(const base::Closure& closure) {
ReleaseFFmpegResources();
state_ = kUninitialized;
- closure.Run();
}
FFmpegVideoDecoder::~FFmpegVideoDecoder() {
@@ -226,40 +220,19 @@ FFmpegVideoDecoder::~FFmpegVideoDecoder() {
DCHECK(!av_frame_);
}
-void FFmpegVideoDecoder::DoRead(const ReadCB& read_cb) {
- DCHECK(message_loop_->BelongsToCurrentThread());
- DCHECK(!read_cb.is_null());
- CHECK_NE(state_, kUninitialized);
- CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported.";
-
- // Return empty frames if decoding has finished.
- if (state_ == kDecodeFinished) {
- read_cb.Run(kOk, VideoFrame::CreateEmptyFrame());
- return;
- }
-
- read_cb_ = read_cb;
- ReadFromDemuxerStream();
-}
-
void FFmpegVideoDecoder::ReadFromDemuxerStream() {
DCHECK_NE(state_, kUninitialized);
DCHECK_NE(state_, kDecodeFinished);
DCHECK(!read_cb_.is_null());
demuxer_stream_->Read(base::Bind(
- &FFmpegVideoDecoder::DoDecryptOrDecodeBuffer, this));
+ &FFmpegVideoDecoder::DecryptOrDecodeBuffer, this));
}
-void FFmpegVideoDecoder::DoDecryptOrDecodeBuffer(
+void FFmpegVideoDecoder::DecryptOrDecodeBuffer(
DemuxerStream::Status status,
const scoped_refptr<DecoderBuffer>& buffer) {
- if (!message_loop_->BelongsToCurrentThread()) {
- message_loop_->PostTask(FROM_HERE, base::Bind(
- &FFmpegVideoDecoder::DoDecryptOrDecodeBuffer, this, status, buffer));
- return;
- }
-
+ DCHECK(message_loop_->BelongsToCurrentThread());
DCHECK_NE(state_, kDecodeFinished);
DCHECK_EQ(status != DemuxerStream::kOk, !buffer) << status;
@@ -291,10 +264,10 @@ void FFmpegVideoDecoder::DoDecryptOrDecodeBuffer(
DCHECK_EQ(status, DemuxerStream::kOk);
+ // TODO(xhwang): Remove decryptor after DecryptingDemuxerStream is ready.
if (buffer->GetDecryptConfig() && buffer->GetDataSize()) {
- decryptor_->Decrypt(Decryptor::kVideo,
- buffer,
- base::Bind(&FFmpegVideoDecoder::BufferDecrypted, this));
+ decryptor_->Decrypt(Decryptor::kVideo, buffer, BindToCurrentLoop(
+ base::Bind(&FFmpegVideoDecoder::BufferDecrypted, this)));
return;
}
@@ -304,13 +277,6 @@ void FFmpegVideoDecoder::DoDecryptOrDecodeBuffer(
void FFmpegVideoDecoder::BufferDecrypted(
Decryptor::Status decrypt_status,
const scoped_refptr<DecoderBuffer>& buffer) {
- message_loop_->PostTask(FROM_HERE, base::Bind(
- &FFmpegVideoDecoder::DoBufferDecrypted, this, decrypt_status, buffer));
-}
-
-void FFmpegVideoDecoder::DoBufferDecrypted(
- Decryptor::Status decrypt_status,
- const scoped_refptr<DecoderBuffer>& buffer) {
DCHECK(message_loop_->BelongsToCurrentThread());
DCHECK_NE(state_, kDecodeFinished);
diff --git a/media/filters/ffmpeg_video_decoder.h b/media/filters/ffmpeg_video_decoder.h
index e18f88b..4cfc1e6 100644
--- a/media/filters/ffmpeg_video_decoder.h
+++ b/media/filters/ffmpeg_video_decoder.h
@@ -51,16 +51,10 @@ class MEDIA_EXPORT FFmpegVideoDecoder : public VideoDecoder {
kDecodeFinished
};
- // Carries out the reading operation scheduled by Read().
- void DoRead(const ReadCB& read_cb);
-
- // Reads from the demuxer stream.
+ // Reads from the demuxer stream and corresponding read callback.
void ReadFromDemuxerStream();
-
- // Carries out the buffer processing operation scheduled by
- // DecryptOrDecodeBuffer().
- void DoDecryptOrDecodeBuffer(DemuxerStream::Status status,
- const scoped_refptr<DecoderBuffer>& buffer);
+ void DecryptOrDecodeBuffer(DemuxerStream::Status status,
+ const scoped_refptr<DecoderBuffer>& buffer);
// Callback called by the decryptor to deliver decrypted data buffer and
// reporting decrypt status. This callback could be called synchronously or
@@ -68,10 +62,7 @@ class MEDIA_EXPORT FFmpegVideoDecoder : public VideoDecoder {
void BufferDecrypted(Decryptor::Status decrypt_status,
const scoped_refptr<DecoderBuffer>& buffer);
- // Carries out the operation scheduled by BufferDecrypted().
- void DoBufferDecrypted(Decryptor::Status decrypt_status,
- const scoped_refptr<DecoderBuffer>& buffer);
-
+ // Handles decoding an unencrypted encoded buffer.
void DecodeBuffer(const scoped_refptr<DecoderBuffer>& buffer);
bool Decode(const scoped_refptr<DecoderBuffer>& buffer,
scoped_refptr<VideoFrame>* video_frame);
diff --git a/media/filters/ffmpeg_video_decoder_unittest.cc b/media/filters/ffmpeg_video_decoder_unittest.cc
index 309f08f..f356f51 100644
--- a/media/filters/ffmpeg_video_decoder_unittest.cc
+++ b/media/filters/ffmpeg_video_decoder_unittest.cc
@@ -415,8 +415,6 @@ TEST_F(FFmpegVideoDecoderTest, DecodeFrame_DecodeError) {
Read(&status, &video_frame);
EXPECT_EQ(VideoDecoder::kDecodeError, status);
EXPECT_FALSE(video_frame);
-
- message_loop_.RunUntilIdle();
}
// Multi-threaded decoders have different behavior than single-threaded
@@ -496,8 +494,6 @@ TEST_F(FFmpegVideoDecoderTest, DecodeEncryptedFrame_DecryptError) {
Read(&status, &video_frame);
EXPECT_EQ(VideoDecoder::kDecryptError, status);
EXPECT_FALSE(video_frame);
-
- message_loop_.RunUntilIdle();
}
// Test the case that the decryptor has no key to decrypt the encrypted buffer.
@@ -519,8 +515,6 @@ TEST_F(FFmpegVideoDecoderTest, DecodeEncryptedFrame_NoDecryptionKey) {
Read(&status, &video_frame);
EXPECT_EQ(VideoDecoder::kDecryptError, status);
EXPECT_FALSE(video_frame);
-
- message_loop_.RunUntilIdle();
}
// Test the case that the decryptor fails to decrypt the encrypted buffer but
@@ -546,8 +540,6 @@ TEST_F(FFmpegVideoDecoderTest, DecodeEncryptedFrame_CorruptedBufferReturned) {
Read(&status, &video_frame);
EXPECT_EQ(VideoDecoder::kDecodeError, status);
EXPECT_FALSE(video_frame);
-
- message_loop_.RunUntilIdle();
}
// Test resetting when decoder has initialized but not decoded.
@@ -575,16 +567,12 @@ TEST_F(FFmpegVideoDecoderTest, Reset_EndOfStream) {
TEST_F(FFmpegVideoDecoderTest, Reset_DuringPendingRead) {
Initialize();
+ // Request a read on the decoder and ensure the demuxer has been called.
DemuxerStream::ReadCB read_cb;
EXPECT_CALL(*demuxer_, Read(_))
.WillOnce(SaveArg<0>(&read_cb));
-
decoder_->Read(read_cb_);
- message_loop_.RunUntilIdle();
-
- // Make sure the Read() on the decoder triggers a Read() on
- // the demuxer.
- EXPECT_FALSE(read_cb.is_null());
+ ASSERT_FALSE(read_cb.is_null());
// Reset the decoder.
Reset();
@@ -592,27 +580,23 @@ TEST_F(FFmpegVideoDecoderTest, Reset_DuringPendingRead) {
EXPECT_CALL(*this, FrameReady(VideoDecoder::kOk, IsNull()));
read_cb.Run(DemuxerStream::kOk, i_frame_buffer_);
- message_loop_.RunUntilIdle();
}
// Test resetting when there is a pending decrypt on the decryptor.
TEST_F(FFmpegVideoDecoderTest, Reset_DuringPendingDecrypt) {
InitializeWithEncryptedConfig();
+ // Request a read on the decoder and ensure the decryptor has been called.
EXPECT_CALL(*demuxer_, Read(_))
.WillRepeatedly(ReturnBuffer(encrypted_i_frame_buffer_));
EXPECT_CALL(*decryptor_,
Decrypt(Decryptor::kVideo, encrypted_i_frame_buffer_, _))
.WillOnce(SaveArg<2>(&decrypt_cb_));
-
decoder_->Read(read_cb_);
- message_loop_.RunUntilIdle();
- // Make sure the Read() on the decoder triggers a Decrypt() on the decryptor.
- EXPECT_FALSE(decrypt_cb_.is_null());
+ ASSERT_FALSE(decrypt_cb_.is_null());
EXPECT_CALL(*this, FrameReady(VideoDecoder::kOk, IsNull()));
Reset();
- message_loop_.RunUntilIdle();
}
// Test stopping when decoder has initialized but not decoded.
@@ -640,42 +624,35 @@ TEST_F(FFmpegVideoDecoderTest, Stop_EndOfStream) {
TEST_F(FFmpegVideoDecoderTest, Stop_DuringPendingRead) {
Initialize();
+ // Request a read on the decoder and ensure the demuxer has been called.
DemuxerStream::ReadCB read_cb;
EXPECT_CALL(*demuxer_, Read(_))
.WillOnce(SaveArg<0>(&read_cb));
-
decoder_->Read(read_cb_);
- message_loop_.RunUntilIdle();
-
- // Make sure the Read() on the decoder triggers a Read() on the demuxer.
- EXPECT_FALSE(read_cb.is_null());
+ ASSERT_FALSE(read_cb.is_null());
EXPECT_CALL(*this, FrameReady(VideoDecoder::kOk, IsNull()));
Stop();
read_cb.Run(DemuxerStream::kOk, i_frame_buffer_);
- message_loop_.RunUntilIdle();
}
// Test stopping when there is a pending decrypt on the decryptor.
TEST_F(FFmpegVideoDecoderTest, Stop_DuringPendingDecrypt) {
InitializeWithEncryptedConfig();
+ // Request a read on the decoder and ensure the decryptor has been called.
EXPECT_CALL(*demuxer_, Read(_))
.WillRepeatedly(ReturnBuffer(encrypted_i_frame_buffer_));
EXPECT_CALL(*decryptor_,
Decrypt(Decryptor::kVideo, encrypted_i_frame_buffer_, _))
.WillOnce(SaveArg<2>(&decrypt_cb_));
-
decoder_->Read(read_cb_);
- message_loop_.RunUntilIdle();
- // Make sure the Read() on the decoder triggers a Decrypt() on the decryptor.
- EXPECT_FALSE(decrypt_cb_.is_null());
+ ASSERT_FALSE(decrypt_cb_.is_null());
EXPECT_CALL(*this, FrameReady(VideoDecoder::kOk, IsNull()));
Stop();
- message_loop_.RunUntilIdle();
}
// Test aborted read on the demuxer stream.
@@ -698,14 +675,11 @@ TEST_F(FFmpegVideoDecoderTest, AbortPendingRead) {
TEST_F(FFmpegVideoDecoderTest, AbortPendingReadDuringReset) {
Initialize();
+ // Request a read on the decoder and ensure the demuxer has been called.
DemuxerStream::ReadCB read_cb;
-
- // Request a read on the decoder and run the MessageLoop to
- // ensure that the demuxer has been called.
- decoder_->Read(read_cb_);
EXPECT_CALL(*demuxer_, Read(_))
.WillOnce(SaveArg<0>(&read_cb));
- message_loop_.RunUntilIdle();
+ decoder_->Read(read_cb_);
ASSERT_FALSE(read_cb.is_null());
// Reset while there is still an outstanding read on the demuxer.
diff --git a/media/filters/gpu_video_decoder.cc b/media/filters/gpu_video_decoder.cc
index c0f7af4..b05698a 100644
--- a/media/filters/gpu_video_decoder.cc
+++ b/media/filters/gpu_video_decoder.cc
@@ -9,6 +9,7 @@
#include "base/cpu.h"
#include "base/message_loop.h"
#include "base/stl_util.h"
+#include "media/base/bind_to_loop.h"
#include "media/base/decoder_buffer.h"
#include "media/base/demuxer_stream.h"
#include "media/base/pipeline.h"
@@ -66,11 +67,7 @@ GpuVideoDecoder::GpuVideoDecoder(
}
void GpuVideoDecoder::Reset(const base::Closure& closure) {
- if (!gvd_loop_proxy_->BelongsToCurrentThread()) {
- gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
- &GpuVideoDecoder::Reset, this, closure));
- return;
- }
+ DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
if (state_ == kDrainingDecoder) {
gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
@@ -85,53 +82,39 @@ void GpuVideoDecoder::Reset(const base::Closure& closure) {
// Throw away any already-decoded, not-yet-delivered frames.
ready_video_frames_.clear();
+ DCHECK(pending_reset_cb_.is_null());
+ pending_reset_cb_ = BindToCurrentLoop(closure);
+
if (!vda_.get()) {
- closure.Run();
+ base::ResetAndReturn(&pending_reset_cb_).Run();
return;
}
- DCHECK(pending_reset_cb_.is_null());
- DCHECK(!closure.is_null());
-
// VideoRendererBase::Flush() can't complete while it has a pending read to
// us, so we fulfill such a read here.
if (!pending_read_cb_.is_null())
EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame());
- pending_reset_cb_ = closure;
vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
&VideoDecodeAccelerator::Reset, weak_vda_));
}
void GpuVideoDecoder::Stop(const base::Closure& closure) {
- if (!gvd_loop_proxy_->BelongsToCurrentThread()) {
- gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
- &GpuVideoDecoder::Stop, this, closure));
- return;
- }
- if (!vda_.get()) {
- closure.Run();
- return;
- }
- DestroyVDA();
- closure.Run();
+ DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
+ if (vda_.get())
+ DestroyVDA();
+ BindToCurrentLoop(closure).Run();
}
void GpuVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream,
const PipelineStatusCB& orig_status_cb,
const StatisticsCB& statistics_cb) {
- if (!gvd_loop_proxy_->BelongsToCurrentThread()) {
- gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
- &GpuVideoDecoder::Initialize,
- this, stream, orig_status_cb, statistics_cb));
- return;
- }
-
DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
PipelineStatusCB status_cb = CreateUMAReportingPipelineCB(
- "Media.GpuVideoDecoderInitializeStatus", orig_status_cb);
-
+ "Media.GpuVideoDecoderInitializeStatus",
+ BindToCurrentLoop(orig_status_cb));
DCHECK(!demuxer_stream_);
+
if (!stream) {
status_cb.Run(PIPELINE_ERROR_DECODE);
return;
@@ -216,26 +199,22 @@ void GpuVideoDecoder::DestroyVDA() {
}
void GpuVideoDecoder::Read(const ReadCB& read_cb) {
- if (!gvd_loop_proxy_->BelongsToCurrentThread()) {
- gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
- &GpuVideoDecoder::Read, this, read_cb));
- return;
- }
+ DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
+ DCHECK(pending_reset_cb_.is_null());
+ DCHECK(pending_read_cb_.is_null());
+ pending_read_cb_ = BindToCurrentLoop(read_cb);
if (error_occured_) {
- read_cb.Run(kDecodeError, NULL);
+ base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL);
return;
}
if (!vda_.get()) {
- read_cb.Run(kOk, VideoFrame::CreateEmptyFrame());
+ base::ResetAndReturn(&pending_read_cb_).Run(
+ kOk, VideoFrame::CreateEmptyFrame());
return;
}
- DCHECK(pending_reset_cb_.is_null());
- DCHECK(pending_read_cb_.is_null());
- pending_read_cb_ = read_cb;
-
if (!ready_video_frames_.empty()) {
EnqueueFrameAndTriggerFrameDelivery(NULL);
return;
@@ -352,6 +331,7 @@ void GpuVideoDecoder::GetBufferData(int32 id, base::TimeDelta* timestamp,
}
bool GpuVideoDecoder::HasAlpha() const {
+ DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
return true;
}
@@ -460,9 +440,7 @@ void GpuVideoDecoder::EnqueueFrameAndTriggerFrameDelivery(
if (pending_read_cb_.is_null())
return;
- gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
- pending_read_cb_, kOk, ready_video_frames_.front()));
- pending_read_cb_.Reset();
+ base::ResetAndReturn(&pending_read_cb_).Run(kOk, ready_video_frames_.front());
ready_video_frames_.pop_front();
}
diff --git a/media/filters/pipeline_integration_test_base.cc b/media/filters/pipeline_integration_test_base.cc
index 4062a47..1acee61 100644
--- a/media/filters/pipeline_integration_test_base.cc
+++ b/media/filters/pipeline_integration_test_base.cc
@@ -206,6 +206,7 @@ PipelineIntegrationTestBase::CreateFilterCollection(
// Disable frame dropping if hashing is enabled.
renderer_ = new VideoRendererBase(
+ message_loop_.message_loop_proxy(),
base::Bind(&PipelineIntegrationTestBase::OnVideoRendererPaint,
base::Unretained(this)),
base::Bind(&PipelineIntegrationTestBase::OnSetOpaque,
diff --git a/media/filters/video_renderer_base.cc b/media/filters/video_renderer_base.cc
index 8f6bf8a..8c564ad 100644
--- a/media/filters/video_renderer_base.cc
+++ b/media/filters/video_renderer_base.cc
@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/callback_helpers.h"
+#include "base/message_loop.h"
#include "base/threading/platform_thread.h"
#include "media/base/buffers.h"
#include "media/base/limits.h"
@@ -19,10 +20,13 @@ base::TimeDelta VideoRendererBase::kMaxLastFrameDuration() {
return base::TimeDelta::FromMilliseconds(250);
}
-VideoRendererBase::VideoRendererBase(const base::Closure& paint_cb,
- const SetOpaqueCB& set_opaque_cb,
- bool drop_frames)
- : frame_available_(&lock_),
+VideoRendererBase::VideoRendererBase(
+ const scoped_refptr<base::MessageLoopProxy>& message_loop,
+ const base::Closure& paint_cb,
+ const SetOpaqueCB& set_opaque_cb,
+ bool drop_frames)
+ : message_loop_(message_loop),
+ frame_available_(&lock_),
state_(kUninitialized),
thread_(base::kNullThreadHandle),
pending_read_(false),
@@ -36,6 +40,7 @@ VideoRendererBase::VideoRendererBase(const base::Closure& paint_cb,
}
void VideoRendererBase::Play(const base::Closure& callback) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
base::AutoLock auto_lock(lock_);
DCHECK_EQ(kPrerolled, state_);
state_ = kPlaying;
@@ -43,6 +48,7 @@ void VideoRendererBase::Play(const base::Closure& callback) {
}
void VideoRendererBase::Pause(const base::Closure& callback) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
base::AutoLock auto_lock(lock_);
DCHECK(state_ != kUninitialized || state_ == kError);
state_ = kPaused;
@@ -50,19 +56,17 @@ void VideoRendererBase::Pause(const base::Closure& callback) {
}
void VideoRendererBase::Flush(const base::Closure& callback) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
base::AutoLock auto_lock(lock_);
DCHECK_EQ(state_, kPaused);
flush_cb_ = callback;
state_ = kFlushingDecoder;
- // We must unlock here because the callback might run within the Flush()
- // call.
- // TODO: Remove this line when fixing http://crbug.com/125020
- base::AutoUnlock auto_unlock(lock_);
- decoder_->Reset(base::Bind(&VideoRendererBase::OnDecoderFlushDone, this));
+ decoder_->Reset(base::Bind(&VideoRendererBase::OnDecoderResetDone, this));
}
void VideoRendererBase::Stop(const base::Closure& callback) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
if (state_ == kStopped) {
callback.Run();
return;
@@ -94,12 +98,14 @@ void VideoRendererBase::Stop(const base::Closure& callback) {
}
void VideoRendererBase::SetPlaybackRate(float playback_rate) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
base::AutoLock auto_lock(lock_);
playback_rate_ = playback_rate;
}
void VideoRendererBase::Preroll(base::TimeDelta time,
const PipelineStatusCB& cb) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
base::AutoLock auto_lock(lock_);
DCHECK_EQ(state_, kFlushed) << "Must flush prior to prerolling.";
DCHECK(!cb.is_null());
@@ -122,6 +128,7 @@ void VideoRendererBase::Initialize(const scoped_refptr<DemuxerStream>& stream,
const PipelineStatusCB& error_cb,
const TimeDeltaCB& get_time_cb,
const TimeDeltaCB& get_duration_cb) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
base::AutoLock auto_lock(lock_);
DCHECK(stream);
DCHECK(!decoders.empty());
@@ -151,6 +158,7 @@ void VideoRendererBase::Initialize(const scoped_refptr<DemuxerStream>& stream,
void VideoRendererBase::InitializeNextDecoder(
const scoped_refptr<DemuxerStream>& demuxer_stream,
scoped_ptr<VideoDecoderList> decoders) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
lock_.AssertAcquired();
DCHECK(!decoders->empty());
@@ -173,6 +181,7 @@ void VideoRendererBase::OnDecoderInitDone(
const scoped_refptr<DemuxerStream>& demuxer_stream,
scoped_ptr<VideoDecoderList> decoders,
PipelineStatus status) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
base::AutoLock auto_lock(lock_);
if (state_ == kStopped)
@@ -330,7 +339,8 @@ void VideoRendererBase::ThreadMain() {
// Frame dropped: read again.
++frames_dropped;
ready_frames_.pop_front();
- AttemptRead_Locked();
+ message_loop_->PostTask(FROM_HERE, base::Bind(
+ &VideoRendererBase::AttemptRead, this));
}
// Continue waiting for the current paint to finish.
frame_available_.TimedWait(kIdleTimeDelta);
@@ -345,7 +355,8 @@ void VideoRendererBase::ThreadMain() {
DCHECK(!pending_paint_);
DCHECK(!ready_frames_.empty());
SetCurrentFrameToNextReadyFrame();
- AttemptRead_Locked();
+ message_loop_->PostTask(FROM_HERE, base::Bind(
+ &VideoRendererBase::AttemptRead, this));
base::AutoUnlock auto_unlock(lock_);
paint_cb_.Run();
@@ -558,15 +569,21 @@ void VideoRendererBase::AddReadyFrame(const scoped_refptr<VideoFrame>& frame) {
frame_available_.Signal();
}
+void VideoRendererBase::AttemptRead() {
+ base::AutoLock auto_lock(lock_);
+ AttemptRead_Locked();
+}
+
void VideoRendererBase::AttemptRead_Locked() {
+ DCHECK(message_loop_->BelongsToCurrentThread());
lock_.AssertAcquired();
- DCHECK_NE(kEnded, state_);
if (pending_read_ ||
NumFrames_Locked() == limits::kMaxVideoFrames ||
(!ready_frames_.empty() && ready_frames_.back()->IsEndOfStream()) ||
state_ == kFlushingDecoder ||
- state_ == kFlushing) {
+ state_ == kFlushing ||
+ state_ == kEnded) {
return;
}
@@ -574,7 +591,7 @@ void VideoRendererBase::AttemptRead_Locked() {
decoder_->Read(base::Bind(&VideoRendererBase::FrameReady, this));
}
-void VideoRendererBase::OnDecoderFlushDone() {
+void VideoRendererBase::OnDecoderResetDone() {
base::AutoLock auto_lock(lock_);
DCHECK_EQ(kFlushingDecoder, state_);
DCHECK(!pending_read_);
diff --git a/media/filters/video_renderer_base.h b/media/filters/video_renderer_base.h
index 85e6527..eee2905 100644
--- a/media/filters/video_renderer_base.h
+++ b/media/filters/video_renderer_base.h
@@ -17,6 +17,10 @@
#include "media/base/video_frame.h"
#include "media/base/video_renderer.h"
+namespace base {
+class MessageLoopProxy;
+}
+
namespace media {
// VideoRendererBase creates its own thread for the sole purpose of timing frame
@@ -46,7 +50,8 @@ class MEDIA_EXPORT VideoRendererBase
//
// TODO(scherkus): pass the VideoFrame* to this callback and remove
// Get/PutCurrentFrame() http://crbug.com/108435
- VideoRendererBase(const base::Closure& paint_cb,
+ VideoRendererBase(const scoped_refptr<base::MessageLoopProxy>& message_loop,
+ const base::Closure& paint_cb,
const SetOpaqueCB& set_opaque_cb,
bool drop_frames);
@@ -95,10 +100,11 @@ class MEDIA_EXPORT VideoRendererBase
// Helper method that schedules an asynchronous read from the decoder as long
// as there isn't a pending read and we have capacity.
+ void AttemptRead();
void AttemptRead_Locked();
- // Called when the VideoDecoder Flush() completes.
- void OnDecoderFlushDone();
+ // Called when VideoDecoder::Reset() completes.
+ void OnDecoderResetDone();
// Attempts to complete flushing and transition into the flushed state.
void AttemptFlush_Locked();
@@ -133,6 +139,8 @@ class MEDIA_EXPORT VideoRendererBase
scoped_ptr<VideoDecoderList> decoders,
PipelineStatus status);
+ scoped_refptr<base::MessageLoopProxy> message_loop_;
+
// Used for accessing data members.
base::Lock lock_;
@@ -165,7 +173,7 @@ class MEDIA_EXPORT VideoRendererBase
// |
// | Initialize()
// V All frames returned
- // +------[kFlushed]<-----[kFlushing]<--- OnDecoderFlushDone()
+ // +------[kFlushed]<-----[kFlushing]<--- OnDecoderResetDone()
// | | Preroll() or upon ^
// | V got first frame [kFlushingDecoder]
// | [kPrerolling] ^
diff --git a/media/filters/video_renderer_base_unittest.cc b/media/filters/video_renderer_base_unittest.cc
index 90f42fe..42acc01 100644
--- a/media/filters/video_renderer_base_unittest.cc
+++ b/media/filters/video_renderer_base_unittest.cc
@@ -40,6 +40,7 @@ class VideoRendererBaseTest : public ::testing::Test {
: decoder_(new MockVideoDecoder()),
demuxer_stream_(new MockDemuxerStream()) {
renderer_ = new VideoRendererBase(
+ message_loop_.message_loop_proxy(),
base::Bind(&VideoRendererBaseTest::OnPaint, base::Unretained(this)),
base::Bind(&VideoRendererBaseTest::OnSetOpaque, base::Unretained(this)),
true);
@@ -297,14 +298,7 @@ class VideoRendererBaseTest : public ::testing::Test {
}
void FrameRequested(const VideoDecoder::ReadCB& read_cb) {
- // TODO(scherkus): Make VideoRendererBase call on right thread.
- if (&message_loop_ != MessageLoop::current()) {
- message_loop_.PostTask(FROM_HERE, base::Bind(
- &VideoRendererBaseTest::FrameRequested, base::Unretained(this),
- read_cb));
- return;
- }
-
+ DCHECK_EQ(&message_loop_, MessageLoop::current());
CHECK(read_cb_.is_null());
read_cb_ = read_cb;
@@ -319,14 +313,7 @@ class VideoRendererBaseTest : public ::testing::Test {
}
void FlushRequested(const base::Closure& callback) {
- // TODO(scherkus): Make VideoRendererBase call on right thread.
- if (&message_loop_ != MessageLoop::current()) {
- message_loop_.PostTask(FROM_HERE, base::Bind(
- &VideoRendererBaseTest::FlushRequested, base::Unretained(this),
- callback));
- return;
- }
-
+ DCHECK_EQ(&message_loop_, MessageLoop::current());
decode_results_.clear();
if (!read_cb_.is_null()) {
QueueAbortedRead();
diff --git a/media/tools/player_x11/player_x11.cc b/media/tools/player_x11/player_x11.cc
index 5822253..42b891f 100644
--- a/media/tools/player_x11/player_x11.cc
+++ b/media/tools/player_x11/player_x11.cc
@@ -118,6 +118,7 @@ bool InitPipeline(const scoped_refptr<base::MessageLoopProxy>& message_loop,
// Create our video renderer and save a reference to it for painting.
g_video_renderer = new media::VideoRendererBase(
+ message_loop,
base::Bind(&Paint, paint_message_loop, paint_cb),
base::Bind(&SetOpaque),
true);