diff options
author | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-12-07 21:55:33 +0000 |
---|---|---|
committer | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-12-07 21:55:33 +0000 |
commit | 1276cc16c2ffd7c4dc2ed516791df93b8cefec22 (patch) | |
tree | 99bee9a3b0485f953483aef2a84e079f61f176a4 /media | |
parent | bf04734290b2e2453a0a5e25578114aa31447893 (diff) | |
download | chromium_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.h | 7 | ||||
-rw-r--r-- | media/filters/decrypting_video_decoder.cc | 177 | ||||
-rw-r--r-- | media/filters/decrypting_video_decoder.h | 17 | ||||
-rw-r--r-- | media/filters/ffmpeg_video_decoder.cc | 94 | ||||
-rw-r--r-- | media/filters/ffmpeg_video_decoder.h | 17 | ||||
-rw-r--r-- | media/filters/ffmpeg_video_decoder_unittest.cc | 46 | ||||
-rw-r--r-- | media/filters/gpu_video_decoder.cc | 66 | ||||
-rw-r--r-- | media/filters/pipeline_integration_test_base.cc | 1 | ||||
-rw-r--r-- | media/filters/video_renderer_base.cc | 45 | ||||
-rw-r--r-- | media/filters/video_renderer_base.h | 16 | ||||
-rw-r--r-- | media/filters/video_renderer_base_unittest.cc | 19 | ||||
-rw-r--r-- | media/tools/player_x11/player_x11.cc | 1 |
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); |