summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorfischman@chromium.org <fischman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-17 19:39:37 +0000
committerfischman@chromium.org <fischman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-17 19:39:37 +0000
commit085390b899d3dcec1abd27ebbddd375ddea98067 (patch)
treea4981d18ead6b8fa1708048e8c510cc16801ea91
parentf9e6c45351f6ca73755cfb0ebb8bf11935ec86c4 (diff)
downloadchromium_src-085390b899d3dcec1abd27ebbddd375ddea98067.zip
chromium_src-085390b899d3dcec1abd27ebbddd375ddea98067.tar.gz
chromium_src-085390b899d3dcec1abd27ebbddd375ddea98067.tar.bz2
VideoDecodeAccelerator now SupportsWeakPtr instead of being RefCountedThreadSafe.
Claiming both (which GpuVideoDecodeAcceleratorHost was doing) is confusing and RCTS encourages sloppy lifecycle management. Instead drop RCTS in favor of WeakPtr<>s and explicit lifecycle management (scoped_ptr, with Pass). BUG=136294 Review URL: https://chromiumcodereview.appspot.com/10749019 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@147069 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--content/common/gpu/client/command_buffer_proxy_impl.cc10
-rw-r--r--content/common/gpu/client/command_buffer_proxy_impl.h4
-rw-r--r--content/common/gpu/client/gpu_video_decode_accelerator_host.cc1
-rw-r--r--content/common/gpu/client/gpu_video_decode_accelerator_host.h7
-rw-r--r--content/common/gpu/media/dxva_video_decode_accelerator.cc18
-rw-r--r--content/common/gpu/media/gpu_video_decode_accelerator.cc30
-rw-r--r--content/common/gpu/media/gpu_video_decode_accelerator.h4
-rw-r--r--content/common/gpu/media/mac_video_decode_accelerator.h5
-rw-r--r--content/common/gpu/media/mac_video_decode_accelerator.mm36
-rw-r--r--content/common/gpu/media/omx_video_decode_accelerator.cc34
-rw-r--r--content/common/gpu/media/omx_video_decode_accelerator.h21
-rw-r--r--content/common/gpu/media/vaapi_video_decode_accelerator.cc55
-rw-r--r--content/common/gpu/media/vaapi_video_decode_accelerator.h19
-rw-r--r--content/common/gpu/media/video_decode_accelerator_unittest.cc25
-rw-r--r--content/content_tests.gypi4
-rw-r--r--content/renderer/media/pepper_platform_video_decoder_impl.cc22
-rw-r--r--content/renderer/media/pepper_platform_video_decoder_impl.h2
-rw-r--r--media/filters/gpu_video_decoder.cc52
-rw-r--r--media/filters/gpu_video_decoder.h11
-rw-r--r--media/video/video_decode_accelerator.h15
-rw-r--r--webkit/plugins/ppapi/plugin_delegate.h2
-rw-r--r--webkit/plugins/ppapi/ppb_video_decoder_impl.cc21
-rw-r--r--webkit/plugins/ppapi/ppb_video_decoder_impl.h2
23 files changed, 231 insertions, 169 deletions
diff --git a/content/common/gpu/client/command_buffer_proxy_impl.cc b/content/common/gpu/client/command_buffer_proxy_impl.cc
index 80e0b1c..2d6a1685 100644
--- a/content/common/gpu/client/command_buffer_proxy_impl.cc
+++ b/content/common/gpu/client/command_buffer_proxy_impl.cc
@@ -46,6 +46,10 @@ CommandBufferProxyImpl::~CommandBufferProxyImpl() {
delete it->second.shared_memory;
it->second.shared_memory = NULL;
}
+ for (Decoders::iterator it = video_decoder_hosts_.begin();
+ it != video_decoder_hosts_.end(); ++it) {
+ it->second->Destroy();
+ }
}
bool CommandBufferProxyImpl::OnMessageReceived(const IPC::Message& message) {
@@ -483,7 +487,7 @@ void CommandBufferProxyImpl::SetNotifyRepaintTask(const base::Closure& task) {
notify_repaint_task_ = task;
}
-scoped_refptr<GpuVideoDecodeAcceleratorHost>
+GpuVideoDecodeAcceleratorHost*
CommandBufferProxyImpl::CreateVideoDecoder(
media::VideoCodecProfile profile,
media::VideoDecodeAccelerator::Client* client) {
@@ -499,13 +503,13 @@ CommandBufferProxyImpl::CreateVideoDecoder(
return NULL;
}
- scoped_refptr<GpuVideoDecodeAcceleratorHost> decoder_host =
+ GpuVideoDecodeAcceleratorHost* decoder_host =
new GpuVideoDecodeAcceleratorHost(channel_, decoder_route_id, client);
bool inserted = video_decoder_hosts_.insert(std::make_pair(
decoder_route_id, decoder_host)).second;
DCHECK(inserted);
- channel_->AddRoute(decoder_route_id, decoder_host->AsWeakPtr());
+ channel_->AddRoute(decoder_route_id, base::AsWeakPtr(decoder_host));
return decoder_host;
}
diff --git a/content/common/gpu/client/command_buffer_proxy_impl.h b/content/common/gpu/client/command_buffer_proxy_impl.h
index b21c51c..7f774639 100644
--- a/content/common/gpu/client/command_buffer_proxy_impl.h
+++ b/content/common/gpu/client/command_buffer_proxy_impl.h
@@ -50,7 +50,7 @@ class CommandBufferProxyImpl
// Note that the GpuVideoDecodeAccelerator may still fail to be created in
// the GPU process, even if this returns non-NULL. In this case the client is
// notified of an error later.
- scoped_refptr<GpuVideoDecodeAcceleratorHost> CreateVideoDecoder(
+ GpuVideoDecodeAcceleratorHost* CreateVideoDecoder(
media::VideoCodecProfile profile,
media::VideoDecodeAccelerator::Client* client);
@@ -107,7 +107,7 @@ class CommandBufferProxyImpl
private:
typedef std::map<int32, gpu::Buffer> TransferBufferMap;
- typedef std::map<int, scoped_refptr<GpuVideoDecodeAcceleratorHost> > Decoders;
+ typedef std::map<int, GpuVideoDecodeAcceleratorHost*> Decoders;
typedef base::hash_map<uint32, base::Closure> SignalTaskMap;
// Send an IPC message over the GPU channel. This is private to fully
diff --git a/content/common/gpu/client/gpu_video_decode_accelerator_host.cc b/content/common/gpu/client/gpu_video_decode_accelerator_host.cc
index 77cdd3a..078171f 100644
--- a/content/common/gpu/client/gpu_video_decode_accelerator_host.cc
+++ b/content/common/gpu/client/gpu_video_decode_accelerator_host.cc
@@ -122,6 +122,7 @@ void GpuVideoDecodeAcceleratorHost::Destroy() {
channel_->RemoveRoute(decoder_route_id_);
client_ = NULL;
Send(new AcceleratedVideoDecoderMsg_Destroy(decoder_route_id_));
+ delete this;
}
GpuVideoDecodeAcceleratorHost::~GpuVideoDecodeAcceleratorHost() {}
diff --git a/content/common/gpu/client/gpu_video_decode_accelerator_host.h b/content/common/gpu/client/gpu_video_decode_accelerator_host.h
index 0339e0f..e33129f 100644
--- a/content/common/gpu/client/gpu_video_decode_accelerator_host.h
+++ b/content/common/gpu/client/gpu_video_decode_accelerator_host.h
@@ -19,13 +19,13 @@ class GpuChannelHost;
class GpuVideoDecodeAcceleratorHost
: public IPC::Listener,
public media::VideoDecodeAccelerator,
- public base::NonThreadSafe,
- public base::SupportsWeakPtr<GpuVideoDecodeAcceleratorHost> {
+ public base::NonThreadSafe {
public:
// |channel| is used to send IPC messages to GPU process.
GpuVideoDecodeAcceleratorHost(GpuChannelHost* channel,
int32 decoder_route_id,
media::VideoDecodeAccelerator::Client* client);
+ virtual ~GpuVideoDecodeAcceleratorHost();
// IPC::Listener implementation.
virtual void OnChannelError() OVERRIDE;
@@ -41,9 +41,6 @@ class GpuVideoDecodeAcceleratorHost
virtual void Reset() OVERRIDE;
virtual void Destroy() OVERRIDE;
- protected:
- virtual ~GpuVideoDecodeAcceleratorHost();
-
private:
void Send(IPC::Message* message);
diff --git a/content/common/gpu/media/dxva_video_decode_accelerator.cc b/content/common/gpu/media/dxva_video_decode_accelerator.cc
index 2edc138..c99121c 100644
--- a/content/common/gpu/media/dxva_video_decode_accelerator.cc
+++ b/content/common/gpu/media/dxva_video_decode_accelerator.cc
@@ -548,8 +548,9 @@ bool DXVAVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile) {
PLATFORM_FAILURE, false);
state_ = kNormal;
- MessageLoop::current()->PostTask(FROM_HERE,
- base::Bind(&DXVAVideoDecodeAccelerator::NotifyInitializeDone, this));
+ MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+ &DXVAVideoDecodeAccelerator::NotifyInitializeDone,
+ base::AsWeakPtr(this)));
return true;
}
@@ -597,7 +598,7 @@ void DXVAVideoDecodeAccelerator::Decode(
// decoder to emit an output packet for every input packet.
// http://code.google.com/p/chromium/issues/detail?id=108121
MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
- &DXVAVideoDecodeAccelerator::NotifyInputBufferRead, this,
+ &DXVAVideoDecodeAccelerator::NotifyInputBufferRead, base::AsWeakPtr(this),
bitstream_buffer.id()));
}
@@ -658,7 +659,7 @@ void DXVAVideoDecodeAccelerator::Flush() {
}
MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
- &DXVAVideoDecodeAccelerator::NotifyFlushDone, this));
+ &DXVAVideoDecodeAccelerator::NotifyFlushDone, base::AsWeakPtr(this)));
state_ = kNormal;
}
@@ -677,7 +678,7 @@ void DXVAVideoDecodeAccelerator::Reset() {
"Reset: Failed to send message.", PLATFORM_FAILURE,);
MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
- &DXVAVideoDecodeAccelerator::NotifyResetDone, this));
+ &DXVAVideoDecodeAccelerator::NotifyResetDone, base::AsWeakPtr(this)));
state_ = DXVAVideoDecodeAccelerator::kNormal;
}
@@ -685,6 +686,7 @@ void DXVAVideoDecodeAccelerator::Reset() {
void DXVAVideoDecodeAccelerator::Destroy() {
DCHECK(CalledOnValidThread());
Invalidate();
+ delete this;
}
bool DXVAVideoDecodeAccelerator::InitDecoder() {
@@ -946,7 +948,7 @@ bool DXVAVideoDecodeAccelerator::ProcessOutputSample(IMFSample* sample) {
// Go ahead and request picture buffers.
MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
&DXVAVideoDecodeAccelerator::RequestPictureBuffers,
- this, surface_desc.Width, surface_desc.Height));
+ base::AsWeakPtr(this), surface_desc.Width, surface_desc.Height));
pictures_requested_ = true;
return true;
@@ -973,8 +975,8 @@ void DXVAVideoDecodeAccelerator::ProcessPendingSamples() {
media::Picture output_picture(index->second->id(),
sample_info.input_buffer_id);
MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
- &DXVAVideoDecodeAccelerator::NotifyPictureReady, this,
- output_picture));
+ &DXVAVideoDecodeAccelerator::NotifyPictureReady,
+ base::AsWeakPtr(this), output_picture));
index->second->set_available(false);
pending_output_samples_.pop_front();
diff --git a/content/common/gpu/media/gpu_video_decode_accelerator.cc b/content/common/gpu/media/gpu_video_decode_accelerator.cc
index ab8415d..f164acc 100644
--- a/content/common/gpu/media/gpu_video_decode_accelerator.cc
+++ b/content/common/gpu/media/gpu_video_decode_accelerator.cc
@@ -70,12 +70,12 @@ GpuVideoDecodeAccelerator::GpuVideoDecodeAccelerator(
GpuVideoDecodeAccelerator::~GpuVideoDecodeAccelerator() {
if (stub_)
stub_->RemoveDestructionObserver(this);
- if (video_decode_accelerator_)
- video_decode_accelerator_->Destroy();
+ if (video_decode_accelerator_.get())
+ video_decode_accelerator_.release()->Destroy();
}
bool GpuVideoDecodeAccelerator::OnMessageReceived(const IPC::Message& msg) {
- if (!stub_ || !video_decode_accelerator_)
+ if (!stub_ || !video_decode_accelerator_.get())
return false;
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(GpuVideoDecodeAccelerator, msg)
@@ -169,31 +169,31 @@ void GpuVideoDecodeAccelerator::Initialize(
return;
}
DLOG(INFO) << "Initializing DXVA HW decoder for windows.";
- scoped_refptr<DXVAVideoDecodeAccelerator> video_decoder(
+ scoped_ptr<DXVAVideoDecodeAccelerator> video_decoder(
new DXVAVideoDecodeAccelerator(this));
- video_decode_accelerator_ = video_decoder;
+ video_decode_accelerator_ = video_decoder.Pass();
#elif defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL)
- scoped_refptr<OmxVideoDecodeAccelerator> video_decoder(
+ scoped_ptr<OmxVideoDecodeAccelerator> video_decoder(
new OmxVideoDecodeAccelerator(this));
video_decoder->SetEglState(
gfx::GLSurfaceEGL::GetHardwareDisplay(),
stub_->decoder()->GetGLContext()->GetHandle());
- video_decode_accelerator_ = video_decoder;
+ video_decode_accelerator_ = video_decoder.Pass();
#elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
- scoped_refptr<VaapiVideoDecodeAccelerator> video_decoder(
+ scoped_ptr<VaapiVideoDecodeAccelerator> video_decoder(
new VaapiVideoDecodeAccelerator(this, make_context_current_));
gfx::GLContextGLX* glx_context =
static_cast<gfx::GLContextGLX*>(stub_->decoder()->GetGLContext());
GLXContext glx_context_handle =
static_cast<GLXContext>(glx_context->GetHandle());
video_decoder->SetGlxState(glx_context->display(), glx_context_handle);
- video_decode_accelerator_ = video_decoder;
+ video_decode_accelerator_ = video_decoder.Pass();
#elif defined(OS_MACOSX)
- scoped_refptr<MacVideoDecodeAccelerator> video_decoder(
+ scoped_ptr<MacVideoDecodeAccelerator> video_decoder(
new MacVideoDecodeAccelerator(this));
video_decoder->SetCGLContext(static_cast<CGLContextObj>(
stub_->decoder()->GetGLContext()->GetHandle()));
- video_decode_accelerator_ = video_decoder;
+ video_decode_accelerator_ = video_decoder.Pass();
#else
NOTIMPLEMENTED() << "HW video decode acceleration not available.";
NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
@@ -263,7 +263,7 @@ void GpuVideoDecodeAccelerator::OnReset() {
void GpuVideoDecodeAccelerator::OnDestroy() {
DCHECK(video_decode_accelerator_.get());
- video_decode_accelerator_->Destroy();
+ video_decode_accelerator_.release()->Destroy();
}
void GpuVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer(
@@ -296,10 +296,8 @@ void GpuVideoDecodeAccelerator::NotifyResetDone() {
void GpuVideoDecodeAccelerator::OnWillDestroyStub(GpuCommandBufferStub* stub) {
DCHECK_EQ(stub, stub_.get());
- if (video_decode_accelerator_) {
- video_decode_accelerator_->Destroy();
- video_decode_accelerator_ = NULL;
- }
+ if (video_decode_accelerator_.get())
+ video_decode_accelerator_.release()->Destroy();
if (stub_) {
stub_->RemoveDestructionObserver(this);
stub_.reset();
diff --git a/content/common/gpu/media/gpu_video_decode_accelerator.h b/content/common/gpu/media/gpu_video_decode_accelerator.h
index e635670..6f7566c 100644
--- a/content/common/gpu/media/gpu_video_decode_accelerator.h
+++ b/content/common/gpu/media/gpu_video_decode_accelerator.h
@@ -84,8 +84,8 @@ class GpuVideoDecodeAccelerator
// Unowned pointer to the underlying GpuCommandBufferStub.
base::WeakPtr<GpuCommandBufferStub> stub_;
- // Pointer to the underlying VideoDecodeAccelerator.
- scoped_refptr<media::VideoDecodeAccelerator> video_decode_accelerator_;
+ // The underlying VideoDecodeAccelerator.
+ scoped_ptr<media::VideoDecodeAccelerator> video_decode_accelerator_;
// Callback for making the relevant context current for GL calls.
// Returns false if failed.
diff --git a/content/common/gpu/media/mac_video_decode_accelerator.h b/content/common/gpu/media/mac_video_decode_accelerator.h
index 55cb55b..2aa3830 100644
--- a/content/common/gpu/media/mac_video_decode_accelerator.h
+++ b/content/common/gpu/media/mac_video_decode_accelerator.h
@@ -33,6 +33,7 @@ class CONTENT_EXPORT MacVideoDecodeAccelerator
public:
// Does not take ownership of |client| which must outlive |*this|.
MacVideoDecodeAccelerator(media::VideoDecodeAccelerator::Client* client);
+ virtual ~MacVideoDecodeAccelerator();
// Set the OpenGL context to use.
void SetCGLContext(CGLContextObj cgl_context);
@@ -48,7 +49,6 @@ class CONTENT_EXPORT MacVideoDecodeAccelerator
virtual void Destroy() OVERRIDE;
private:
- virtual ~MacVideoDecodeAccelerator();
// Callback for a completed frame.
void OnFrameReady(int32 bitstream_buffer_id,
@@ -85,6 +85,9 @@ class CONTENT_EXPORT MacVideoDecodeAccelerator
// has been processed.
void NotifyInputBufferRead(int input_buffer_id);
+ // Helper for Destroy(), doing all the actual work except for deleting self.
+ void Cleanup();
+
// To expose client callbacks from VideoDecodeAccelerator.
Client* client_;
// C++ wrapper around the Mac VDA API.
diff --git a/content/common/gpu/media/mac_video_decode_accelerator.mm b/content/common/gpu/media/mac_video_decode_accelerator.mm
index b10ec55..7aa9c6c 100644
--- a/content/common/gpu/media/mac_video_decode_accelerator.mm
+++ b/content/common/gpu/media/mac_video_decode_accelerator.mm
@@ -112,7 +112,7 @@ bool MacVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile) {
return false;
MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
- &MacVideoDecodeAccelerator::NotifyInitializeDone, this));
+ &MacVideoDecodeAccelerator::NotifyInitializeDone, base::AsWeakPtr(this)));
return true;
}
@@ -134,8 +134,8 @@ void MacVideoDecodeAccelerator::Decode(
if (result == content::H264Parser::kEOStream) {
if (bitstream_nalu_count_.count(bitstream_buffer.id()) == 0) {
MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
- &MacVideoDecodeAccelerator::NotifyInputBufferRead, this,
- bitstream_buffer.id()));
+ &MacVideoDecodeAccelerator::NotifyInputBufferRead,
+ base::AsWeakPtr(this), bitstream_buffer.id()));
}
return;
}
@@ -197,7 +197,7 @@ void MacVideoDecodeAccelerator::Flush() {
"Call to Flush() during invalid state.", ILLEGAL_STATE,);
vda_support_->Flush(true);
MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
- &MacVideoDecodeAccelerator::NotifyFlushDone, this));
+ &MacVideoDecodeAccelerator::NotifyFlushDone, base::AsWeakPtr(this)));
}
void MacVideoDecodeAccelerator::Reset() {
@@ -206,10 +206,10 @@ void MacVideoDecodeAccelerator::Reset() {
"Call to Reset() during invalid state.", ILLEGAL_STATE,);
vda_support_->Flush(false);
MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
- &MacVideoDecodeAccelerator::NotifyResetDone, this));
+ &MacVideoDecodeAccelerator::NotifyResetDone, base::AsWeakPtr(this)));
}
-void MacVideoDecodeAccelerator::Destroy() {
+void MacVideoDecodeAccelerator::Cleanup() {
DCHECK(CalledOnValidThread());
if (vda_support_) {
vda_support_->Destroy();
@@ -219,9 +219,17 @@ void MacVideoDecodeAccelerator::Destroy() {
decoded_images_.clear();
}
+void MacVideoDecodeAccelerator::Destroy() {
+ DCHECK(CalledOnValidThread());
+ Cleanup();
+ delete this;
+}
+
MacVideoDecodeAccelerator::~MacVideoDecodeAccelerator() {
DCHECK(CalledOnValidThread());
- Destroy();
+ DCHECK(!vda_support_);
+ DCHECK(!client_);
+ DCHECK(decoded_images_.empty());
}
void MacVideoDecodeAccelerator::OnFrameReady(
@@ -247,8 +255,8 @@ void MacVideoDecodeAccelerator::OnFrameReady(
if (--bitstream_count_it->second == 0) {
bitstream_nalu_count_.erase(bitstream_count_it);
MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
- &MacVideoDecodeAccelerator::NotifyInputBufferRead, this,
- bitstream_buffer_id));
+ &MacVideoDecodeAccelerator::NotifyInputBufferRead,
+ base::AsWeakPtr(this), bitstream_buffer_id));
}
}
@@ -279,7 +287,7 @@ void MacVideoDecodeAccelerator::StopOnError(
media::VideoDecodeAccelerator::Error error) {
if (client_)
client_->NotifyError(error);
- Destroy();
+ Cleanup();
}
bool MacVideoDecodeAccelerator::CreateDecoder(
@@ -298,7 +306,7 @@ bool MacVideoDecodeAccelerator::CreateDecoder(
PLATFORM_FAILURE, false);
MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
- &MacVideoDecodeAccelerator::RequestPictures, this));
+ &MacVideoDecodeAccelerator::RequestPictures, base::AsWeakPtr(this)));
return true;
}
@@ -321,9 +329,9 @@ void MacVideoDecodeAccelerator::DecodeNALU(const content::H264NALU& nalu,
// Keep a ref counted copy of the buffer.
scoped_refptr<base::RefCountedBytes> bytes(
base::RefCountedBytes::TakeVector(&data));
- vda_support_->Decode(bytes->front(), bytes->size(),
- base::Bind(&MacVideoDecodeAccelerator::OnFrameReady,
- this, bitstream_buffer_id, bytes));
+ vda_support_->Decode(bytes->front(), bytes->size(), base::Bind(
+ &MacVideoDecodeAccelerator::OnFrameReady,
+ base::AsWeakPtr(this), bitstream_buffer_id, bytes));
}
void MacVideoDecodeAccelerator::NotifyInitializeDone() {
diff --git a/content/common/gpu/media/omx_video_decode_accelerator.cc b/content/common/gpu/media/omx_video_decode_accelerator.cc
index 7bcd1bb..d8045ab 100644
--- a/content/common/gpu/media/omx_video_decode_accelerator.cc
+++ b/content/common/gpu/media/omx_video_decode_accelerator.cc
@@ -101,6 +101,7 @@ OmxVideoDecodeAccelerator::OmxVideoDecodeAccelerator(
media::VideoDecodeAccelerator::Client* client)
: message_loop_(MessageLoop::current()),
component_handle_(NULL),
+ weak_this_(base::AsWeakPtr(this)),
init_begun_(false),
client_state_(OMX_StateMax),
current_state_change_(NO_TRANSITION),
@@ -190,7 +191,6 @@ bool OmxVideoDecodeAccelerator::CreateComponent() {
PLATFORM_FAILURE, false);
// Get the handle to the component.
- AddRef(); // To reflect passing |this| to OMX_GetHandle below.
result = omx_gethandle(
&component_handle_, reinterpret_cast<OMX_STRING>(component.get()),
this, &omx_accelerator_callbacks);
@@ -439,6 +439,9 @@ void OmxVideoDecodeAccelerator::Reset() {
void OmxVideoDecodeAccelerator::Destroy() {
DCHECK_EQ(message_loop_, MessageLoop::current());
+
+ scoped_ptr<OmxVideoDecodeAccelerator> deleter(this);
+
if (current_state_change_ == ERRORING ||
current_state_change_ == DESTROYING) {
return;
@@ -462,7 +465,7 @@ void OmxVideoDecodeAccelerator::Destroy() {
current_state_change_ = DESTROYING;
client_ = NULL;
BeginTransitionToState(OMX_StateIdle);
- BusyLoopInDestroying();
+ BusyLoopInDestroying(deleter.Pass());
}
void OmxVideoDecodeAccelerator::BeginTransitionToState(
@@ -562,14 +565,15 @@ void OmxVideoDecodeAccelerator::OnReachedExecutingInResetting() {
// outlives the shutdown dance, even during process shutdown. We do this by
// repeatedly enqueuing a no-op task until shutdown is complete, since
// MessageLoop's shutdown drains pending tasks.
-void OmxVideoDecodeAccelerator::BusyLoopInDestroying() {
+void OmxVideoDecodeAccelerator::BusyLoopInDestroying(
+ scoped_ptr<OmxVideoDecodeAccelerator> self) {
if (!component_handle_) return;
// Can't use PostDelayedTask here because MessageLoop doesn't drain delayed
// tasks. Instead we sleep for 5ms. Really.
base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(5));
- message_loop_->PostTask(
- FROM_HERE, base::Bind(
- &OmxVideoDecodeAccelerator::BusyLoopInDestroying, this));
+ MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+ &OmxVideoDecodeAccelerator::BusyLoopInDestroying,
+ base::Unretained(this), base::Passed(&self)));
}
void OmxVideoDecodeAccelerator::OnReachedIdleInDestroying() {
@@ -590,8 +594,6 @@ void OmxVideoDecodeAccelerator::OnReachedIdleInDestroying() {
FreeInputBuffers();
if (!output_buffers_at_component_)
FreeOutputBuffers();
-
- BusyLoopInDestroying();
}
void OmxVideoDecodeAccelerator::OnReachedLoadedInDestroying() {
@@ -610,12 +612,10 @@ void OmxVideoDecodeAccelerator::ShutdownComponent() {
OMX_ERRORTYPE result = omx_free_handle(component_handle_);
if (result != OMX_ErrorNone)
DLOG(ERROR) << "OMX_FreeHandle() error. Error code: " << result;
- component_handle_ = NULL;
client_state_ = OMX_StateMax;
- // This Release() call must happen *after* any access to |*this| because it
- // might result in |this| being deleted.
- Release(); // Since OMX no longer has |this| to call back to.
omx_deinit();
+ // Allow BusyLoopInDestroying to exit and delete |this|.
+ component_handle_ = NULL;
}
void OmxVideoDecodeAccelerator::StopOnError(
@@ -1000,8 +1000,8 @@ OMX_ERRORTYPE OmxVideoDecodeAccelerator::EventHandler(OMX_HANDLETYPE component,
static_cast<OmxVideoDecodeAccelerator*>(priv_data);
DCHECK_EQ(component, decoder->component_handle_);
decoder->message_loop_->PostTask(FROM_HERE, base::Bind(
- &OmxVideoDecodeAccelerator::EventHandlerCompleteTask, decoder,
- event, data1, data2));
+ &OmxVideoDecodeAccelerator::EventHandlerCompleteTask,
+ decoder->weak_this(), event, data1, data2));
return OMX_ErrorNone;
}
@@ -1017,7 +1017,8 @@ OMX_ERRORTYPE OmxVideoDecodeAccelerator::EmptyBufferCallback(
static_cast<OmxVideoDecodeAccelerator*>(priv_data);
DCHECK_EQ(component, decoder->component_handle_);
decoder->message_loop_->PostTask(FROM_HERE, base::Bind(
- &OmxVideoDecodeAccelerator::EmptyBufferDoneTask, decoder, buffer));
+ &OmxVideoDecodeAccelerator::EmptyBufferDoneTask, decoder->weak_this(),
+ buffer));
return OMX_ErrorNone;
}
@@ -1037,7 +1038,8 @@ OMX_ERRORTYPE OmxVideoDecodeAccelerator::FillBufferCallback(
static_cast<OmxVideoDecodeAccelerator*>(priv_data);
DCHECK_EQ(component, decoder->component_handle_);
decoder->message_loop_->PostTask(FROM_HERE, base::Bind(
- &OmxVideoDecodeAccelerator::FillBufferDoneTask, decoder, buffer));
+ &OmxVideoDecodeAccelerator::FillBufferDoneTask, decoder->weak_this(),
+ buffer));
return OMX_ErrorNone;
}
diff --git a/content/common/gpu/media/omx_video_decode_accelerator.h b/content/common/gpu/media/omx_video_decode_accelerator.h
index b42a39b..1c186a2 100644
--- a/content/common/gpu/media/omx_video_decode_accelerator.h
+++ b/content/common/gpu/media/omx_video_decode_accelerator.h
@@ -15,7 +15,6 @@
#include "base/compiler_specific.h"
#include "base/logging.h"
-#include "base/memory/ref_counted.h"
#include "base/message_loop.h"
#include "base/shared_memory.h"
#include "content/common/content_export.h"
@@ -32,16 +31,15 @@ class Gles2TextureToEglImageTranslator;
// The implementation assumes an OpenMAX IL 1.1.2 implementation conforming to
// http://www.khronos.org/registry/omxil/specs/OpenMAX_IL_1_1_2_Specification.pdf
//
-// This class lives on a single thread and DCHECKs that it is never accessed
-// from any other. OMX callbacks are trampolined from the OMX component's
-// thread to maintain this invariant. The only exception to thread-unsafety is
-// that references can be added from any thread (practically used only by the
-// OMX thread).
+// This class lives on a single thread (the GPU process ChildThread) and DCHECKs
+// that it is never accessed from any other. OMX callbacks are trampolined from
+// the OMX component's thread to maintain this invariant, using |weak_this()|.
class CONTENT_EXPORT OmxVideoDecodeAccelerator :
public media::VideoDecodeAccelerator {
public:
// Does not take ownership of |client| which must outlive |*this|.
OmxVideoDecodeAccelerator(media::VideoDecodeAccelerator::Client* client);
+ virtual ~OmxVideoDecodeAccelerator();
// media::VideoDecodeAccelerator implementation.
bool Initialize(media::VideoCodecProfile profile) OVERRIDE;
@@ -55,9 +53,9 @@ class CONTENT_EXPORT OmxVideoDecodeAccelerator :
void SetEglState(EGLDisplay egl_display, EGLContext egl_context);
- private:
- virtual ~OmxVideoDecodeAccelerator();
+ base::WeakPtr<OmxVideoDecodeAccelerator> weak_this() { return weak_this_; }
+ private:
// Because OMX state-transitions are described solely by the "state reached"
// (3.1.2.9.1, table 3-7 of the spec), we track what transition was requested
// using this enum. Note that it is an error to request a transition while
@@ -114,7 +112,7 @@ class CONTENT_EXPORT OmxVideoDecodeAccelerator :
void OnReachedEOSInFlushing();
void OnReachedInvalidInErroring();
void ShutdownComponent();
- void BusyLoopInDestroying();
+ void BusyLoopInDestroying(scoped_ptr<OmxVideoDecodeAccelerator> self);
// Port-flushing helpers.
void FlushIOPorts();
@@ -138,6 +136,11 @@ class CONTENT_EXPORT OmxVideoDecodeAccelerator :
// Decode bitstream buffers that were queued (see queued_bitstream_buffers_).
void DecodeQueuedBitstreamBuffers();
+ // Weak pointer to |this|; used to safely trampoline calls from the OMX thread
+ // to the ChildThread. Since |this| is kept alive until OMX is fully shut
+ // down, only the OMX->Child thread direction needs to be guarded this way.
+ base::WeakPtr<OmxVideoDecodeAccelerator> weak_this_;
+
// True once Initialize() has returned true; before this point there's never a
// point in calling client_->NotifyError().
bool init_begun_;
diff --git a/content/common/gpu/media/vaapi_video_decode_accelerator.cc b/content/common/gpu/media/vaapi_video_decode_accelerator.cc
index 389d406..a9bddee 100644
--- a/content/common/gpu/media/vaapi_video_decode_accelerator.cc
+++ b/content/common/gpu/media/vaapi_video_decode_accelerator.cc
@@ -36,8 +36,9 @@ VaapiVideoDecodeAccelerator::InputBuffer::~InputBuffer() {
void VaapiVideoDecodeAccelerator::NotifyError(Error error) {
if (message_loop_ != MessageLoop::current()) {
+ DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
message_loop_->PostTask(FROM_HERE, base::Bind(
- &VaapiVideoDecodeAccelerator::NotifyError, this, error));
+ &VaapiVideoDecodeAccelerator::NotifyError, weak_this_, error));
return;
}
@@ -47,7 +48,7 @@ void VaapiVideoDecodeAccelerator::NotifyError(Error error) {
client_->NotifyError(error);
client_ptr_factory_.InvalidateWeakPtrs();
}
- Destroy();
+ Cleanup();
}
VaapiVideoDecodeAccelerator::VaapiVideoDecodeAccelerator(
@@ -58,6 +59,7 @@ VaapiVideoDecodeAccelerator::VaapiVideoDecodeAccelerator(
input_ready_(&lock_),
output_ready_(&lock_),
message_loop_(MessageLoop::current()),
+ weak_this_(base::AsWeakPtr(this)),
client_ptr_factory_(client),
client_(client_ptr_factory_.GetWeakPtr()),
decoder_thread_("VaapiDecoderThread") {
@@ -78,7 +80,8 @@ bool VaapiVideoDecodeAccelerator::Initialize(
bool res = decoder_.Initialize(
profile, x_display_, glx_context_, make_context_current_,
- base::Bind(&VaapiVideoDecodeAccelerator::OutputPicCallback, this));
+ base::Bind(&VaapiVideoDecodeAccelerator::OutputPicCallback,
+ base::Unretained(this)));
if (!res) {
DVLOG(1) << "Failed initializing decoder";
return false;
@@ -181,7 +184,8 @@ void VaapiVideoDecodeAccelerator::InitialDecodeTask() {
DCHECK_EQ(state_, kIdle);
state_ = kDecoding;
decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
- &VaapiVideoDecodeAccelerator::DecodeTask, this));
+ &VaapiVideoDecodeAccelerator::DecodeTask,
+ base::Unretained(this)));
}
return;
@@ -342,8 +346,9 @@ void VaapiVideoDecodeAccelerator::Decode(
switch (state_) {
case kInitialized:
// Initial decode to get the required size of output buffers.
- decoder_thread_.message_loop()->PostTask(FROM_HERE,
- base::Bind(&VaapiVideoDecodeAccelerator::InitialDecodeTask, this));
+ decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
+ &VaapiVideoDecodeAccelerator::InitialDecodeTask,
+ base::Unretained(this)));
break;
case kPicturesRequested:
@@ -355,8 +360,9 @@ void VaapiVideoDecodeAccelerator::Decode(
case kIdle:
// Need to get decoder into suitable stream location to resume.
- decoder_thread_.message_loop()->PostTask(FROM_HERE,
- base::Bind(&VaapiVideoDecodeAccelerator::InitialDecodeTask, this));
+ decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
+ &VaapiVideoDecodeAccelerator::InitialDecodeTask,
+ base::Unretained(this)));
break;
default:
@@ -384,8 +390,8 @@ void VaapiVideoDecodeAccelerator::AssignPictureBuffers(
}
state_ = kDecoding;
- decoder_thread_.message_loop()->PostTask(FROM_HERE,
- base::Bind(&VaapiVideoDecodeAccelerator::DecodeTask, this));
+ decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
+ &VaapiVideoDecodeAccelerator::DecodeTask, base::Unretained(this)));
}
void VaapiVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) {
@@ -411,8 +417,8 @@ void VaapiVideoDecodeAccelerator::FlushTask() {
// Put the decoder in idle state, ready to resume.
decoder_.Reset();
- message_loop_->PostTask(FROM_HERE,
- base::Bind(&VaapiVideoDecodeAccelerator::FinishFlush, this));
+ message_loop_->PostTask(FROM_HERE, base::Bind(
+ &VaapiVideoDecodeAccelerator::FinishFlush, weak_this_));
}
void VaapiVideoDecodeAccelerator::Flush() {
@@ -422,8 +428,8 @@ void VaapiVideoDecodeAccelerator::Flush() {
base::AutoLock auto_lock(lock_);
state_ = kFlushing;
// Queue a flush task after all existing decoding tasks to clean up.
- decoder_thread_.message_loop()->PostTask(FROM_HERE,
- base::Bind(&VaapiVideoDecodeAccelerator::FlushTask, this));
+ decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
+ &VaapiVideoDecodeAccelerator::FlushTask, base::Unretained(this)));
input_ready_.Signal();
output_ready_.Signal();
@@ -460,7 +466,7 @@ void VaapiVideoDecodeAccelerator::ResetTask() {
// And let client know that we are done with reset.
message_loop_->PostTask(FROM_HERE, base::Bind(
- &VaapiVideoDecodeAccelerator::FinishReset, this));
+ &VaapiVideoDecodeAccelerator::FinishReset, weak_this_));
}
void VaapiVideoDecodeAccelerator::Reset() {
@@ -471,8 +477,8 @@ void VaapiVideoDecodeAccelerator::Reset() {
base::AutoLock auto_lock(lock_);
state_ = kResetting;
- decoder_thread_.message_loop()->PostTask(FROM_HERE,
- base::Bind(&VaapiVideoDecodeAccelerator::ResetTask, this));
+ decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
+ &VaapiVideoDecodeAccelerator::ResetTask, base::Unretained(this)));
input_ready_.Signal();
output_ready_.Signal();
@@ -503,7 +509,7 @@ void VaapiVideoDecodeAccelerator::FinishReset() {
DVLOG(1) << "Reset finished";
}
-void VaapiVideoDecodeAccelerator::Destroy() {
+void VaapiVideoDecodeAccelerator::Cleanup() {
DCHECK_EQ(message_loop_, MessageLoop::current());
if (state_ == kUninitialized || state_ == kDestroying)
@@ -524,12 +530,19 @@ void VaapiVideoDecodeAccelerator::Destroy() {
input_ready_.Signal();
output_ready_.Signal();
waiter.Wait();
+ decoder_thread_.Stop();
}
decoder_.Destroy();
state_ = kUninitialized;
}
+void VaapiVideoDecodeAccelerator::Destroy() {
+ DCHECK_EQ(message_loop_, MessageLoop::current());
+ Cleanup();
+ delete this;
+}
+
void VaapiVideoDecodeAccelerator::OutputPicCallback(int32 input_id,
int32 output_id) {
TRACE_EVENT2("Video Decoder", "VAVDA::OutputPicCallback",
@@ -539,7 +552,7 @@ void VaapiVideoDecodeAccelerator::OutputPicCallback(int32 input_id,
// Forward the request to the main thread.
DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
- message_loop_->PostTask(FROM_HERE,
- base::Bind(&VaapiVideoDecodeAccelerator::SyncAndNotifyPictureReady,
- this, input_id, output_id));
+ message_loop_->PostTask(FROM_HERE, base::Bind(
+ &VaapiVideoDecodeAccelerator::SyncAndNotifyPictureReady, weak_this_,
+ input_id, output_id));
}
diff --git a/content/common/gpu/media/vaapi_video_decode_accelerator.h b/content/common/gpu/media/vaapi_video_decode_accelerator.h
index 6624792..9fdffde 100644
--- a/content/common/gpu/media/vaapi_video_decode_accelerator.h
+++ b/content/common/gpu/media/vaapi_video_decode_accelerator.h
@@ -32,12 +32,18 @@
// Class to provide video decode acceleration for Intel systems with hardware
// support for it, and on which libva is available.
// Decoding tasks are performed in a separate decoding thread.
+//
+// Threading/life-cycle: this object is created & destroyed on the GPU
+// ChildThread. A few methods on it are called on the decoder thread which is
+// stopped during |this->Destroy()|, so any tasks posted to the decoder thread
+// can assume |*this| is still alive. See |weak_this_| below for more details.
class CONTENT_EXPORT VaapiVideoDecodeAccelerator :
public media::VideoDecodeAccelerator {
public:
VaapiVideoDecodeAccelerator(
Client* client,
const base::Callback<bool(void)>& make_context_current);
+ virtual ~VaapiVideoDecodeAccelerator();
// media::VideoDecodeAccelerator implementation.
virtual bool Initialize(media::VideoCodecProfile profile) OVERRIDE;
@@ -53,8 +59,6 @@ class CONTENT_EXPORT VaapiVideoDecodeAccelerator :
void SetGlxState(Display* x_display, GLXContext glx_context);
private:
- virtual ~VaapiVideoDecodeAccelerator();
-
// Ensure data has been synced with the output texture and notify
// the client it is ready for displaying.
void SyncAndNotifyPictureReady(int32 input_id, int32 output_id);
@@ -116,6 +120,9 @@ class CONTENT_EXPORT VaapiVideoDecodeAccelerator :
// finished.
void FinishReset();
+ // Helper for Destroy(), doing all the actual work except for deleting self.
+ void Cleanup();
+
// Client-provided X/GLX state.
Display* x_display_;
GLXContext glx_context_;
@@ -174,6 +181,14 @@ class CONTENT_EXPORT VaapiVideoDecodeAccelerator :
// ChildThread's message loop
MessageLoop* message_loop_;
+ // WeakPtr<> pointing to |this| for use in posting tasks from the decoder
+ // thread back to the ChildThread. Because the decoder thread is a member of
+ // this class, any task running on the decoder thread is guaranteed that this
+ // object is still alive. As a result, tasks posted from ChildThread to
+ // decoder thread should use base::Unretained(this), and tasks posted from the
+ // decoder thread to the ChildThread should use |weak_this_|.
+ base::WeakPtr<VaapiVideoDecodeAccelerator> weak_this_;
+
// To expose client callbacks from VideoDecodeAccelerator.
// NOTE: all calls to these objects *MUST* be executed on message_loop_.
base::WeakPtrFactory<Client> client_ptr_factory_;
diff --git a/content/common/gpu/media/video_decode_accelerator_unittest.cc b/content/common/gpu/media/video_decode_accelerator_unittest.cc
index 8b01a05..59f6f20 100644
--- a/content/common/gpu/media/video_decode_accelerator_unittest.cc
+++ b/content/common/gpu/media/video_decode_accelerator_unittest.cc
@@ -224,7 +224,7 @@ class GLRenderingVDAClient : public VideoDecodeAccelerator::Client {
int num_done_bitstream_buffers() { return num_done_bitstream_buffers_; }
int num_decoded_frames() { return num_decoded_frames_; }
double frames_per_second();
- bool decoder_deleted() { return !decoder_; }
+ bool decoder_deleted() { return !decoder_.get(); }
private:
typedef std::map<int, media::PictureBuffer*> PictureBufferById;
@@ -250,7 +250,7 @@ class GLRenderingVDAClient : public VideoDecodeAccelerator::Client {
size_t encoded_data_next_pos_to_decode_;
int next_bitstream_buffer_id_;
ClientStateNotification* note_;
- scoped_refptr<VideoDecodeAccelerator> decoder_;
+ scoped_ptr<VideoDecodeAccelerator> decoder_;
std::set<int> outstanding_texture_ids_;
int remaining_play_throughs_;
int reset_after_frame_num_;
@@ -308,27 +308,27 @@ static bool DoNothingReturnTrue() { return true; }
void GLRenderingVDAClient::CreateDecoder() {
CHECK(decoder_deleted());
#if defined(OS_WIN)
- scoped_refptr<DXVAVideoDecodeAccelerator> decoder =
- new DXVAVideoDecodeAccelerator(this);
+ scoped_ptr<DXVAVideoDecodeAccelerator> decoder(
+ new DXVAVideoDecodeAccelerator(this));
#elif defined(OS_MACOSX)
- scoped_refptr<MacVideoDecodeAccelerator> decoder =
- new MacVideoDecodeAccelerator(this);
+ scoped_ptr<MacVideoDecodeAccelerator> decoder(
+ new MacVideoDecodeAccelerator(this));
decoder->SetCGLContext(
static_cast<CGLContextObj>(rendering_helper_->GetGLContext()));
#elif defined(ARCH_CPU_ARMEL)
- scoped_refptr<OmxVideoDecodeAccelerator> decoder =
- new OmxVideoDecodeAccelerator(this);
+ scoped_ptr<OmxVideoDecodeAccelerator> decoder(
+ new OmxVideoDecodeAccelerator(this));
decoder->SetEglState(
static_cast<EGLDisplay>(rendering_helper_->GetGLDisplay()),
static_cast<EGLContext>(rendering_helper_->GetGLContext()));
#elif defined(ARCH_CPU_X86_FAMILY)
- scoped_refptr<VaapiVideoDecodeAccelerator> decoder =
- new VaapiVideoDecodeAccelerator(this, base::Bind(&DoNothingReturnTrue));
+ scoped_ptr<VaapiVideoDecodeAccelerator> decoder(
+ new VaapiVideoDecodeAccelerator(this, base::Bind(&DoNothingReturnTrue)));
decoder->SetGlxState(
static_cast<Display*>(rendering_helper_->GetGLDisplay()),
static_cast<GLXContext>(rendering_helper_->GetGLContext()));
#endif // OS_WIN
- decoder_ = decoder.release();
+ decoder_ = decoder.Pass();
SetState(CS_DECODER_SET);
if (decoder_deleted())
return;
@@ -483,8 +483,7 @@ void GLRenderingVDAClient::SetState(ClientState new_state) {
void GLRenderingVDAClient::DeleteDecoder() {
if (decoder_deleted())
return;
- decoder_->Destroy();
- decoder_ = NULL;
+ decoder_.release()->Destroy();
STLClearObject(&encoded_data_);
for (std::set<int>::iterator it = outstanding_texture_ids_.begin();
it != outstanding_texture_ids_.end(); ++it) {
diff --git a/content/content_tests.gypi b/content/content_tests.gypi
index 30f8bb5..c0672bb 100644
--- a/content/content_tests.gypi
+++ b/content/content_tests.gypi
@@ -629,7 +629,9 @@
'../third_party/angle/src/build_angle.gyp:libGLESv2',
],
}],
- ['OS=="win" and win_use_allocator_shim==1', {
+ ['(OS=="win" and win_use_allocator_shim==1) or '
+ '(os_posix == 1 and OS != "mac" and OS != "android" and '
+ ' linux_use_tcmalloc==1)', {
'dependencies': [
'../base/allocator/allocator.gyp:allocator',
],
diff --git a/content/renderer/media/pepper_platform_video_decoder_impl.cc b/content/renderer/media/pepper_platform_video_decoder_impl.cc
index 62e5d23..b00f36c 100644
--- a/content/renderer/media/pepper_platform_video_decoder_impl.cc
+++ b/content/renderer/media/pepper_platform_video_decoder_impl.cc
@@ -26,7 +26,7 @@ PlatformVideoDecoderImpl::~PlatformVideoDecoderImpl() {}
bool PlatformVideoDecoderImpl::Initialize(media::VideoCodecProfile profile) {
// TODO(vrk): Support multiple decoders.
- if (decoder_)
+ if (decoder_.get())
return true;
RenderThreadImpl* render_thread = RenderThreadImpl::current();
@@ -43,43 +43,43 @@ bool PlatformVideoDecoderImpl::Initialize(media::VideoCodecProfile profile) {
DCHECK_EQ(channel->state(), GpuChannelHost::kConnected);
// Send IPC message to initialize decoder in GPU process.
- decoder_ = channel->CreateVideoDecoder(
- command_buffer_route_id_, profile, this);
+ decoder_.reset(channel->CreateVideoDecoder(
+ command_buffer_route_id_, profile, this));
return decoder_.get() != NULL;
}
void PlatformVideoDecoderImpl::Decode(const BitstreamBuffer& bitstream_buffer) {
- DCHECK(decoder_);
+ DCHECK(decoder_.get());
decoder_->Decode(bitstream_buffer);
}
void PlatformVideoDecoderImpl::AssignPictureBuffers(
const std::vector<media::PictureBuffer>& buffers) {
- DCHECK(decoder_);
+ DCHECK(decoder_.get());
decoder_->AssignPictureBuffers(buffers);
}
void PlatformVideoDecoderImpl::ReusePictureBuffer(
int32 picture_buffer_id) {
- DCHECK(decoder_);
+ DCHECK(decoder_.get());
decoder_->ReusePictureBuffer(picture_buffer_id);
}
void PlatformVideoDecoderImpl::Flush() {
- DCHECK(decoder_);
+ DCHECK(decoder_.get());
decoder_->Flush();
}
void PlatformVideoDecoderImpl::Reset() {
- DCHECK(decoder_);
+ DCHECK(decoder_.get());
decoder_->Reset();
}
void PlatformVideoDecoderImpl::Destroy() {
- DCHECK(decoder_);
- decoder_->Destroy();
+ DCHECK(decoder_.get());
+ decoder_.release()->Destroy();
client_ = NULL;
- decoder_ = NULL;
+ delete this;
}
void PlatformVideoDecoderImpl::NotifyError(
diff --git a/content/renderer/media/pepper_platform_video_decoder_impl.h b/content/renderer/media/pepper_platform_video_decoder_impl.h
index d79ce01..0008531 100644
--- a/content/renderer/media/pepper_platform_video_decoder_impl.h
+++ b/content/renderer/media/pepper_platform_video_decoder_impl.h
@@ -58,7 +58,7 @@ class PlatformVideoDecoderImpl
int32 command_buffer_route_id_;
// Holds a GpuVideoDecodeAcceleratorHost.
- scoped_refptr<media::VideoDecodeAccelerator> decoder_;
+ scoped_ptr<media::VideoDecodeAccelerator> decoder_;
DISALLOW_COPY_AND_ASSIGN(PlatformVideoDecoderImpl);
};
diff --git a/media/filters/gpu_video_decoder.cc b/media/filters/gpu_video_decoder.cc
index 7415db8..e5bca0d 100644
--- a/media/filters/gpu_video_decoder.cc
+++ b/media/filters/gpu_video_decoder.cc
@@ -72,7 +72,7 @@ void GpuVideoDecoder::Reset(const base::Closure& closure) {
// Throw away any already-decoded, not-yet-delivered frames.
ready_video_frames_.clear();
- if (!vda_) {
+ if (!vda_.get()) {
closure.Run();
return;
}
@@ -94,7 +94,7 @@ void GpuVideoDecoder::Reset(const base::Closure& closure) {
}
vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
- &VideoDecodeAccelerator::Reset, vda_));
+ &VideoDecodeAccelerator::Reset, weak_vda_));
}
void GpuVideoDecoder::Stop(const base::Closure& closure) {
@@ -103,13 +103,13 @@ void GpuVideoDecoder::Stop(const base::Closure& closure) {
&GpuVideoDecoder::Stop, this, closure));
return;
}
- if (!vda_) {
+ if (!vda_.get()) {
closure.Run();
return;
}
+ VideoDecodeAccelerator* vda ALLOW_UNUSED = vda_.release();
vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
- &VideoDecodeAccelerator::Destroy, vda_));
- vda_ = NULL;
+ &VideoDecodeAccelerator::Destroy, weak_vda_));
closure.Run();
}
@@ -141,8 +141,9 @@ void GpuVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream,
return;
}
- vda_ = factories_->CreateVideoDecodeAccelerator(config.profile(), this);
- if (!vda_) {
+ VideoDecodeAccelerator* vda =
+ factories_->CreateVideoDecodeAccelerator(config.profile(), this);
+ if (!vda) {
status_cb.Run(DECODER_ERROR_NOT_SUPPORTED);
return;
}
@@ -156,7 +157,16 @@ void GpuVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream,
config_frame_duration_ = GetFrameDuration(config);
DVLOG(1) << "GpuVideoDecoder::Initialize() succeeded.";
- status_cb.Run(PIPELINE_OK);
+ vda_loop_proxy_->PostTaskAndReply(
+ FROM_HERE,
+ base::Bind(&GpuVideoDecoder::SetVDA, this, vda),
+ base::Bind(status_cb, PIPELINE_OK));
+}
+
+void GpuVideoDecoder::SetVDA(VideoDecodeAccelerator* vda) {
+ DCHECK(vda_loop_proxy_->BelongsToCurrentThread());
+ vda_.reset(vda);
+ weak_vda_ = vda->AsWeakPtr();
}
void GpuVideoDecoder::Read(const ReadCB& read_cb) {
@@ -171,7 +181,7 @@ void GpuVideoDecoder::Read(const ReadCB& read_cb) {
return;
}
- if (!vda_) {
+ if (!vda_.get()) {
read_cb.Run(kOk, VideoFrame::CreateEmptyFrame());
return;
}
@@ -218,7 +228,7 @@ void GpuVideoDecoder::RequestBufferDecode(
return;
}
- if (!vda_) {
+ if (!vda_.get()) {
EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame());
return;
}
@@ -227,7 +237,7 @@ void GpuVideoDecoder::RequestBufferDecode(
if (state_ == kNormal) {
state_ = kDrainingDecoder;
vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
- &VideoDecodeAccelerator::Flush, vda_));
+ &VideoDecodeAccelerator::Flush, weak_vda_));
}
return;
}
@@ -243,7 +253,7 @@ void GpuVideoDecoder::RequestBufferDecode(
RecordBufferTimeData(bitstream_buffer, *buffer);
vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
- &VideoDecodeAccelerator::Decode, vda_, bitstream_buffer));
+ &VideoDecodeAccelerator::Decode, weak_vda_, bitstream_buffer));
}
void GpuVideoDecoder::RecordBufferTimeData(
@@ -319,7 +329,7 @@ void GpuVideoDecoder::ProvidePictureBuffers(uint32 count,
return;
}
- if (!vda_)
+ if (!vda_.get())
return;
std::vector<PictureBuffer> picture_buffers;
@@ -331,7 +341,8 @@ void GpuVideoDecoder::ProvidePictureBuffers(uint32 count,
DCHECK(inserted);
}
vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
- &VideoDecodeAccelerator::AssignPictureBuffers, vda_, picture_buffers));
+ &VideoDecodeAccelerator::AssignPictureBuffers, weak_vda_,
+ picture_buffers));
}
void GpuVideoDecoder::DismissPictureBuffer(int32 id) {
@@ -409,10 +420,11 @@ void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id) {
&GpuVideoDecoder::ReusePictureBuffer, this, picture_buffer_id));
return;
}
- if (!vda_)
+ if (!vda_.get())
return;
vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
- &VideoDecodeAccelerator::ReusePictureBuffer, vda_, picture_buffer_id));
+ &VideoDecodeAccelerator::ReusePictureBuffer, weak_vda_,
+ picture_buffer_id));
}
GpuVideoDecoder::SHMBuffer* GpuVideoDecoder::GetSHM(size_t min_size) {
@@ -467,7 +479,7 @@ void GpuVideoDecoder::NotifyEndOfBitstreamBuffer(int32 id) {
}
GpuVideoDecoder::~GpuVideoDecoder() {
- DCHECK(!vda_); // Stop should have been already called.
+ DCHECK(!vda_.get()); // Stop should have been already called.
DCHECK(pending_read_cb_.is_null());
for (size_t i = 0; i < available_shm_segments_.size(); ++i) {
available_shm_segments_[i]->shm->Close();
@@ -510,7 +522,7 @@ void GpuVideoDecoder::NotifyResetDone() {
return;
}
- if (!vda_)
+ if (!vda_.get())
return;
DCHECK(ready_video_frames_.empty());
@@ -532,9 +544,9 @@ void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) {
&GpuVideoDecoder::NotifyError, this, error));
return;
}
- if (!vda_)
+ if (!vda_.get())
return;
- vda_ = NULL;
+ vda_loop_proxy_->DeleteSoon(FROM_HERE, vda_.release());
DLOG(ERROR) << "VDA Error: " << error;
error_occured_ = true;
diff --git a/media/filters/gpu_video_decoder.h b/media/filters/gpu_video_decoder.h
index f4c3c63..1ccbbde 100644
--- a/media/filters/gpu_video_decoder.h
+++ b/media/filters/gpu_video_decoder.h
@@ -119,6 +119,10 @@ class MEDIA_EXPORT GpuVideoDecoder
void GetBufferTimeData(
int32 id, base::TimeDelta* timestamp, base::TimeDelta* duration);
+ // Set |vda_| and |weak_vda_| on the VDA thread (in practice the render
+ // thread).
+ void SetVDA(VideoDecodeAccelerator* vda);
+
// A shared memory segment and its allocated size.
struct SHMBuffer {
SHMBuffer(base::SharedMemory* m, size_t s);
@@ -158,8 +162,11 @@ class MEDIA_EXPORT GpuVideoDecoder
scoped_refptr<Factories> factories_;
- // Populated during Initialize() (on success) and unchanged thereafter.
- scoped_refptr<VideoDecodeAccelerator> vda_;
+ // Populated during Initialize() via SetVDA() (on success) and unchanged
+ // 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_;
// Callbacks that are !is_null() only during their respective operation being
// asynchronously executed.
diff --git a/media/video/video_decode_accelerator.h b/media/video/video_decode_accelerator.h
index 83d0b95..63553a9 100644
--- a/media/video/video_decode_accelerator.h
+++ b/media/video/video_decode_accelerator.h
@@ -8,6 +8,7 @@
#include <vector>
#include "base/basictypes.h"
+#include "base/memory/weak_ptr.h"
#include "media/base/bitstream_buffer.h"
#include "media/base/video_decoder_config.h"
#include "media/video/picture.h"
@@ -18,12 +19,11 @@ namespace media {
// Video decoder interface.
// This interface is extended by the various components that ultimately
// implement the backend of PPB_VideoDecode_Dev.
-//
-// No thread-safety guarantees are implied by the use of RefCountedThreadSafe
-// below.
class MEDIA_EXPORT VideoDecodeAccelerator
- : public base::RefCountedThreadSafe<VideoDecodeAccelerator> {
+ : public base::SupportsWeakPtr<VideoDecodeAccelerator> {
public:
+ virtual ~VideoDecodeAccelerator();
+
// Enumeration of potential errors generated by the API.
// Note: Keep these in sync with PP_VideoDecodeError_Dev.
enum Error {
@@ -126,12 +126,9 @@ class MEDIA_EXPORT VideoDecodeAccelerator
// Destroys the decoder: all pending inputs are dropped immediately and the
// component is freed. This call may asynchornously free system resources,
// but its client-visible effects are synchronous. After this method returns
- // no more callbacks will be made on the client.
+ // no more callbacks will be made on the client. Deletes |this|
+ // unconditionally, so make sure to drop all pointers to it!
virtual void Destroy() = 0;
-
- protected:
- friend class base::RefCountedThreadSafe<VideoDecodeAccelerator>;
- virtual ~VideoDecodeAccelerator();
};
} // namespace media
diff --git a/webkit/plugins/ppapi/plugin_delegate.h b/webkit/plugins/ppapi/plugin_delegate.h
index 9c3e38c..c393d0c 100644
--- a/webkit/plugins/ppapi/plugin_delegate.h
+++ b/webkit/plugins/ppapi/plugin_delegate.h
@@ -269,7 +269,7 @@ class PluginDelegate {
// Interface for PlatformVideoDecoder is directly inherited from general media
// VideoDecodeAccelerator interface.
class PlatformVideoDecoder : public media::VideoDecodeAccelerator {
- protected:
+ public:
virtual ~PlatformVideoDecoder() {}
};
diff --git a/webkit/plugins/ppapi/ppb_video_decoder_impl.cc b/webkit/plugins/ppapi/ppb_video_decoder_impl.cc
index 9c63e13..b1bcc9d 100644
--- a/webkit/plugins/ppapi/ppb_video_decoder_impl.cc
+++ b/webkit/plugins/ppapi/ppb_video_decoder_impl.cc
@@ -116,9 +116,9 @@ bool PPB_VideoDecoder_Impl::Init(
if (!plugin_delegate)
return false;
- platform_video_decoder_ = plugin_delegate->CreateVideoDecoder(
- this, command_buffer_route_id);
- if (!platform_video_decoder_)
+ platform_video_decoder_.reset(plugin_delegate->CreateVideoDecoder(
+ this, command_buffer_route_id));
+ if (!platform_video_decoder_.get())
return false;
FlushCommandBuffer();
@@ -128,7 +128,7 @@ bool PPB_VideoDecoder_Impl::Init(
int32_t PPB_VideoDecoder_Impl::Decode(
const PP_VideoBitstreamBuffer_Dev* bitstream_buffer,
scoped_refptr<TrackedCallback> callback) {
- if (!platform_video_decoder_)
+ if (!platform_video_decoder_.get())
return PP_ERROR_BADRESOURCE;
EnterResourceNoLock<PPB_Buffer_API> enter(bitstream_buffer->data, true);
@@ -151,7 +151,7 @@ int32_t PPB_VideoDecoder_Impl::Decode(
void PPB_VideoDecoder_Impl::AssignPictureBuffers(
uint32_t no_of_buffers,
const PP_PictureBuffer_Dev* buffers) {
- if (!platform_video_decoder_)
+ if (!platform_video_decoder_.get())
return;
std::vector<media::PictureBuffer> wrapped_buffers;
@@ -169,7 +169,7 @@ void PPB_VideoDecoder_Impl::AssignPictureBuffers(
}
void PPB_VideoDecoder_Impl::ReusePictureBuffer(int32_t picture_buffer_id) {
- if (!platform_video_decoder_)
+ if (!platform_video_decoder_.get())
return;
FlushCommandBuffer();
@@ -177,7 +177,7 @@ void PPB_VideoDecoder_Impl::ReusePictureBuffer(int32_t picture_buffer_id) {
}
int32_t PPB_VideoDecoder_Impl::Flush(scoped_refptr<TrackedCallback> callback) {
- if (!platform_video_decoder_)
+ if (!platform_video_decoder_.get())
return PP_ERROR_BADRESOURCE;
if (!SetFlushCallback(callback))
@@ -189,7 +189,7 @@ int32_t PPB_VideoDecoder_Impl::Flush(scoped_refptr<TrackedCallback> callback) {
}
int32_t PPB_VideoDecoder_Impl::Reset(scoped_refptr<TrackedCallback> callback) {
- if (!platform_video_decoder_)
+ if (!platform_video_decoder_.get())
return PP_ERROR_BADRESOURCE;
if (!SetResetCallback(callback))
@@ -201,13 +201,12 @@ int32_t PPB_VideoDecoder_Impl::Reset(scoped_refptr<TrackedCallback> callback) {
}
void PPB_VideoDecoder_Impl::Destroy() {
- if (!platform_video_decoder_)
+ if (!platform_video_decoder_.get())
return;
FlushCommandBuffer();
- platform_video_decoder_->Destroy();
+ platform_video_decoder_.release()->Destroy();
::ppapi::PPB_VideoDecoder_Shared::Destroy();
- platform_video_decoder_ = NULL;
ppp_videodecoder_ = NULL;
}
diff --git a/webkit/plugins/ppapi/ppb_video_decoder_impl.h b/webkit/plugins/ppapi/ppb_video_decoder_impl.h
index f82f702..ea29305 100644
--- a/webkit/plugins/ppapi/ppb_video_decoder_impl.h
+++ b/webkit/plugins/ppapi/ppb_video_decoder_impl.h
@@ -73,7 +73,7 @@ class PPB_VideoDecoder_Impl : public ::ppapi::PPB_VideoDecoder_Shared,
// This is NULL before initialization, and if this PPB_VideoDecoder_Impl is
// swapped with another.
- scoped_refptr<PluginDelegate::PlatformVideoDecoder> platform_video_decoder_;
+ scoped_ptr<PluginDelegate::PlatformVideoDecoder> platform_video_decoder_;
// Reference to the plugin requesting this interface.
const PPP_VideoDecoder_Dev* ppp_videodecoder_;