diff options
author | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-18 22:03:48 +0000 |
---|---|---|
committer | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-18 22:03:48 +0000 |
commit | c9802d4f24fcee643d992038b9d4658e640c2867 (patch) | |
tree | bf7b7b029c253243b10b5e301b417c5efc81d4bf /media/filters | |
parent | 13b33a4f0c3f3f4c9e29cf222d59335c19dda7f9 (diff) | |
download | chromium_src-c9802d4f24fcee643d992038b9d4658e640c2867.zip chromium_src-c9802d4f24fcee643d992038b9d4658e640c2867.tar.gz chromium_src-c9802d4f24fcee643d992038b9d4658e640c2867.tar.bz2 |
Revert 194993 "Remove reference counting from media::VideoDecode..."
> Remove reference counting from media::VideoDecoder and friends.
>
> In addition:
> * VideoRenderer is now passed a list of decoders via constructor instead of Initialize()
> * WebMediaPlayerImpl's FilterCollection is now built in one shot instead of incrementally
>
> BUG=173313
>
> Review URL: https://codereview.chromium.org/12989009
TBR=scherkus@chromium.org
Review URL: https://codereview.chromium.org/14320005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@195013 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/filters')
20 files changed, 236 insertions, 321 deletions
diff --git a/media/filters/decrypting_video_decoder.cc b/media/filters/decrypting_video_decoder.cc index 6179fd7..6fe6e69 100644 --- a/media/filters/decrypting_video_decoder.cc +++ b/media/filters/decrypting_video_decoder.cc @@ -24,7 +24,6 @@ DecryptingVideoDecoder::DecryptingVideoDecoder( const scoped_refptr<base::MessageLoopProxy>& message_loop, const SetDecryptorReadyCB& set_decryptor_ready_cb) : message_loop_(message_loop), - weak_factory_(this), state_(kUninitialized), set_decryptor_ready_cb_(set_decryptor_ready_cb), decryptor_(NULL), @@ -41,7 +40,6 @@ void DecryptingVideoDecoder::Initialize( DCHECK_EQ(state_, kUninitialized) << state_; DCHECK(stream); init_cb_ = BindToCurrentLoop(status_cb); - weak_this_ = weak_factory_.GetWeakPtr(); const VideoDecoderConfig& config = stream->video_decoder_config(); if (!config.IsValidConfig()) { @@ -63,7 +61,7 @@ void DecryptingVideoDecoder::Initialize( state_ = kDecryptorRequested; set_decryptor_ready_cb_.Run(BindToCurrentLoop(base::Bind( - &DecryptingVideoDecoder::SetDecryptor, weak_this_))); + &DecryptingVideoDecoder::SetDecryptor, this))); } void DecryptingVideoDecoder::Read(const ReadCB& read_cb) { @@ -168,7 +166,7 @@ void DecryptingVideoDecoder::SetDecryptor(Decryptor* decryptor) { state_ = kPendingDecoderInit; decryptor_->InitializeVideoDecoder( demuxer_stream_->video_decoder_config(), BindToCurrentLoop(base::Bind( - &DecryptingVideoDecoder::FinishInitialization, weak_this_))); + &DecryptingVideoDecoder::FinishInitialization, this))); } void DecryptingVideoDecoder::FinishInitialization(bool success) { @@ -190,7 +188,7 @@ void DecryptingVideoDecoder::FinishInitialization(bool success) { } decryptor_->RegisterNewKeyCB(Decryptor::kVideo, BindToCurrentLoop( - base::Bind(&DecryptingVideoDecoder::OnKeyAdded, weak_this_))); + base::Bind(&DecryptingVideoDecoder::OnKeyAdded, this))); // Success! state_ = kIdle; @@ -232,7 +230,7 @@ void DecryptingVideoDecoder::ReadFromDemuxerStream() { DCHECK(!read_cb_.is_null()); demuxer_stream_->Read( - base::Bind(&DecryptingVideoDecoder::DecryptAndDecodeBuffer, weak_this_)); + base::Bind(&DecryptingVideoDecoder::DecryptAndDecodeBuffer, this)); } void DecryptingVideoDecoder::DecryptAndDecodeBuffer( @@ -255,7 +253,7 @@ void DecryptingVideoDecoder::DecryptAndDecodeBuffer( decryptor_->DeinitializeDecoder(Decryptor::kVideo); decryptor_->InitializeVideoDecoder( demuxer_stream_->video_decoder_config(), BindToCurrentLoop(base::Bind( - &DecryptingVideoDecoder::FinishConfigChange, weak_this_))); + &DecryptingVideoDecoder::FinishConfigChange, this))); return; } @@ -291,7 +289,7 @@ void DecryptingVideoDecoder::DecodePendingBuffer() { decryptor_->DecryptAndDecodeVideo( pending_buffer_to_decode_, BindToCurrentLoop(base::Bind( - &DecryptingVideoDecoder::DeliverFrame, weak_this_, buffer_size))); + &DecryptingVideoDecoder::DeliverFrame, this, buffer_size))); } void DecryptingVideoDecoder::DeliverFrame( diff --git a/media/filters/decrypting_video_decoder.h b/media/filters/decrypting_video_decoder.h index eeb4210..9da57a1 100644 --- a/media/filters/decrypting_video_decoder.h +++ b/media/filters/decrypting_video_decoder.h @@ -6,7 +6,7 @@ #define MEDIA_FILTERS_DECRYPTING_VIDEO_DECODER_H_ #include "base/callback.h" -#include "base/memory/weak_ptr.h" +#include "base/memory/ref_counted.h" #include "media/base/decryptor.h" #include "media/base/demuxer_stream.h" #include "media/base/video_decoder.h" @@ -34,7 +34,6 @@ class MEDIA_EXPORT DecryptingVideoDecoder : public VideoDecoder { DecryptingVideoDecoder( const scoped_refptr<base::MessageLoopProxy>& message_loop, const SetDecryptorReadyCB& set_decryptor_ready_cb); - virtual ~DecryptingVideoDecoder(); // VideoDecoder implementation. virtual void Initialize(const scoped_refptr<DemuxerStream>& stream, @@ -44,6 +43,9 @@ class MEDIA_EXPORT DecryptingVideoDecoder : public VideoDecoder { virtual void Reset(const base::Closure& closure) OVERRIDE; virtual void Stop(const base::Closure& closure) OVERRIDE; + protected: + virtual ~DecryptingVideoDecoder(); + private: // For a detailed state diagram please see this link: http://goo.gl/8jAok // TODO(xhwang): Add a ASCII state diagram in this file after this class @@ -94,8 +96,6 @@ class MEDIA_EXPORT DecryptingVideoDecoder : public VideoDecoder { void DoStop(); scoped_refptr<base::MessageLoopProxy> message_loop_; - base::WeakPtrFactory<DecryptingVideoDecoder> weak_factory_; - base::WeakPtr<DecryptingVideoDecoder> weak_this_; State state_; diff --git a/media/filters/decrypting_video_decoder_unittest.cc b/media/filters/decrypting_video_decoder_unittest.cc index 140206f..9d8462e 100644 --- a/media/filters/decrypting_video_decoder_unittest.cc +++ b/media/filters/decrypting_video_decoder_unittest.cc @@ -235,7 +235,7 @@ class DecryptingVideoDecoderTest : public testing::Test { const scoped_refptr<VideoFrame>&)); MessageLoop message_loop_; - scoped_ptr<DecryptingVideoDecoder> decoder_; + scoped_refptr<DecryptingVideoDecoder> decoder_; scoped_ptr<StrictMock<MockDecryptor> > decryptor_; scoped_refptr<StrictMock<MockDemuxerStream> > demuxer_; MockStatisticsCB statistics_cb_; diff --git a/media/filters/ffmpeg_video_decoder.cc b/media/filters/ffmpeg_video_decoder.cc index 105199f..9dd4058 100644 --- a/media/filters/ffmpeg_video_decoder.cc +++ b/media/filters/ffmpeg_video_decoder.cc @@ -58,7 +58,6 @@ static int GetThreadCount(CodecID codec_id) { FFmpegVideoDecoder::FFmpegVideoDecoder( const scoped_refptr<base::MessageLoopProxy>& message_loop) : message_loop_(message_loop), - weak_factory_(this), state_(kUninitialized), codec_context_(NULL), av_frame_(NULL) { @@ -135,7 +134,6 @@ void FFmpegVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream, const StatisticsCB& statistics_cb) { DCHECK(message_loop_->BelongsToCurrentThread()); PipelineStatusCB initialize_cb = BindToCurrentLoop(status_cb); - weak_this_ = weak_factory_.GetWeakPtr(); FFmpegGlue::InitializeFFmpeg(); DCHECK(!demuxer_stream_) << "Already initialized."; @@ -226,8 +224,7 @@ void FFmpegVideoDecoder::ReturnFrameOrReadFromDemuxerStream() { DCHECK_NE(state_, kUninitialized); DCHECK_NE(state_, kDecodeFinished); DCHECK(!read_cb_.is_null()); - demuxer_stream_->Read(base::Bind( - &FFmpegVideoDecoder::BufferReady, weak_this_)); + demuxer_stream_->Read(base::Bind(&FFmpegVideoDecoder::BufferReady, this)); } void FFmpegVideoDecoder::BufferReady( diff --git a/media/filters/ffmpeg_video_decoder.h b/media/filters/ffmpeg_video_decoder.h index de83814..4c6629e 100644 --- a/media/filters/ffmpeg_video_decoder.h +++ b/media/filters/ffmpeg_video_decoder.h @@ -8,7 +8,7 @@ #include <list> #include "base/callback.h" -#include "base/memory/weak_ptr.h" +#include "base/memory/ref_counted.h" #include "media/base/demuxer_stream.h" #include "media/base/video_decoder.h" @@ -27,7 +27,6 @@ class MEDIA_EXPORT FFmpegVideoDecoder : public VideoDecoder { public: explicit FFmpegVideoDecoder( const scoped_refptr<base::MessageLoopProxy>& message_loop); - virtual ~FFmpegVideoDecoder(); // VideoDecoder implementation. virtual void Initialize(const scoped_refptr<DemuxerStream>& stream, @@ -42,6 +41,9 @@ class MEDIA_EXPORT FFmpegVideoDecoder : public VideoDecoder { // documentation inside FFmpeg. int GetVideoBuffer(AVCodecContext *codec_context, AVFrame* frame); + protected: + virtual ~FFmpegVideoDecoder(); + private: enum DecoderState { kUninitialized, @@ -72,8 +74,6 @@ class MEDIA_EXPORT FFmpegVideoDecoder : public VideoDecoder { void DoReset(); scoped_refptr<base::MessageLoopProxy> message_loop_; - base::WeakPtrFactory<FFmpegVideoDecoder> weak_factory_; - base::WeakPtr<FFmpegVideoDecoder> weak_this_; DecoderState state_; diff --git a/media/filters/ffmpeg_video_decoder_unittest.cc b/media/filters/ffmpeg_video_decoder_unittest.cc index 863c317..1aa1de33 100644 --- a/media/filters/ffmpeg_video_decoder_unittest.cc +++ b/media/filters/ffmpeg_video_decoder_unittest.cc @@ -50,12 +50,14 @@ ACTION_P(ReturnBuffer, buffer) { class FFmpegVideoDecoderTest : public testing::Test { public: FFmpegVideoDecoderTest() - : decoder_(new FFmpegVideoDecoder(message_loop_.message_loop_proxy())), + : decoder_(NULL), demuxer_(new StrictMock<MockDemuxerStream>()), read_cb_(base::Bind(&FFmpegVideoDecoderTest::FrameReady, base::Unretained(this))) { FFmpegGlue::InitializeFFmpeg(); + decoder_ = new FFmpegVideoDecoder(message_loop_.message_loop_proxy()); + // Initialize various test buffers. frame_buffer_.reset(new uint8[kCodedSize.GetArea()]); end_of_stream_buffer_ = DecoderBuffer::CreateEOSBuffer(); @@ -199,7 +201,7 @@ class FFmpegVideoDecoderTest : public testing::Test { const scoped_refptr<VideoFrame>&)); MessageLoop message_loop_; - scoped_ptr<FFmpegVideoDecoder> decoder_; + scoped_refptr<FFmpegVideoDecoder> decoder_; scoped_refptr<StrictMock<MockDemuxerStream> > demuxer_; MockStatisticsCB statistics_cb_; VideoDecoderConfig config_; diff --git a/media/filters/gpu_video_decoder.cc b/media/filters/gpu_video_decoder.cc index 555164e..a2fc662 100644 --- a/media/filters/gpu_video_decoder.cc +++ b/media/filters/gpu_video_decoder.cc @@ -9,7 +9,6 @@ #include "base/cpu.h" #include "base/message_loop.h" #include "base/stl_util.h" -#include "base/task_runner_util.h" #include "media/base/bind_to_loop.h" #include "media/base/decoder_buffer.h" #include "media/base/demuxer_stream.h" @@ -19,112 +18,6 @@ namespace media { -// Proxies calls to a VideoDecodeAccelerator::Client from the calling thread to -// the client's thread. -// -// TODO(scherkus): VDAClientProxy should hold onto GpuVideoDecoder::Factories -// and take care of some of the work that GpuVideoDecoder does to minimize -// thread hopping. See following for discussion: -// -// https://codereview.chromium.org/12989009/diff/27035/media/filters/gpu_video_decoder.cc#newcode23 -class VDAClientProxy - : public base::RefCountedThreadSafe<VDAClientProxy>, - public VideoDecodeAccelerator::Client { - public: - explicit VDAClientProxy(VideoDecodeAccelerator::Client* client); - - // Detaches the proxy. |weak_client_| will no longer be called and can be - // safely deleted. Any pending/future calls will be discarded. - // - // Must be called on |client_loop_|. - void Detach(); - - // VideoDecodeAccelerator::Client implementation. - virtual void NotifyInitializeDone() OVERRIDE; - virtual void ProvidePictureBuffers(uint32 count, - const gfx::Size& size, - uint32 texture_target) OVERRIDE; - virtual void DismissPictureBuffer(int32 id) OVERRIDE; - virtual void PictureReady(const media::Picture& picture) OVERRIDE; - virtual void NotifyEndOfBitstreamBuffer(int32 id) OVERRIDE; - virtual void NotifyFlushDone() OVERRIDE; - virtual void NotifyResetDone() OVERRIDE; - virtual void NotifyError(media::VideoDecodeAccelerator::Error error) OVERRIDE; - - private: - friend class base::RefCountedThreadSafe<VDAClientProxy>; - virtual ~VDAClientProxy(); - - scoped_refptr<base::MessageLoopProxy> client_loop_; - - // Weak pointers are used to invalidate tasks posted to |client_loop_| after - // Detach() has been called. - base::WeakPtrFactory<VideoDecodeAccelerator::Client> weak_client_factory_; - base::WeakPtr<VideoDecodeAccelerator::Client> weak_client_; - - DISALLOW_COPY_AND_ASSIGN(VDAClientProxy); -}; - -VDAClientProxy::VDAClientProxy(VideoDecodeAccelerator::Client* client) - : client_loop_(base::MessageLoopProxy::current()), - weak_client_factory_(client), - weak_client_(weak_client_factory_.GetWeakPtr()) { - DCHECK(weak_client_); -} - -VDAClientProxy::~VDAClientProxy() {} - -void VDAClientProxy::Detach() { - DCHECK(client_loop_->BelongsToCurrentThread()); - DCHECK(weak_client_) << "Detach() already called"; - weak_client_factory_.InvalidateWeakPtrs(); -} - -void VDAClientProxy::NotifyInitializeDone() { - client_loop_->PostTask(FROM_HERE, base::Bind( - &VideoDecodeAccelerator::Client::NotifyInitializeDone, weak_client_)); -} - -void VDAClientProxy::ProvidePictureBuffers(uint32 count, - const gfx::Size& size, - uint32 texture_target) { - client_loop_->PostTask(FROM_HERE, base::Bind( - &VideoDecodeAccelerator::Client::ProvidePictureBuffers, weak_client_, - count, size, texture_target)); -} - -void VDAClientProxy::DismissPictureBuffer(int32 id) { - client_loop_->PostTask(FROM_HERE, base::Bind( - &VideoDecodeAccelerator::Client::DismissPictureBuffer, weak_client_, id)); -} - -void VDAClientProxy::PictureReady(const media::Picture& picture) { - client_loop_->PostTask(FROM_HERE, base::Bind( - &VideoDecodeAccelerator::Client::PictureReady, weak_client_, picture)); -} - -void VDAClientProxy::NotifyEndOfBitstreamBuffer(int32 id) { - client_loop_->PostTask(FROM_HERE, base::Bind( - &VideoDecodeAccelerator::Client::NotifyEndOfBitstreamBuffer, weak_client_, - id)); -} - -void VDAClientProxy::NotifyFlushDone() { - client_loop_->PostTask(FROM_HERE, base::Bind( - &VideoDecodeAccelerator::Client::NotifyFlushDone, weak_client_)); -} - -void VDAClientProxy::NotifyResetDone() { - client_loop_->PostTask(FROM_HERE, base::Bind( - &VideoDecodeAccelerator::Client::NotifyResetDone, weak_client_)); -} - -void VDAClientProxy::NotifyError(media::VideoDecodeAccelerator::Error error) { - client_loop_->PostTask(FROM_HERE, base::Bind( - &VideoDecodeAccelerator::Client::NotifyError, weak_client_, error)); -} - - // Maximum number of concurrent VDA::Decode() operations GVD will maintain. // Higher values allow better pipelining in the GPU, but also require more // resources. @@ -161,7 +54,6 @@ GpuVideoDecoder::GpuVideoDecoder( const scoped_refptr<base::MessageLoopProxy>& message_loop, const scoped_refptr<Factories>& factories) : gvd_loop_proxy_(message_loop), - weak_factory_(this), vda_loop_proxy_(factories->GetMessageLoop()), factories_(factories), state_(kNormal), @@ -179,7 +71,7 @@ void GpuVideoDecoder::Reset(const base::Closure& closure) { if (state_ == kDrainingDecoder && !factories_->IsAborted()) { gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( - &GpuVideoDecoder::Reset, weak_this_, closure)); + &GpuVideoDecoder::Reset, this, closure)); // NOTE: if we're deferring Reset() until a Flush() completes, return // queued pictures to the VDA so they can be used to finish that Flush(). if (pending_read_cb_.is_null()) @@ -221,8 +113,6 @@ void GpuVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream, const PipelineStatusCB& orig_status_cb, const StatisticsCB& statistics_cb) { DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); - weak_this_ = weak_factory_.GetWeakPtr(); - PipelineStatusCB status_cb = CreateUMAReportingPipelineCB( "Media.GpuVideoDecoderInitializeStatus", BindToCurrentLoop(orig_status_cb)); @@ -260,9 +150,8 @@ void GpuVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream, } } - client_proxy_ = new VDAClientProxy(this); VideoDecodeAccelerator* vda = - factories_->CreateVideoDecodeAccelerator(config.profile(), client_proxy_); + factories_->CreateVideoDecodeAccelerator(config.profile(), this); if (!vda) { status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); return; @@ -275,21 +164,17 @@ void GpuVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream, statistics_cb_ = statistics_cb; DVLOG(1) << "GpuVideoDecoder::Initialize() succeeded."; - PostTaskAndReplyWithResult( - vda_loop_proxy_, FROM_HERE, - base::Bind(&VideoDecodeAccelerator::AsWeakPtr, base::Unretained(vda)), - base::Bind(&GpuVideoDecoder::SetVDA, weak_this_, status_cb, vda)); + vda_loop_proxy_->PostTaskAndReply( + FROM_HERE, + base::Bind(&GpuVideoDecoder::SetVDA, this, vda), + base::Bind(status_cb, PIPELINE_OK)); } -void GpuVideoDecoder::SetVDA( - const PipelineStatusCB& status_cb, - VideoDecodeAccelerator* vda, - base::WeakPtr<VideoDecodeAccelerator> weak_vda) { - DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); +void GpuVideoDecoder::SetVDA(VideoDecodeAccelerator* vda) { + DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); DCHECK(!vda_.get()); vda_.reset(vda); - weak_vda_ = weak_vda; - status_cb.Run(PIPELINE_OK); + weak_vda_ = vda->AsWeakPtr(); } void GpuVideoDecoder::DestroyTextures() { @@ -301,25 +186,17 @@ void GpuVideoDecoder::DestroyTextures() { picture_buffers_in_decoder_.clear(); } -static void DestroyVDAWithClientProxy( - const scoped_refptr<VDAClientProxy>& client_proxy, - base::WeakPtr<VideoDecodeAccelerator> weak_vda) { - if (weak_vda) { - weak_vda->Destroy(); - DCHECK(!weak_vda); // Check VDA::Destroy() contract. - } -} - void GpuVideoDecoder::DestroyVDA() { DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); - - // |client_proxy| must stay alive until |weak_vda_| has been destroyed. - vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( - &DestroyVDAWithClientProxy, client_proxy_, weak_vda_)); - VideoDecodeAccelerator* vda ALLOW_UNUSED = vda_.release(); - client_proxy_->Detach(); - client_proxy_ = NULL; + // Tricky: |this| needs to stay alive until after VDA::Destroy is actually + // called, not just posted, so we take an artificial ref to |this| and release + // it as |reply| after VDA::Destroy() returns. + AddRef(); + vda_loop_proxy_->PostTaskAndReply( + FROM_HERE, + base::Bind(&VideoDecodeAccelerator::Destroy, weak_vda_), + base::Bind(&GpuVideoDecoder::Release, this)); DestroyTextures(); } @@ -367,9 +244,13 @@ bool GpuVideoDecoder::CanMoreDecodeWorkBeDone() { void GpuVideoDecoder::RequestBufferDecode( DemuxerStream::Status status, const scoped_refptr<DecoderBuffer>& buffer) { - DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); DCHECK_EQ(status != DemuxerStream::kOk, !buffer) << status; + if (!gvd_loop_proxy_->BelongsToCurrentThread()) { + gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( + &GpuVideoDecoder::RequestBufferDecode, this, status, buffer)); + return; + } demuxer_read_in_progress_ = false; if (status != DemuxerStream::kOk) { @@ -424,7 +305,7 @@ void GpuVideoDecoder::RequestBufferDecode( if (CanMoreDecodeWorkBeDone()) { // Force post here to prevent reentrancy into DemuxerStream. gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( - &GpuVideoDecoder::EnsureDemuxOrDecode, weak_this_)); + &GpuVideoDecoder::EnsureDemuxOrDecode, this)); } } @@ -477,7 +358,12 @@ void GpuVideoDecoder::NotifyInitializeDone() { void GpuVideoDecoder::ProvidePictureBuffers(uint32 count, const gfx::Size& size, uint32 texture_target) { - DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); + if (!gvd_loop_proxy_->BelongsToCurrentThread()) { + gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( + &GpuVideoDecoder::ProvidePictureBuffers, this, count, size, + texture_target)); + return; + } std::vector<uint32> texture_ids; decoder_texture_target_ = texture_target; @@ -507,8 +393,11 @@ void GpuVideoDecoder::ProvidePictureBuffers(uint32 count, } void GpuVideoDecoder::DismissPictureBuffer(int32 id) { - DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); - + if (!gvd_loop_proxy_->BelongsToCurrentThread()) { + gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( + &GpuVideoDecoder::DismissPictureBuffer, this, id)); + return; + } std::map<int32, PictureBuffer>::iterator it = picture_buffers_in_decoder_.find(id); if (it == picture_buffers_in_decoder_.end()) { @@ -520,8 +409,11 @@ void GpuVideoDecoder::DismissPictureBuffer(int32 id) { } void GpuVideoDecoder::PictureReady(const media::Picture& picture) { - DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); - + if (!gvd_loop_proxy_->BelongsToCurrentThread()) { + gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( + &GpuVideoDecoder::PictureReady, this, picture)); + return; + } std::map<int32, PictureBuffer>::iterator it = picture_buffers_in_decoder_.find(picture.picture_buffer_id()); if (it == picture_buffers_in_decoder_.end()) { @@ -545,9 +437,8 @@ void GpuVideoDecoder::PictureReady(const media::Picture& picture) { base::Bind(&Factories::ReadPixels, factories_, pb.texture_id(), decoder_texture_target_, gfx::Size(visible_rect.width(), visible_rect.height())), - BindToCurrentLoop(base::Bind( - &GpuVideoDecoder::ReusePictureBuffer, weak_this_, - picture.picture_buffer_id())))); + base::Bind(&GpuVideoDecoder::ReusePictureBuffer, this, + picture.picture_buffer_id()))); CHECK_GT(available_pictures_, 0); available_pictures_--; @@ -576,7 +467,11 @@ void GpuVideoDecoder::EnqueueFrameAndTriggerFrameDelivery( } void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id) { - DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); + if (!gvd_loop_proxy_->BelongsToCurrentThread()) { + gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( + &GpuVideoDecoder::ReusePictureBuffer, this, picture_buffer_id)); + return; + } CHECK_GE(available_pictures_, 0); available_pictures_++; @@ -609,7 +504,11 @@ void GpuVideoDecoder::PutSHM(SHMBuffer* shm_buffer) { } void GpuVideoDecoder::NotifyEndOfBitstreamBuffer(int32 id) { - DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); + if (!gvd_loop_proxy_->BelongsToCurrentThread()) { + gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( + &GpuVideoDecoder::NotifyEndOfBitstreamBuffer, this, id)); + return; + } std::map<int32, BufferPair>::iterator it = bitstream_buffers_in_decoder_.find(id); @@ -664,18 +563,27 @@ void GpuVideoDecoder::EnsureDemuxOrDecode() { demuxer_read_in_progress_ = true; demuxer_stream_->Read(base::Bind( - &GpuVideoDecoder::RequestBufferDecode, weak_this_)); + &GpuVideoDecoder::RequestBufferDecode, this)); } void GpuVideoDecoder::NotifyFlushDone() { - DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); + if (!gvd_loop_proxy_->BelongsToCurrentThread()) { + gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( + &GpuVideoDecoder::NotifyFlushDone, this)); + return; + } DCHECK_EQ(state_, kDrainingDecoder); state_ = kDecoderDrained; EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); } void GpuVideoDecoder::NotifyResetDone() { - DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); + if (!gvd_loop_proxy_->BelongsToCurrentThread()) { + gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( + &GpuVideoDecoder::NotifyResetDone, this)); + return; + } + DCHECK(ready_video_frames_.empty()); // This needs to happen after the Reset() on vda_ is done to ensure pictures @@ -690,7 +598,11 @@ void GpuVideoDecoder::NotifyResetDone() { } void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { - DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); + if (!gvd_loop_proxy_->BelongsToCurrentThread()) { + gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( + &GpuVideoDecoder::NotifyError, this, error)); + return; + } if (!vda_.get()) return; diff --git a/media/filters/gpu_video_decoder.h b/media/filters/gpu_video_decoder.h index c2defb3..6acc2de 100644 --- a/media/filters/gpu_video_decoder.h +++ b/media/filters/gpu_video_decoder.h @@ -10,7 +10,6 @@ #include <utility> #include <vector> -#include "base/memory/weak_ptr.h" #include "media/base/pipeline_status.h" #include "media/base/demuxer_stream.h" #include "media/base/video_decoder.h" @@ -28,7 +27,6 @@ class SkBitmap; namespace media { class DecoderBuffer; -class VDAClientProxy; // GPU-accelerated video decoder implementation. Relies on // AcceleratedVideoDecoderMsg_Decode and friends. @@ -66,7 +64,7 @@ class MEDIA_EXPORT GpuVideoDecoder // attempts at factory operations virtual void Abort() = 0; - // Returns true if Abort() has been called. + // Returns true if Abort has been called. virtual bool IsAborted() = 0; protected: @@ -136,10 +134,9 @@ class MEDIA_EXPORT GpuVideoDecoder void GetBufferData(int32 id, base::TimeDelta* timetamp, gfx::Rect* visible_rect, gfx::Size* natural_size); - // Sets |vda_| and |weak_vda_| on the GVD thread and runs |status_cb|. - void SetVDA(const PipelineStatusCB& status_cb, - VideoDecodeAccelerator* vda, - base::WeakPtr<VideoDecodeAccelerator> weak_vda); + // Set |vda_| and |weak_vda_| on the VDA thread (in practice the render + // thread). + void SetVDA(VideoDecodeAccelerator* vda); // Call VDA::Destroy() on |vda_loop_proxy_| ensuring that |this| outlives the // Destroy() call. @@ -170,8 +167,6 @@ class MEDIA_EXPORT GpuVideoDecoder // MessageLoop on which to fire callbacks and trampoline calls to this class // if they arrive on other loops. scoped_refptr<base::MessageLoopProxy> gvd_loop_proxy_; - base::WeakPtrFactory<GpuVideoDecoder> weak_factory_; - base::WeakPtr<GpuVideoDecoder> weak_this_; // Message loop on which to makes all calls to vda_. (beware this loop may be // paused during the Pause/Flush/Stop dance PipelineImpl::Stop() goes @@ -180,12 +175,8 @@ class MEDIA_EXPORT GpuVideoDecoder scoped_refptr<Factories> factories_; - // Proxies calls from |vda_| to |gvd_loop_proxy_| and used to safely detach - // during shutdown. - scoped_refptr<VDAClientProxy> client_proxy_; - // Populated during Initialize() via SetVDA() (on success) and unchanged - // until an error occurs. + // until an error occurs scoped_ptr<VideoDecodeAccelerator> vda_; // Used to post tasks from the GVD thread to the VDA thread safely. base::WeakPtr<VideoDecodeAccelerator> weak_vda_; diff --git a/media/filters/pipeline_integration_test_base.cc b/media/filters/pipeline_integration_test_base.cc index 0be9861..1b650d5 100644 --- a/media/filters/pipeline_integration_test_base.cc +++ b/media/filters/pipeline_integration_test_base.cc @@ -223,17 +223,16 @@ PipelineIntegrationTestBase::CreateFilterCollection( Decryptor* decryptor) { scoped_ptr<FilterCollection> collection(new FilterCollection()); collection->SetDemuxer(demuxer); - - ScopedVector<VideoDecoder> video_decoders; - video_decoders.push_back( - new FFmpegVideoDecoder(message_loop_.message_loop_proxy())); - video_decoders.push_back( - new VpxVideoDecoder(message_loop_.message_loop_proxy())); + scoped_refptr<VideoDecoder> video_decoder = new FFmpegVideoDecoder( + message_loop_.message_loop_proxy()); + scoped_refptr<VpxVideoDecoder> vpx_decoder = new VpxVideoDecoder( + message_loop_.message_loop_proxy()); + collection->GetVideoDecoders()->push_back(video_decoder); + collection->GetVideoDecoders()->push_back(vpx_decoder); // Disable frame dropping if hashing is enabled. scoped_ptr<VideoRenderer> renderer(new VideoRendererBase( message_loop_.message_loop_proxy(), - video_decoders.Pass(), base::Bind(&PipelineIntegrationTestBase::SetDecryptor, base::Unretained(this), decryptor), base::Bind(&PipelineIntegrationTestBase::OnVideoRendererPaint, diff --git a/media/filters/video_decoder_selector.cc b/media/filters/video_decoder_selector.cc index f1aebb26..b1f186f 100644 --- a/media/filters/video_decoder_selector.cc +++ b/media/filters/video_decoder_selector.cc @@ -19,10 +19,10 @@ namespace media { VideoDecoderSelector::VideoDecoderSelector( const scoped_refptr<base::MessageLoopProxy>& message_loop, - ScopedVector<VideoDecoder> decoders, + const VideoDecoderList& decoders, const SetDecryptorReadyCB& set_decryptor_ready_cb) : message_loop_(message_loop), - decoders_(decoders.Pass()), + decoders_(decoders), set_decryptor_ready_cb_(set_decryptor_ready_cb), ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { } @@ -43,8 +43,7 @@ void VideoDecoderSelector::SelectVideoDecoder( const VideoDecoderConfig& config = stream->video_decoder_config(); if (!config.IsValidConfig()) { DLOG(ERROR) << "Invalid video stream config."; - base::ResetAndReturn(&select_decoder_cb_).Run( - scoped_ptr<VideoDecoder>(), NULL); + base::ResetAndReturn(&select_decoder_cb_).Run(NULL, NULL); return; } @@ -52,19 +51,24 @@ void VideoDecoderSelector::SelectVideoDecoder( statistics_cb_ = statistics_cb; if (!config.is_encrypted()) { - InitializeDecoder(decoders_.begin()); + if (decoders_.empty()) { + DLOG(ERROR) << "No video decoder can be used to decode the input stream."; + base::ResetAndReturn(&select_decoder_cb_).Run(NULL, NULL); + return; + } + + InitializeNextDecoder(); return; } // This could happen if Encrypted Media Extension (EME) is not enabled. if (set_decryptor_ready_cb_.is_null()) { - base::ResetAndReturn(&select_decoder_cb_).Run( - scoped_ptr<VideoDecoder>(), NULL); + base::ResetAndReturn(&select_decoder_cb_).Run(NULL, NULL); return; } - video_decoder_.reset(new DecryptingVideoDecoder( - message_loop_, set_decryptor_ready_cb_)); + video_decoder_ = new DecryptingVideoDecoder(message_loop_, + set_decryptor_ready_cb_); video_decoder_->Initialize( input_stream_, @@ -79,7 +83,16 @@ void VideoDecoderSelector::DecryptingVideoDecoderInitDone( DCHECK(message_loop_->BelongsToCurrentThread()); if (status == PIPELINE_OK) { - base::ResetAndReturn(&select_decoder_cb_).Run(video_decoder_.Pass(), NULL); + decoders_.clear(); + base::ResetAndReturn(&select_decoder_cb_).Run(video_decoder_, NULL); + return; + } + + video_decoder_ = NULL; + + if (decoders_.empty()) { + DLOG(ERROR) << "No video decoder can be used to decode the input stream."; + base::ResetAndReturn(&select_decoder_cb_).Run(NULL, NULL); return; } @@ -99,48 +112,42 @@ void VideoDecoderSelector::DecryptingDemuxerStreamInitDone( if (status != PIPELINE_OK) { decrypted_stream_ = NULL; - base::ResetAndReturn(&select_decoder_cb_).Run( - scoped_ptr<VideoDecoder>(), NULL); + base::ResetAndReturn(&select_decoder_cb_).Run(NULL, NULL); return; } DCHECK(!decrypted_stream_->video_decoder_config().is_encrypted()); input_stream_ = decrypted_stream_; - InitializeDecoder(decoders_.begin()); + InitializeNextDecoder(); } -void VideoDecoderSelector::InitializeDecoder( - ScopedVector<VideoDecoder>::iterator iter) { +void VideoDecoderSelector::InitializeNextDecoder() { DCHECK(message_loop_->BelongsToCurrentThread()); - - if (iter == decoders_.end()) { - base::ResetAndReturn(&select_decoder_cb_).Run( - scoped_ptr<VideoDecoder>(), NULL); - return; - } - - (*iter)->Initialize( - input_stream_, - BindToCurrentLoop(base::Bind( - &VideoDecoderSelector::DecoderInitDone, - weak_ptr_factory_.GetWeakPtr(), - iter)), - statistics_cb_); + DCHECK(!decoders_.empty()); + + video_decoder_ = decoders_.front(); + decoders_.pop_front(); + DCHECK(video_decoder_); + video_decoder_->Initialize(input_stream_, + BindToCurrentLoop(base::Bind( + &VideoDecoderSelector::DecoderInitDone, + weak_ptr_factory_.GetWeakPtr())), + statistics_cb_); } -void VideoDecoderSelector::DecoderInitDone( - ScopedVector<VideoDecoder>::iterator iter, PipelineStatus status) { +void VideoDecoderSelector::DecoderInitDone(PipelineStatus status) { DCHECK(message_loop_->BelongsToCurrentThread()); if (status != PIPELINE_OK) { - InitializeDecoder(++iter); + if (!decoders_.empty()) + InitializeNextDecoder(); + else + base::ResetAndReturn(&select_decoder_cb_).Run(NULL, NULL); return; } - scoped_ptr<VideoDecoder> video_decoder(*iter); - decoders_.weak_erase(iter); - - base::ResetAndReturn(&select_decoder_cb_).Run(video_decoder.Pass(), + decoders_.clear(); + base::ResetAndReturn(&select_decoder_cb_).Run(video_decoder_, decrypted_stream_); } diff --git a/media/filters/video_decoder_selector.h b/media/filters/video_decoder_selector.h index 81a3110..826bbf8 100644 --- a/media/filters/video_decoder_selector.h +++ b/media/filters/video_decoder_selector.h @@ -5,9 +5,10 @@ #ifndef MEDIA_FILTERS_VIDEO_DECODER_SELECTOR_H_ #define MEDIA_FILTERS_VIDEO_DECODER_SELECTOR_H_ +#include <list> + #include "base/callback.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_vector.h" #include "base/memory/weak_ptr.h" #include "media/base/decryptor.h" #include "media/base/demuxer_stream.h" @@ -28,6 +29,8 @@ class Decryptor; // encrypted, a DecryptingDemuxerStream may also be created. class MEDIA_EXPORT VideoDecoderSelector { public: + typedef std::list<scoped_refptr<VideoDecoder> > VideoDecoderList; + // Indicates completion of VideoDecoder selection. // - First parameter: The initialized VideoDecoder. If it's set to NULL, then // VideoDecoder initialization failed. @@ -38,16 +41,14 @@ class MEDIA_EXPORT VideoDecoderSelector { // The caller should call DecryptingDemuxerStream::Reset() before // calling VideoDecoder::Reset() to release any pending decryption or read. typedef base::Callback< - void(scoped_ptr<VideoDecoder>, + void(const scoped_refptr<VideoDecoder>&, const scoped_refptr<DecryptingDemuxerStream>&)> SelectDecoderCB; - // |decoders| contains the VideoDecoders to use when initializing. - // // |set_decryptor_ready_cb| is optional. If |set_decryptor_ready_cb| is null, // no decryptor will be available to perform decryption. VideoDecoderSelector( const scoped_refptr<base::MessageLoopProxy>& message_loop, - ScopedVector<VideoDecoder> decoders, + const VideoDecoderList& decoders, const SetDecryptorReadyCB& set_decryptor_ready_cb); ~VideoDecoderSelector(); @@ -61,19 +62,18 @@ class MEDIA_EXPORT VideoDecoderSelector { private: void DecryptingVideoDecoderInitDone(PipelineStatus status); void DecryptingDemuxerStreamInitDone(PipelineStatus status); - void InitializeDecoder(ScopedVector<VideoDecoder>::iterator iter); - void DecoderInitDone(ScopedVector<VideoDecoder>::iterator iter, - PipelineStatus status); + void InitializeNextDecoder(); + void DecoderInitDone(PipelineStatus status); scoped_refptr<base::MessageLoopProxy> message_loop_; - ScopedVector<VideoDecoder> decoders_; + VideoDecoderList decoders_; SetDecryptorReadyCB set_decryptor_ready_cb_; scoped_refptr<DemuxerStream> input_stream_; StatisticsCB statistics_cb_; SelectDecoderCB select_decoder_cb_; - scoped_ptr<VideoDecoder> video_decoder_; + scoped_refptr<VideoDecoder> video_decoder_; scoped_refptr<DecryptingDemuxerStream> decrypted_stream_; base::WeakPtrFactory<VideoDecoderSelector> weak_ptr_factory_; diff --git a/media/filters/video_decoder_selector_unittest.cc b/media/filters/video_decoder_selector_unittest.cc index 764a0ba..8086c62 100644 --- a/media/filters/video_decoder_selector_unittest.cc +++ b/media/filters/video_decoder_selector_unittest.cc @@ -18,6 +18,7 @@ using ::testing::NiceMock; using ::testing::NotNull; using ::testing::Return; using ::testing::ReturnRef; +using ::testing::SaveArg; using ::testing::StrictMock; namespace media { @@ -51,17 +52,16 @@ class VideoDecoderSelectorTest : public ::testing::Test { EXPECT_CALL(*demuxer_stream_, type()) .WillRepeatedly(Return(DemuxerStream::VIDEO)); + } + ~VideoDecoderSelectorTest() { EXPECT_CALL(*decoder_1_, Stop(_)) .WillRepeatedly(RunClosure<0>()); EXPECT_CALL(*decoder_2_, Stop(_)) .WillRepeatedly(RunClosure<0>()); - } - ~VideoDecoderSelectorTest() { - if (selected_decoder_) { + if (selected_decoder_) selected_decoder_->Stop(NewExpectedClosure()); - } message_loop_.RunUntilIdle(); } @@ -69,16 +69,9 @@ class VideoDecoderSelectorTest : public ::testing::Test { MOCK_METHOD1(OnStatistics, void(const PipelineStatistics&)); MOCK_METHOD1(SetDecryptorReadyCallback, void(const media::DecryptorReadyCB&)); MOCK_METHOD2(OnDecoderSelected, - void(VideoDecoder*, + void(const scoped_refptr<VideoDecoder>&, const scoped_refptr<DecryptingDemuxerStream>&)); - void MockOnDecoderSelected( - scoped_ptr<VideoDecoder> decoder, - const scoped_refptr<DecryptingDemuxerStream>& stream) { - OnDecoderSelected(decoder.get(), stream); - selected_decoder_ = decoder.Pass(); - } - void UseClearStream() { EXPECT_CALL(*demuxer_stream_, video_decoder_config()) .WillRepeatedly(ReturnRef(clear_video_config_)); @@ -111,12 +104,12 @@ class VideoDecoderSelectorTest : public ::testing::Test { } DCHECK_GE(all_decoders_.size(), static_cast<size_t>(num_decoders)); - all_decoders_.erase( - all_decoders_.begin() + num_decoders, all_decoders_.end()); + VideoDecoderSelector::VideoDecoderList decoders( + all_decoders_.begin(), all_decoders_.begin() + num_decoders); decoder_selector_.reset(new VideoDecoderSelector( message_loop_.message_loop_proxy(), - all_decoders_.Pass(), + decoders, set_decryptor_ready_cb)); } @@ -125,7 +118,7 @@ class VideoDecoderSelectorTest : public ::testing::Test { demuxer_stream_, base::Bind(&VideoDecoderSelectorTest::OnStatistics, base::Unretained(this)), - base::Bind(&VideoDecoderSelectorTest::MockOnDecoderSelected, + base::Bind(&VideoDecoderSelectorTest::OnDecoderSelected, base::Unretained(this))); message_loop_.RunUntilIdle(); } @@ -138,11 +131,11 @@ class VideoDecoderSelectorTest : public ::testing::Test { // Use NiceMock since we don't care about most of calls on the decryptor, e.g. // RegisterNewKeyCB(). scoped_ptr<NiceMock<MockDecryptor> > decryptor_; - StrictMock<MockVideoDecoder>* decoder_1_; - StrictMock<MockVideoDecoder>* decoder_2_; - ScopedVector<VideoDecoder> all_decoders_; + scoped_refptr<StrictMock<MockVideoDecoder> > decoder_1_; + scoped_refptr<StrictMock<MockVideoDecoder> > decoder_2_; + std::vector<scoped_refptr<VideoDecoder> > all_decoders_; - scoped_ptr<VideoDecoder> selected_decoder_; + scoped_refptr<VideoDecoder> selected_decoder_; MessageLoop message_loop_; @@ -169,7 +162,9 @@ TEST_F(VideoDecoderSelectorTest, ClearStream_NoDecryptor_OneClearDecoder) { EXPECT_CALL(*decoder_1_, Initialize(_, _, _)) .WillOnce(RunCallback<1>(PIPELINE_OK)); - EXPECT_CALL(*this, OnDecoderSelected(decoder_1_, IsNull())); + EXPECT_CALL(*this, OnDecoderSelected(scoped_refptr<VideoDecoder>(decoder_1_), + IsNull())) + .WillOnce(SaveArg<0>(&selected_decoder_)); SelectDecoder(); } @@ -184,7 +179,9 @@ TEST_F(VideoDecoderSelectorTest, ClearStream_NoDecryptor_MultipleClearDecoder) { .WillOnce(RunCallback<1>(DECODER_ERROR_NOT_SUPPORTED)); EXPECT_CALL(*decoder_2_, Initialize(_, _, _)) .WillOnce(RunCallback<1>(PIPELINE_OK)); - EXPECT_CALL(*this, OnDecoderSelected(decoder_2_, IsNull())); + EXPECT_CALL(*this, OnDecoderSelected(scoped_refptr<VideoDecoder>(decoder_2_), + IsNull())) + .WillOnce(SaveArg<0>(&selected_decoder_)); SelectDecoder(); } @@ -197,7 +194,9 @@ TEST_F(VideoDecoderSelectorTest, ClearStream_HasDecryptor) { EXPECT_CALL(*decoder_1_, Initialize(_, _, _)) .WillOnce(RunCallback<1>(PIPELINE_OK)); - EXPECT_CALL(*this, OnDecoderSelected(decoder_1_, IsNull())); + EXPECT_CALL(*this, OnDecoderSelected(scoped_refptr<VideoDecoder>(decoder_1_), + IsNull())) + .WillOnce(SaveArg<0>(&selected_decoder_)); SelectDecoder(); } @@ -231,7 +230,9 @@ TEST_F(VideoDecoderSelectorTest, EncryptedStream_DecryptOnly_OneClearDecoder) { EXPECT_CALL(*decoder_1_, Initialize(_, _, _)) .WillOnce(RunCallback<1>(PIPELINE_OK)); - EXPECT_CALL(*this, OnDecoderSelected(decoder_1_, NotNull())); + EXPECT_CALL(*this, OnDecoderSelected(scoped_refptr<VideoDecoder>(decoder_1_), + NotNull())) + .WillOnce(SaveArg<0>(&selected_decoder_)); SelectDecoder(); } @@ -248,7 +249,9 @@ TEST_F(VideoDecoderSelectorTest, .WillOnce(RunCallback<1>(DECODER_ERROR_NOT_SUPPORTED)); EXPECT_CALL(*decoder_2_, Initialize(_, _, _)) .WillOnce(RunCallback<1>(PIPELINE_OK)); - EXPECT_CALL(*this, OnDecoderSelected(decoder_2_, NotNull())); + EXPECT_CALL(*this, OnDecoderSelected(scoped_refptr<VideoDecoder>(decoder_2_), + NotNull())) + .WillOnce(SaveArg<0>(&selected_decoder_)); SelectDecoder(); } @@ -260,7 +263,8 @@ TEST_F(VideoDecoderSelectorTest, EncryptedStream_DecryptAndDecode) { UseEncryptedStream(); InitializeDecoderSelector(kDecryptAndDecode, 1); - EXPECT_CALL(*this, OnDecoderSelected(NotNull(), IsNull())); + EXPECT_CALL(*this, OnDecoderSelected(NotNull(), IsNull())) + .WillOnce(SaveArg<0>(&selected_decoder_)); SelectDecoder(); } diff --git a/media/filters/video_frame_stream.cc b/media/filters/video_frame_stream.cc index 8a788da..72ee20d 100644 --- a/media/filters/video_frame_stream.cc +++ b/media/filters/video_frame_stream.cc @@ -19,13 +19,11 @@ namespace media { VideoFrameStream::VideoFrameStream( const scoped_refptr<base::MessageLoopProxy>& message_loop, - ScopedVector<VideoDecoder> decoders, const SetDecryptorReadyCB& set_decryptor_ready_cb) : message_loop_(message_loop), weak_factory_(this), state_(UNINITIALIZED), - decoder_selector_( - message_loop_, decoders.Pass(), set_decryptor_ready_cb) { + set_decryptor_ready_cb_(set_decryptor_ready_cb) { } VideoFrameStream::~VideoFrameStream() { @@ -33,6 +31,7 @@ VideoFrameStream::~VideoFrameStream() { } void VideoFrameStream::Initialize(const scoped_refptr<DemuxerStream>& stream, + const VideoDecoderList& decoders, const StatisticsCB& statistics_cb, const InitCB& init_cb) { DCHECK(message_loop_->BelongsToCurrentThread()); @@ -45,8 +44,20 @@ void VideoFrameStream::Initialize(const scoped_refptr<DemuxerStream>& stream, init_cb_ = init_cb; stream_ = stream; - decoder_selector_.SelectVideoDecoder(this, statistics_cb, base::Bind( - &VideoFrameStream::OnDecoderSelected, weak_this_)); + scoped_ptr<VideoDecoderSelector> decoder_selector( + new VideoDecoderSelector(message_loop_, + decoders, + set_decryptor_ready_cb_)); + + // To avoid calling |decoder_selector| methods and passing ownership of + // |decoder_selector| in the same line. + VideoDecoderSelector* decoder_selector_ptr = decoder_selector.get(); + + decoder_selector_ptr->SelectVideoDecoder( + this, + statistics_cb, + base::Bind(&VideoFrameStream::OnDecoderSelected, weak_this_, + base::Passed(&decoder_selector))); } void VideoFrameStream::ReadFrame(const VideoDecoder::ReadCB& read_cb) { @@ -117,7 +128,7 @@ void VideoFrameStream::Stop(const base::Closure& closure) { // we don't need this here. See: http://crbug.com/173313 stream_ = NULL; decrypting_demuxer_stream_ = NULL; - decoder_.reset(); + decoder_ = NULL; message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); } @@ -153,7 +164,8 @@ void VideoFrameStream::EnableBitstreamConverter() { } void VideoFrameStream::OnDecoderSelected( - scoped_ptr<VideoDecoder> selected_decoder, + scoped_ptr<VideoDecoderSelector> decoder_selector, + const scoped_refptr<VideoDecoder>& selected_decoder, const scoped_refptr<DecryptingDemuxerStream>& decrypting_demuxer_stream) { DCHECK(message_loop_->BelongsToCurrentThread()); DCHECK_EQ(state_, UNINITIALIZED); @@ -163,7 +175,7 @@ void VideoFrameStream::OnDecoderSelected( state_ = UNINITIALIZED; base::ResetAndReturn(&init_cb_).Run(false, false); } else { - decoder_ = selected_decoder.Pass(); + decoder_ = selected_decoder; decrypting_demuxer_stream_ = decrypting_demuxer_stream; state_ = NORMAL; base::ResetAndReturn(&init_cb_).Run(true, decoder_->HasAlpha()); @@ -227,7 +239,7 @@ void VideoFrameStream::OnDecoderStopped() { // we don't need this here. See: http://crbug.com/173313 stream_ = NULL; decrypting_demuxer_stream_ = NULL; - decoder_.reset(); + decoder_ = NULL; base::ResetAndReturn(&stop_cb_).Run(); } diff --git a/media/filters/video_frame_stream.h b/media/filters/video_frame_stream.h index 193ffc6..f815419 100644 --- a/media/filters/video_frame_stream.h +++ b/media/filters/video_frame_stream.h @@ -11,14 +11,12 @@ #include "base/callback.h" #include "base/compiler_specific.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_vector.h" #include "base/memory/weak_ptr.h" #include "media/base/decryptor.h" #include "media/base/demuxer_stream.h" #include "media/base/media_export.h" #include "media/base/pipeline_status.h" #include "media/base/video_decoder.h" -#include "media/filters/video_decoder_selector.h" namespace base { class MessageLoopProxy; @@ -33,16 +31,18 @@ class VideoDecoderSelector; // VideoFrames to its client (e.g. VideoRendererBase). class MEDIA_EXPORT VideoFrameStream : public DemuxerStream { public: + typedef std::list<scoped_refptr<VideoDecoder> > VideoDecoderList; + // Indicates completion of VideoFrameStream initialization. typedef base::Callback<void(bool success, bool has_alpha)> InitCB; VideoFrameStream(const scoped_refptr<base::MessageLoopProxy>& message_loop, - ScopedVector<VideoDecoder> decoders, const SetDecryptorReadyCB& set_decryptor_ready_cb); // Initializes the VideoFrameStream and returns the initialization result // through |init_cb|. Note that |init_cb| is always called asynchronously. void Initialize(const scoped_refptr<DemuxerStream>& stream, + const VideoDecoderList& decoders, const StatisticsCB& statistics_cb, const InitCB& init_cb); @@ -90,8 +90,11 @@ class MEDIA_EXPORT VideoFrameStream : public DemuxerStream { // Called when |decoder_selector_| selected the |selected_decoder|. // |decrypting_demuxer_stream| was also populated if a DecryptingDemuxerStream // is created to help decrypt the encrypted stream. + // Note: |decoder_selector| is passed here to keep the VideoDecoderSelector + // alive until OnDecoderSelected() finishes. void OnDecoderSelected( - scoped_ptr<VideoDecoder> selected_decoder, + scoped_ptr<VideoDecoderSelector> decoder_selector, + const scoped_refptr<VideoDecoder>& selected_decoder, const scoped_refptr<DecryptingDemuxerStream>& decrypting_demuxer_stream); // Callback for VideoDecoder::Read(). @@ -115,12 +118,12 @@ class MEDIA_EXPORT VideoFrameStream : public DemuxerStream { base::Closure reset_cb_; base::Closure stop_cb_; - VideoDecoderSelector decoder_selector_; + SetDecryptorReadyCB set_decryptor_ready_cb_; scoped_refptr<DemuxerStream> stream_; // These two will be set by VideoDecoderSelector::SelectVideoDecoder(). - scoped_ptr<VideoDecoder> decoder_; + scoped_refptr<VideoDecoder> decoder_; scoped_refptr<DecryptingDemuxerStream> decrypting_demuxer_stream_; DISALLOW_COPY_AND_ASSIGN(VideoFrameStream); diff --git a/media/filters/video_frame_stream_unittest.cc b/media/filters/video_frame_stream_unittest.cc index 7c58b6e..e45c903 100644 --- a/media/filters/video_frame_stream_unittest.cc +++ b/media/filters/video_frame_stream_unittest.cc @@ -31,21 +31,18 @@ static const gfx::Size kNaturalSize(320, 240); class VideoFrameStreamTest : public testing::TestWithParam<bool> { public: VideoFrameStreamTest() - : video_config_(kCodecVP8, VIDEO_CODEC_PROFILE_UNKNOWN, kVideoFormat, + : video_frame_stream_(new VideoFrameStream( + message_loop_.message_loop_proxy(), + base::Bind(&VideoFrameStreamTest::SetDecryptorReadyCallback, + base::Unretained(this)))), + video_config_(kCodecVP8, VIDEO_CODEC_PROFILE_UNKNOWN, kVideoFormat, kCodedSize, kVisibleRect, kNaturalSize, NULL, 0, GetParam()), demuxer_stream_(new StrictMock<MockDemuxerStream>()), decryptor_(new NiceMock<MockDecryptor>()), decoder_(new StrictMock<MockVideoDecoder>()), is_initialized_(false) { - ScopedVector<VideoDecoder> decoders; - decoders.push_back(decoder_); - - video_frame_stream_ = new VideoFrameStream( - message_loop_.message_loop_proxy(), - decoders.Pass(), - base::Bind(&VideoFrameStreamTest::SetDecryptorReadyCallback, - base::Unretained(this))); + decoders_.push_back(decoder_); EXPECT_CALL(*demuxer_stream_, type()) .WillRepeatedly(Return(DemuxerStream::VIDEO)); @@ -91,6 +88,7 @@ class VideoFrameStreamTest : public testing::TestWithParam<bool> { .WillOnce(SaveArg<1>(&decoder_init_cb_)); video_frame_stream_->Initialize( demuxer_stream_, + decoders_, base::Bind(&VideoFrameStreamTest::OnStatistics, base::Unretained(this)), base::Bind(&VideoFrameStreamTest::OnInitialized, base::Unretained(this))); @@ -190,7 +188,8 @@ class VideoFrameStreamTest : public testing::TestWithParam<bool> { // Use NiceMock since we don't care about most of calls on the decryptor, e.g. // RegisterNewKeyCB(). scoped_ptr<NiceMock<MockDecryptor> > decryptor_; - StrictMock<MockVideoDecoder>* decoder_; // Owned by |video_frame_stream_|. + scoped_refptr<StrictMock<MockVideoDecoder> > decoder_; + VideoFrameStream::VideoDecoderList decoders_; // Callbacks to simulate pending decoder operations. PipelineStatusCB decoder_init_cb_; diff --git a/media/filters/video_renderer_base.cc b/media/filters/video_renderer_base.cc index c9dee83..98439c6 100644 --- a/media/filters/video_renderer_base.cc +++ b/media/filters/video_renderer_base.cc @@ -23,15 +23,14 @@ base::TimeDelta VideoRendererBase::kMaxLastFrameDuration() { VideoRendererBase::VideoRendererBase( const scoped_refptr<base::MessageLoopProxy>& message_loop, - ScopedVector<VideoDecoder> decoders, const SetDecryptorReadyCB& set_decryptor_ready_cb, const PaintCB& paint_cb, const SetOpaqueCB& set_opaque_cb, bool drop_frames) : message_loop_(message_loop), weak_factory_(this), - video_frame_stream_(new VideoFrameStream( - message_loop, decoders.Pass(), set_decryptor_ready_cb)), + video_frame_stream_(new VideoFrameStream(message_loop, + set_decryptor_ready_cb)), received_end_of_stream_(false), frame_available_(&lock_), state_(kUninitialized), @@ -137,6 +136,7 @@ void VideoRendererBase::Preroll(base::TimeDelta time, } void VideoRendererBase::Initialize(const scoped_refptr<DemuxerStream>& stream, + const VideoDecoderList& decoders, const PipelineStatusCB& init_cb, const StatisticsCB& statistics_cb, const TimeCB& max_time_cb, @@ -148,6 +148,7 @@ void VideoRendererBase::Initialize(const scoped_refptr<DemuxerStream>& stream, DCHECK(message_loop_->BelongsToCurrentThread()); base::AutoLock auto_lock(lock_); DCHECK(stream); + DCHECK(!decoders.empty()); DCHECK_EQ(stream->type(), DemuxerStream::VIDEO); DCHECK(!init_cb.is_null()); DCHECK(!statistics_cb.is_null()); @@ -171,6 +172,7 @@ void VideoRendererBase::Initialize(const scoped_refptr<DemuxerStream>& stream, video_frame_stream_->Initialize( stream, + decoders, statistics_cb, base::Bind(&VideoRendererBase::OnVideoFrameStreamInitialized, weak_this_)); diff --git a/media/filters/video_renderer_base.h b/media/filters/video_renderer_base.h index 94e0730..7b01653 100644 --- a/media/filters/video_renderer_base.h +++ b/media/filters/video_renderer_base.h @@ -8,7 +8,6 @@ #include <deque> #include "base/memory/ref_counted.h" -#include "base/memory/scoped_vector.h" #include "base/memory/weak_ptr.h" #include "base/synchronization/condition_variable.h" #include "base/synchronization/lock.h" @@ -44,8 +43,6 @@ class MEDIA_EXPORT VideoRendererBase // Maximum duration of the last frame. static base::TimeDelta kMaxLastFrameDuration(); - // |decoders| contains the VideoDecoders to use when initializing. - // // |paint_cb| is executed on the video frame timing thread whenever a new // frame is available for painting. // @@ -58,7 +55,6 @@ class MEDIA_EXPORT VideoRendererBase // // Setting |drop_frames_| to true causes the renderer to drop expired frames. VideoRendererBase(const scoped_refptr<base::MessageLoopProxy>& message_loop, - ScopedVector<VideoDecoder> decoders, const SetDecryptorReadyCB& set_decryptor_ready_cb, const PaintCB& paint_cb, const SetOpaqueCB& set_opaque_cb, @@ -67,6 +63,7 @@ class MEDIA_EXPORT VideoRendererBase // VideoRenderer implementation. virtual void Initialize(const scoped_refptr<DemuxerStream>& stream, + const VideoDecoderList& decoders, const PipelineStatusCB& init_cb, const StatisticsCB& statistics_cb, const TimeCB& max_time_cb, @@ -132,17 +129,12 @@ class MEDIA_EXPORT VideoRendererBase // A read is scheduled to replace the frame. void DropNextReadyFrame_Locked(); - void ResetDecoder(); - void StopDecoder(const base::Closure& callback); - void TransitionToPrerolled_Locked(); scoped_refptr<base::MessageLoopProxy> message_loop_; base::WeakPtrFactory<VideoRendererBase> weak_factory_; base::WeakPtr<VideoRendererBase> weak_this_; - scoped_ptr<VideoDecoderSelector> decoder_selector_; - // Used for accessing data members. base::Lock lock_; diff --git a/media/filters/video_renderer_base_unittest.cc b/media/filters/video_renderer_base_unittest.cc index 4ce9f08..c498c50 100644 --- a/media/filters/video_renderer_base_unittest.cc +++ b/media/filters/video_renderer_base_unittest.cc @@ -45,12 +45,8 @@ class VideoRendererBaseTest : public ::testing::Test { demuxer_stream_(new MockDemuxerStream()), video_config_(kCodecVP8, VIDEO_CODEC_PROFILE_UNKNOWN, kVideoFormat, kCodedSize, kVisibleRect, kNaturalSize, NULL, 0, false) { - ScopedVector<VideoDecoder> decoders; - decoders.push_back(decoder_); - renderer_.reset(new VideoRendererBase( message_loop_.message_loop_proxy(), - decoders.Pass(), media::SetDecryptorReadyCB(), base::Bind(&VideoRendererBaseTest::OnPaint, base::Unretained(this)), base::Bind(&VideoRendererBaseTest::OnSetOpaque, base::Unretained(this)), @@ -122,8 +118,11 @@ class VideoRendererBaseTest : public ::testing::Test { } void CallInitialize(const PipelineStatusCB& status_cb) { + VideoRendererBase::VideoDecoderList decoders; + decoders.push_back(decoder_); renderer_->Initialize( demuxer_stream_, + decoders, status_cb, base::Bind(&MockStatisticsCB::OnStatistics, base::Unretained(&statistics_cb_object_)), @@ -296,7 +295,7 @@ class VideoRendererBaseTest : public ::testing::Test { protected: // Fixture members. scoped_ptr<VideoRendererBase> renderer_; - MockVideoDecoder* decoder_; // Owned by |renderer_|. + scoped_refptr<MockVideoDecoder> decoder_; scoped_refptr<MockDemuxerStream> demuxer_stream_; MockStatisticsCB statistics_cb_object_; diff --git a/media/filters/vpx_video_decoder.cc b/media/filters/vpx_video_decoder.cc index baab017..0b92a7d 100644 --- a/media/filters/vpx_video_decoder.cc +++ b/media/filters/vpx_video_decoder.cc @@ -58,7 +58,6 @@ static int GetThreadCount() { VpxVideoDecoder::VpxVideoDecoder( const scoped_refptr<base::MessageLoopProxy>& message_loop) : message_loop_(message_loop), - weak_factory_(this), state_(kUninitialized), vpx_codec_(NULL) { } @@ -74,7 +73,6 @@ void VpxVideoDecoder::Initialize( const StatisticsCB& statistics_cb) { DCHECK(message_loop_->BelongsToCurrentThread()); DCHECK(!demuxer_stream_) << "Already initialized."; - weak_this_ = weak_factory_.GetWeakPtr(); if (!stream) { status_cb.Run(PIPELINE_ERROR_DECODE); @@ -184,7 +182,7 @@ void VpxVideoDecoder::ReadFromDemuxerStream() { DCHECK(!read_cb_.is_null()); demuxer_stream_->Read(base::Bind( - &VpxVideoDecoder::DoDecryptOrDecodeBuffer, weak_this_)); + &VpxVideoDecoder::DoDecryptOrDecodeBuffer, this)); } void VpxVideoDecoder::DoDecryptOrDecodeBuffer( diff --git a/media/filters/vpx_video_decoder.h b/media/filters/vpx_video_decoder.h index aea47bb..77578fd 100644 --- a/media/filters/vpx_video_decoder.h +++ b/media/filters/vpx_video_decoder.h @@ -6,7 +6,7 @@ #define MEDIA_FILTERS_VPX_VIDEO_DECODER_H_ #include "base/callback.h" -#include "base/memory/weak_ptr.h" +#include "base/memory/ref_counted.h" #include "media/base/demuxer_stream.h" #include "media/base/video_decoder.h" @@ -23,7 +23,6 @@ class MEDIA_EXPORT VpxVideoDecoder : public VideoDecoder { public: explicit VpxVideoDecoder( const scoped_refptr<base::MessageLoopProxy>& message_loop); - virtual ~VpxVideoDecoder(); // VideoDecoder implementation. virtual void Initialize(const scoped_refptr<DemuxerStream>& stream, @@ -33,6 +32,9 @@ class MEDIA_EXPORT VpxVideoDecoder : public VideoDecoder { virtual void Reset(const base::Closure& closure) OVERRIDE; virtual void Stop(const base::Closure& closure) OVERRIDE; + protected: + virtual ~VpxVideoDecoder(); + private: enum DecoderState { kUninitialized, @@ -64,8 +66,6 @@ class MEDIA_EXPORT VpxVideoDecoder : public VideoDecoder { scoped_refptr<VideoFrame>* video_frame); scoped_refptr<base::MessageLoopProxy> message_loop_; - base::WeakPtrFactory<VpxVideoDecoder> weak_factory_; - base::WeakPtr<VpxVideoDecoder> weak_this_; DecoderState state_; |