diff options
Diffstat (limited to 'content/renderer/media/renderer_gpu_video_decoder_factories.cc')
-rw-r--r-- | content/renderer/media/renderer_gpu_video_decoder_factories.cc | 144 |
1 files changed, 56 insertions, 88 deletions
diff --git a/content/renderer/media/renderer_gpu_video_decoder_factories.cc b/content/renderer/media/renderer_gpu_video_decoder_factories.cc index 1f0e85a..cdd5804 100644 --- a/content/renderer/media/renderer_gpu_video_decoder_factories.cc +++ b/content/renderer/media/renderer_gpu_video_decoder_factories.cc @@ -8,12 +8,12 @@ #include <GLES2/gl2ext.h> #include "base/bind.h" +#include "base/synchronization/waitable_event.h" #include "content/common/child_thread.h" #include "content/common/gpu/client/gpu_channel_host.h" #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h" #include "gpu/command_buffer/client/gles2_implementation.h" #include "gpu/ipc/command_buffer_proxy.h" -#include "third_party/skia/include/core/SkPixelRef.h" namespace content { @@ -23,14 +23,13 @@ RendererGpuVideoDecoderFactories::RendererGpuVideoDecoderFactories( const scoped_refptr<base::MessageLoopProxy>& message_loop, WebGraphicsContext3DCommandBufferImpl* context) : message_loop_(message_loop), - gpu_channel_host_(gpu_channel_host), - aborted_waiter_(true, false), - async_waiter_(false, false) { + gpu_channel_host_(gpu_channel_host) { if (message_loop_->BelongsToCurrentThread()) { - AsyncGetContext(context); + AsyncGetContext(context, NULL); return; } // Threaded compositor requires us to wait for the context to be acquired. + base::WaitableEvent waiter(false, false); message_loop_->PostTask(FROM_HERE, base::Bind( &RendererGpuVideoDecoderFactories::AsyncGetContext, // Unretained to avoid ref/deref'ing |*this|, which is not yet stored in a @@ -41,12 +40,14 @@ RendererGpuVideoDecoderFactories::RendererGpuVideoDecoderFactories( // thread, and only as the result of a PostTask from the render thread // which can only happen after this function returns, so our PostTask will // run first. - context)); - async_waiter_.Wait(); + context, + &waiter)); + waiter.Wait(); } void RendererGpuVideoDecoderFactories::AsyncGetContext( - WebGraphicsContext3DCommandBufferImpl* context) { + WebGraphicsContext3DCommandBufferImpl* context, + base::WaitableEvent* waiter) { context_ = context->AsWeakPtr(); if (context_) { if (context_->makeContextCurrent()) { @@ -55,7 +56,8 @@ void RendererGpuVideoDecoderFactories::AsyncGetContext( context_->insertEventMarkerEXT("GpuVDAContext3D"); } } - async_waiter_.Signal(); + if (waiter) + waiter->Signal(); } media::VideoDecodeAccelerator* @@ -63,36 +65,29 @@ RendererGpuVideoDecoderFactories::CreateVideoDecodeAccelerator( media::VideoCodecProfile profile, media::VideoDecodeAccelerator::Client* client) { DCHECK(!message_loop_->BelongsToCurrentThread()); - // The VDA is returned in the vda_ member variable by the - // AsyncCreateVideoDecodeAccelerator() function. + media::VideoDecodeAccelerator* vda = NULL; + base::WaitableEvent waiter(false, false); message_loop_->PostTask(FROM_HERE, base::Bind( &RendererGpuVideoDecoderFactories::AsyncCreateVideoDecodeAccelerator, - this, profile, client)); - - base::WaitableEvent* objects[] = {&aborted_waiter_, &async_waiter_}; - if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) { - // If we are aborting and the VDA is created by the - // AsyncCreateVideoDecodeAccelerator() function later we need to ensure - // that it is destroyed on the same thread. - message_loop_->PostTask(FROM_HERE, base::Bind( - &RendererGpuVideoDecoderFactories::AsyncDestroyVideoDecodeAccelerator, - this)); - return NULL; - } - return vda_.release(); + this, profile, client, &vda, &waiter)); + waiter.Wait(); + return vda; } void RendererGpuVideoDecoderFactories::AsyncCreateVideoDecodeAccelerator( media::VideoCodecProfile profile, - media::VideoDecodeAccelerator::Client* client) { + media::VideoDecodeAccelerator::Client* client, + media::VideoDecodeAccelerator** vda, + base::WaitableEvent* waiter) { DCHECK(message_loop_->BelongsToCurrentThread()); - if (context_ && context_->GetCommandBufferProxy()) { - vda_.reset(gpu_channel_host_->CreateVideoDecoder( + *vda = gpu_channel_host_->CreateVideoDecoder( context_->GetCommandBufferProxy()->GetRouteID(), - profile, client)); + profile, client); + } else { + *vda = NULL; } - async_waiter_.Signal(); + waiter->Signal(); } bool RendererGpuVideoDecoderFactories::CreateTextures( @@ -100,32 +95,31 @@ bool RendererGpuVideoDecoderFactories::CreateTextures( std::vector<uint32>* texture_ids, uint32 texture_target) { DCHECK(!message_loop_->BelongsToCurrentThread()); + bool success = false; + base::WaitableEvent waiter(false, false); message_loop_->PostTask(FROM_HERE, base::Bind( &RendererGpuVideoDecoderFactories::AsyncCreateTextures, this, - count, size, texture_target)); - - base::WaitableEvent* objects[] = {&aborted_waiter_, &async_waiter_}; - if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) - return false; - texture_ids->swap(created_textures_); - return true; + count, size, texture_ids, texture_target, &success, &waiter)); + waiter.Wait(); + return success; } void RendererGpuVideoDecoderFactories::AsyncCreateTextures( - int32 count, const gfx::Size& size, uint32 texture_target) { + int32 count, const gfx::Size& size, std::vector<uint32>* texture_ids, + uint32 texture_target, bool* success, base::WaitableEvent* waiter) { DCHECK(message_loop_->BelongsToCurrentThread()); DCHECK(texture_target); - if (!context_) { - async_waiter_.Signal(); + *success = false; + waiter->Signal(); return; } gpu::gles2::GLES2Implementation* gles2 = context_->GetImplementation(); - created_textures_.resize(count); - gles2->GenTextures(count, &created_textures_[0]); + texture_ids->resize(count); + gles2->GenTextures(count, &texture_ids->at(0)); for (int i = 0; i < count; ++i) { gles2->ActiveTexture(GL_TEXTURE0); - uint32 texture_id = created_textures_[i]; + uint32 texture_id = texture_ids->at(i); gles2->BindTexture(texture_target, texture_id); gles2->TexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); gles2->TexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -141,7 +135,8 @@ void RendererGpuVideoDecoderFactories::AsyncCreateTextures( // reused, this should not be unacceptably expensive. gles2->Flush(); DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR)); - async_waiter_.Signal(); + *success = true; + waiter->Signal(); } void RendererGpuVideoDecoderFactories::DeleteTexture(uint32 texture_id) { @@ -154,7 +149,6 @@ void RendererGpuVideoDecoderFactories::AsyncDeleteTexture(uint32 texture_id) { DCHECK(message_loop_->BelongsToCurrentThread()); if (!context_) return; - gpu::gles2::GLES2Implementation* gles2 = context_->GetImplementation(); gles2->DeleteTextures(1, &texture_id); DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR)); @@ -162,33 +156,24 @@ void RendererGpuVideoDecoderFactories::AsyncDeleteTexture(uint32 texture_id) { void RendererGpuVideoDecoderFactories::ReadPixels( uint32 texture_id, uint32 texture_target, const gfx::Size& size, - const SkBitmap& pixels) { - // SkBitmaps use the SkPixelRef object to refcount the underlying pixels. - // Multiple SkBitmaps can share a SkPixelRef instance. We use this to - // ensure that the underlying pixels in the SkBitmap passed in remain valid - // until the AsyncReadPixels() call completes. - read_pixels_bitmap_.setPixelRef(pixels.pixelRef()); - + void* pixels) { + base::WaitableEvent waiter(false, false); if (!message_loop_->BelongsToCurrentThread()) { message_loop_->PostTask(FROM_HERE, base::Bind( &RendererGpuVideoDecoderFactories::AsyncReadPixels, this, - texture_id, texture_target, size)); - base::WaitableEvent* objects[] = {&aborted_waiter_, &async_waiter_}; - if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) - return; + texture_id, texture_target, size, pixels, &waiter)); + waiter.Wait(); } else { - AsyncReadPixels(texture_id, texture_target, size); + AsyncReadPixels(texture_id, texture_target, size, pixels, &waiter); } - read_pixels_bitmap_.setPixelRef(NULL); } void RendererGpuVideoDecoderFactories::AsyncReadPixels( - uint32 texture_id, uint32 texture_target, const gfx::Size& size) { + uint32 texture_id, uint32 texture_target, const gfx::Size& size, + void* pixels, base::WaitableEvent* waiter) { DCHECK(message_loop_->BelongsToCurrentThread()); - if (!context_) { - async_waiter_.Signal(); + if (!context_) return; - } gpu::gles2::GLES2Implementation* gles2 = context_->GetImplementation(); @@ -209,33 +194,30 @@ void RendererGpuVideoDecoderFactories::AsyncReadPixels( texture_target, tmp_texture, 0); gles2->PixelStorei(GL_PACK_ALIGNMENT, 4); gles2->ReadPixels(0, 0, size.width(), size.height(), GL_BGRA_EXT, - GL_UNSIGNED_BYTE, read_pixels_bitmap_.pixelRef()->pixels()); + GL_UNSIGNED_BYTE, pixels); gles2->DeleteFramebuffers(1, &fb); gles2->DeleteTextures(1, &tmp_texture); DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR)); - async_waiter_.Signal(); + waiter->Signal(); } base::SharedMemory* RendererGpuVideoDecoderFactories::CreateSharedMemory( size_t size) { DCHECK_NE(MessageLoop::current(), ChildThread::current()->message_loop()); + base::SharedMemory* shm = NULL; + base::WaitableEvent waiter(false, false); ChildThread::current()->message_loop()->PostTask(FROM_HERE, base::Bind( &RendererGpuVideoDecoderFactories::AsyncCreateSharedMemory, this, - size)); - - base::WaitableEvent* objects[] = {&aborted_waiter_, &async_waiter_}; - if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) - return NULL; - return shared_memory_segment_.release(); + size, &shm, &waiter)); + waiter.Wait(); + return shm; } void RendererGpuVideoDecoderFactories::AsyncCreateSharedMemory( - size_t size) { + size_t size, base::SharedMemory** shm, base::WaitableEvent* waiter) { DCHECK_EQ(MessageLoop::current(), ChildThread::current()->message_loop()); - - shared_memory_segment_.reset( - ChildThread::current()->AllocateSharedMemory(size)); - async_waiter_.Signal(); + *shm = ChildThread::current()->AllocateSharedMemory(size); + waiter->Signal(); } scoped_refptr<base::MessageLoopProxy> @@ -243,18 +225,4 @@ RendererGpuVideoDecoderFactories::GetMessageLoop() { return message_loop_; } -void RendererGpuVideoDecoderFactories::Abort() { - aborted_waiter_.Signal(); -} - -bool RendererGpuVideoDecoderFactories::IsAborted() { - return aborted_waiter_.IsSignaled(); -} - -void RendererGpuVideoDecoderFactories::AsyncDestroyVideoDecodeAccelerator() { - // OK to release because Destroy() will delete the VDA instance. - if (vda_) - vda_.release()->Destroy(); -} - } // namespace content |