summaryrefslogtreecommitdiffstats
path: root/media/filters
diff options
context:
space:
mode:
authorscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-18 22:03:48 +0000
committerscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-18 22:03:48 +0000
commitc9802d4f24fcee643d992038b9d4658e640c2867 (patch)
treebf7b7b029c253243b10b5e301b417c5efc81d4bf /media/filters
parent13b33a4f0c3f3f4c9e29cf222d59335c19dda7f9 (diff)
downloadchromium_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')
-rw-r--r--media/filters/decrypting_video_decoder.cc14
-rw-r--r--media/filters/decrypting_video_decoder.h8
-rw-r--r--media/filters/decrypting_video_decoder_unittest.cc2
-rw-r--r--media/filters/ffmpeg_video_decoder.cc5
-rw-r--r--media/filters/ffmpeg_video_decoder.h8
-rw-r--r--media/filters/ffmpeg_video_decoder_unittest.cc6
-rw-r--r--media/filters/gpu_video_decoder.cc224
-rw-r--r--media/filters/gpu_video_decoder.h19
-rw-r--r--media/filters/pipeline_integration_test_base.cc13
-rw-r--r--media/filters/video_decoder_selector.cc79
-rw-r--r--media/filters/video_decoder_selector.h20
-rw-r--r--media/filters/video_decoder_selector_unittest.cc56
-rw-r--r--media/filters/video_frame_stream.cc30
-rw-r--r--media/filters/video_frame_stream.h15
-rw-r--r--media/filters/video_frame_stream_unittest.cc19
-rw-r--r--media/filters/video_renderer_base.cc8
-rw-r--r--media/filters/video_renderer_base.h10
-rw-r--r--media/filters/video_renderer_base_unittest.cc9
-rw-r--r--media/filters/vpx_video_decoder.cc4
-rw-r--r--media/filters/vpx_video_decoder.h8
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_;