diff options
author | Torne (Richard Coles) <torne@google.com> | 2014-08-28 12:05:23 +0100 |
---|---|---|
committer | Torne (Richard Coles) <torne@google.com> | 2014-08-28 12:05:23 +0100 |
commit | 03b57e008b61dfcb1fbad3aea950ae0e001748b0 (patch) | |
tree | 9a740c1a5fbe659ec83484b67cbc679332f5a408 /content/common/gpu | |
parent | ca7d0c81aa30d24514c34c963f43cd24da34a2bf (diff) | |
download | chromium_org-03b57e008b61dfcb1fbad3aea950ae0e001748b0.tar.gz |
Merge from Chromium at DEPS revision 291560
This commit was generated by merge_to_master.py.
Change-Id: Ic58269055810d51286b4109e59b90b6856887a30
Diffstat (limited to 'content/common/gpu')
30 files changed, 543 insertions, 184 deletions
diff --git a/content/common/gpu/client/command_buffer_proxy_impl.cc b/content/common/gpu/client/command_buffer_proxy_impl.cc index 74a4089e56..7959fda688 100644 --- a/content/common/gpu/client/command_buffer_proxy_impl.cc +++ b/content/common/gpu/client/command_buffer_proxy_impl.cc @@ -194,7 +194,8 @@ void CommandBufferProxyImpl::Flush(int32 put_offset) { void CommandBufferProxyImpl::SetLatencyInfo( const std::vector<ui::LatencyInfo>& latency_info) { - if (last_state_.error != gpu::error::kNoError) + if (last_state_.error != gpu::error::kNoError || + latency_info.empty()) return; Send(new GpuCommandBufferMsg_SetLatencyInfo(route_id_, latency_info)); } diff --git a/content/common/gpu/client/gpu_channel_host.cc b/content/common/gpu/client/gpu_channel_host.cc index 492e6965b7..d0ceecd262 100644 --- a/content/common/gpu/client/gpu_channel_host.cc +++ b/content/common/gpu/client/gpu_channel_host.cc @@ -304,6 +304,10 @@ gfx::GpuMemoryBufferHandle GpuChannelHost::ShareGpuMemoryBufferToGpuProcess( handle.handle = ShareToGpuProcess(source_handle.handle); return handle; } +#if defined(USE_OZONE) + case gfx::OZONE_NATIVE_BUFFER: + return source_handle; +#endif #if defined(OS_MACOSX) case gfx::IO_SURFACE_BUFFER: return source_handle; diff --git a/content/common/gpu/client/gpu_memory_buffer_factory_host.cc b/content/common/gpu/client/gpu_memory_buffer_factory_host.cc new file mode 100644 index 0000000000..ea7a321d1c --- /dev/null +++ b/content/common/gpu/client/gpu_memory_buffer_factory_host.cc @@ -0,0 +1,27 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/common/gpu/client/gpu_memory_buffer_factory_host.h" + +#include "base/logging.h" + +namespace content { +namespace { +GpuMemoryBufferFactoryHost* instance = NULL; +} + +// static +GpuMemoryBufferFactoryHost* GpuMemoryBufferFactoryHost::GetInstance() { + return instance; +} + +GpuMemoryBufferFactoryHost::GpuMemoryBufferFactoryHost() { + DCHECK(instance == NULL); + instance = this; +} + +GpuMemoryBufferFactoryHost::~GpuMemoryBufferFactoryHost() { + instance = NULL; +} +} diff --git a/content/common/gpu/client/gpu_memory_buffer_factory_host.h b/content/common/gpu/client/gpu_memory_buffer_factory_host.h index 6dfd58beab..9e616e27e6 100644 --- a/content/common/gpu/client/gpu_memory_buffer_factory_host.h +++ b/content/common/gpu/client/gpu_memory_buffer_factory_host.h @@ -6,6 +6,7 @@ #define CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_FACTORY_HOST_H_ #include "base/callback.h" +#include "content/common/content_export.h" namespace gfx { class Size; @@ -19,6 +20,8 @@ class CONTENT_EXPORT GpuMemoryBufferFactoryHost { typedef base::Callback<void(const gfx::GpuMemoryBufferHandle& handle)> CreateGpuMemoryBufferCallback; + static GpuMemoryBufferFactoryHost* GetInstance(); + virtual void CreateGpuMemoryBuffer( const gfx::GpuMemoryBufferHandle& handle, const gfx::Size& size, @@ -29,7 +32,8 @@ class CONTENT_EXPORT GpuMemoryBufferFactoryHost { int32 sync_point) = 0; protected: - virtual ~GpuMemoryBufferFactoryHost() {} + GpuMemoryBufferFactoryHost(); + virtual ~GpuMemoryBufferFactoryHost(); }; } // namespace content diff --git a/content/common/gpu/client/gpu_memory_buffer_impl.h b/content/common/gpu/client/gpu_memory_buffer_impl.h index 2565c02653..e3323f0fed 100644 --- a/content/common/gpu/client/gpu_memory_buffer_impl.h +++ b/content/common/gpu/client/gpu_memory_buffer_impl.h @@ -27,12 +27,13 @@ class GpuMemoryBufferImpl : public gfx::GpuMemoryBuffer { unsigned usage); // Allocates a GPU memory buffer with |size| and |internalformat| for |usage| - // by |child_process|. The |handle| returned can be used by the - // |child_process| to create an instance of this class. + // by |child_process| identified by |child_id|. The |handle| returned can be + // used by the |child_process| to create an instance of this class. static void AllocateForChildProcess(const gfx::Size& size, unsigned internalformat, unsigned usage, base::ProcessHandle child_process, + int child_id, const AllocationCallback& callback); // Notify that GPU memory buffer has been deleted by |child_process|. diff --git a/content/common/gpu/client/gpu_memory_buffer_impl_android.cc b/content/common/gpu/client/gpu_memory_buffer_impl_android.cc index 44efda0861..799eff5334 100644 --- a/content/common/gpu/client/gpu_memory_buffer_impl_android.cc +++ b/content/common/gpu/client/gpu_memory_buffer_impl_android.cc @@ -33,6 +33,7 @@ void GpuMemoryBufferImpl::AllocateForChildProcess( unsigned internalformat, unsigned usage, base::ProcessHandle child_process, + int child_id, const AllocationCallback& callback) { if (GpuMemoryBufferImplSharedMemory::IsConfigurationSupported( size, internalformat, usage)) { diff --git a/content/common/gpu/client/gpu_memory_buffer_impl_linux.cc b/content/common/gpu/client/gpu_memory_buffer_impl_linux.cc index 0fc371b99d..5c04cd8d9b 100644 --- a/content/common/gpu/client/gpu_memory_buffer_impl_linux.cc +++ b/content/common/gpu/client/gpu_memory_buffer_impl_linux.cc @@ -32,6 +32,7 @@ void GpuMemoryBufferImpl::AllocateForChildProcess( unsigned internalformat, unsigned usage, base::ProcessHandle child_process, + int child_id, const AllocationCallback& callback) { if (GpuMemoryBufferImplSharedMemory::IsConfigurationSupported( size, internalformat, usage)) { diff --git a/content/common/gpu/client/gpu_memory_buffer_impl_mac.cc b/content/common/gpu/client/gpu_memory_buffer_impl_mac.cc index 24e39a6ce7..11949c9d6f 100644 --- a/content/common/gpu/client/gpu_memory_buffer_impl_mac.cc +++ b/content/common/gpu/client/gpu_memory_buffer_impl_mac.cc @@ -33,6 +33,7 @@ void GpuMemoryBufferImpl::AllocateForChildProcess( unsigned internalformat, unsigned usage, base::ProcessHandle child_process, + int child_id, const AllocationCallback& callback) { if (GpuMemoryBufferImplSharedMemory::IsConfigurationSupported( size, internalformat, usage)) { diff --git a/content/common/gpu/client/gpu_memory_buffer_impl_ozone.cc b/content/common/gpu/client/gpu_memory_buffer_impl_ozone.cc new file mode 100644 index 0000000000..784f75c6c9 --- /dev/null +++ b/content/common/gpu/client/gpu_memory_buffer_impl_ozone.cc @@ -0,0 +1,88 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/common/gpu/client/gpu_memory_buffer_impl.h" + +#include "content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_buffer.h" +#include "content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h" + +namespace content { + +// static +scoped_ptr<GpuMemoryBufferImpl> GpuMemoryBufferImpl::Create( + const gfx::Size& size, + unsigned internalformat, + unsigned usage) { + if (GpuMemoryBufferImplSharedMemory::IsConfigurationSupported( + size, internalformat, usage)) { + scoped_ptr<GpuMemoryBufferImplSharedMemory> buffer( + new GpuMemoryBufferImplSharedMemory(size, internalformat)); + if (!buffer->Initialize()) + return scoped_ptr<GpuMemoryBufferImpl>(); + + return buffer.PassAs<GpuMemoryBufferImpl>(); + } + + return scoped_ptr<GpuMemoryBufferImpl>(); +} + +// static +void GpuMemoryBufferImpl::AllocateForChildProcess( + const gfx::Size& size, + unsigned internalformat, + unsigned usage, + base::ProcessHandle child_process, + int child_id, + const AllocationCallback& callback) { + if (GpuMemoryBufferImplOzoneNativeBuffer::IsConfigurationSupported( + internalformat, usage)) { + GpuMemoryBufferImplOzoneNativeBuffer::AllocateOzoneNativeBufferForChildId( + size, internalformat, usage, child_id, callback); + return; + } + if (GpuMemoryBufferImplSharedMemory::IsConfigurationSupported( + size, internalformat, usage)) { + GpuMemoryBufferImplSharedMemory::AllocateSharedMemoryForChildProcess( + size, internalformat, child_process, callback); + return; + } + + callback.Run(gfx::GpuMemoryBufferHandle()); +} + +// static +void GpuMemoryBufferImpl::DeletedByChildProcess( + gfx::GpuMemoryBufferType type, + const gfx::GpuMemoryBufferId& id, + base::ProcessHandle child_process) { +} + +// static +scoped_ptr<GpuMemoryBufferImpl> GpuMemoryBufferImpl::CreateFromHandle( + const gfx::GpuMemoryBufferHandle& handle, + const gfx::Size& size, + unsigned internalformat) { + switch (handle.type) { + case gfx::SHARED_MEMORY_BUFFER: { + scoped_ptr<GpuMemoryBufferImplSharedMemory> buffer( + new GpuMemoryBufferImplSharedMemory(size, internalformat)); + if (!buffer->InitializeFromHandle(handle)) + return scoped_ptr<GpuMemoryBufferImpl>(); + + return buffer.PassAs<GpuMemoryBufferImpl>(); + } + case gfx::OZONE_NATIVE_BUFFER: { + scoped_ptr<GpuMemoryBufferImplOzoneNativeBuffer> buffer( + new GpuMemoryBufferImplOzoneNativeBuffer(size, internalformat)); + if (!buffer->InitializeFromHandle(handle)) + return scoped_ptr<GpuMemoryBufferImpl>(); + + return buffer.PassAs<GpuMemoryBufferImpl>(); + } + default: + return scoped_ptr<GpuMemoryBufferImpl>(); + } +} + +} // namespace content diff --git a/content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_buffer.cc b/content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_buffer.cc new file mode 100644 index 0000000000..fe2681bf05 --- /dev/null +++ b/content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_buffer.cc @@ -0,0 +1,110 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_buffer.h" + +#include "base/atomic_sequence_num.h" +#include "base/bind.h" +#include "content/common/gpu/client/gpu_memory_buffer_factory_host.h" +#include "ui/gl/gl_bindings.h" + +namespace content { +namespace { + +base::StaticAtomicSequenceNumber g_next_buffer_id; + +} // namespace + +GpuMemoryBufferImplOzoneNativeBuffer::GpuMemoryBufferImplOzoneNativeBuffer( + const gfx::Size& size, + unsigned internalformat) + : GpuMemoryBufferImpl(size, internalformat) { +} + +GpuMemoryBufferImplOzoneNativeBuffer::~GpuMemoryBufferImplOzoneNativeBuffer() { +} + +// static +void GpuMemoryBufferImplOzoneNativeBuffer::AllocateOzoneNativeBufferForChildId( + const gfx::Size& size, + unsigned internalformat, + unsigned usage, + int child_id, + const AllocationCallback& callback) { + gfx::GpuMemoryBufferHandle handle; + // +1 ensures we always get non-zero IDs. + handle.global_id.primary_id = g_next_buffer_id.GetNext() + 1; + handle.global_id.secondary_id = child_id; + handle.type = gfx::OZONE_NATIVE_BUFFER; + GpuMemoryBufferFactoryHost::GetInstance()->CreateGpuMemoryBuffer( + handle, + size, + internalformat, + usage, + base::Bind(&OnGpuMemoryBufferCreated, callback)); +} + +// static +bool GpuMemoryBufferImplOzoneNativeBuffer::IsFormatSupported( + unsigned internalformat) { + switch (internalformat) { + case GL_RGBA8_OES: + return true; + default: + return false; + } +} + +// static +bool GpuMemoryBufferImplOzoneNativeBuffer::IsUsageSupported(unsigned usage) { + switch (usage) { + case GL_IMAGE_SCANOUT_CHROMIUM: + return true; + default: + return false; + } +} + +// static +bool GpuMemoryBufferImplOzoneNativeBuffer::IsConfigurationSupported( + unsigned internalformat, + unsigned usage) { + return IsFormatSupported(internalformat) && IsUsageSupported(usage); +} + +bool GpuMemoryBufferImplOzoneNativeBuffer::InitializeFromHandle( + const gfx::GpuMemoryBufferHandle& handle) { + id_ = handle.global_id; + return true; +} + +void* GpuMemoryBufferImplOzoneNativeBuffer::Map() { + NOTREACHED(); + return NULL; +} + +void GpuMemoryBufferImplOzoneNativeBuffer::Unmap() { + NOTREACHED(); +} + +uint32 GpuMemoryBufferImplOzoneNativeBuffer::GetStride() const { + NOTREACHED(); + return 0; +} + +gfx::GpuMemoryBufferHandle GpuMemoryBufferImplOzoneNativeBuffer::GetHandle() + const { + gfx::GpuMemoryBufferHandle handle; + handle.type = gfx::OZONE_NATIVE_BUFFER; + handle.global_id = id_; + return handle; +} + +void GpuMemoryBufferImplOzoneNativeBuffer::OnGpuMemoryBufferCreated( + const AllocationCallback& callback, + const gfx::GpuMemoryBufferHandle& handle) { + callback.Run(handle); +} + +} // namespace content diff --git a/content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_buffer.h b/content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_buffer.h new file mode 100644 index 0000000000..ab4cc56a18 --- /dev/null +++ b/content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_buffer.h @@ -0,0 +1,52 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_OZONE_H_ +#define CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_OZONE_H_ + +#include "content/common/gpu/client/gpu_memory_buffer_impl.h" + +namespace content { + +// Implementation of GPU memory buffer based on Ozone native buffers. +class GpuMemoryBufferImplOzoneNativeBuffer : public GpuMemoryBufferImpl { + public: + GpuMemoryBufferImplOzoneNativeBuffer(const gfx::Size& size, + unsigned internalformat); + virtual ~GpuMemoryBufferImplOzoneNativeBuffer(); + + // Allocates an Ozone native buffer backed GPU memory buffer with |size| and + // |internalformat| with usage |usage| for use by |child_id|. + static void AllocateOzoneNativeBufferForChildId( + const gfx::Size& size, + unsigned internalformat, + unsigned usage, + int child_id, + const AllocationCallback& callback); + + static bool IsFormatSupported(unsigned internalformat); + static bool IsUsageSupported(unsigned usage); + static bool IsConfigurationSupported(unsigned internalformat, unsigned usage); + + bool InitializeFromHandle(const gfx::GpuMemoryBufferHandle& handle); + + // Overridden from gfx::GpuMemoryBuffer: + virtual void* Map() OVERRIDE; + virtual void Unmap() OVERRIDE; + virtual uint32 GetStride() const OVERRIDE; + virtual gfx::GpuMemoryBufferHandle GetHandle() const OVERRIDE; + + private: + static void OnGpuMemoryBufferCreated( + const AllocationCallback& callback, + const gfx::GpuMemoryBufferHandle& handle); + + gfx::GpuMemoryBufferId id_; + + DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferImplOzoneNativeBuffer); +}; + +} // namespace content + +#endif // CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_OZONE_H_ diff --git a/content/common/gpu/client/gpu_memory_buffer_impl_win.cc b/content/common/gpu/client/gpu_memory_buffer_impl_win.cc index 0fc371b99d..5c04cd8d9b 100644 --- a/content/common/gpu/client/gpu_memory_buffer_impl_win.cc +++ b/content/common/gpu/client/gpu_memory_buffer_impl_win.cc @@ -32,6 +32,7 @@ void GpuMemoryBufferImpl::AllocateForChildProcess( unsigned internalformat, unsigned usage, base::ProcessHandle child_process, + int child_id, const AllocationCallback& callback) { if (GpuMemoryBufferImplSharedMemory::IsConfigurationSupported( size, internalformat, usage)) { 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 8b714b9e19..a784467800 100644 --- a/content/common/gpu/client/gpu_video_decode_accelerator_host.cc +++ b/content/common/gpu/client/gpu_video_decode_accelerator_host.cc @@ -231,11 +231,13 @@ void GpuVideoDecodeAcceleratorHost::OnDismissPictureBuffer( } void GpuVideoDecodeAcceleratorHost::OnPictureReady( - int32 picture_buffer_id, int32 bitstream_buffer_id) { + int32 picture_buffer_id, + int32 bitstream_buffer_id, + const gfx::Rect& visible_rect) { DCHECK(CalledOnValidThread()); if (!client_) return; - media::Picture picture(picture_buffer_id, bitstream_buffer_id); + media::Picture picture(picture_buffer_id, bitstream_buffer_id, visible_rect); client_->PictureReady(picture); } 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 571bd0c94b..e333f6b50b 100644 --- a/content/common/gpu/client/gpu_video_decode_accelerator_host.h +++ b/content/common/gpu/client/gpu_video_decode_accelerator_host.h @@ -64,7 +64,9 @@ class GpuVideoDecodeAcceleratorHost const gfx::Size& dimensions, uint32 texture_target); void OnDismissPictureBuffer(int32 picture_buffer_id); - void OnPictureReady(int32 picture_buffer_id, int32 bitstream_buffer_id); + void OnPictureReady(int32 picture_buffer_id, + int32 bitstream_buffer_id, + const gfx::Rect& visible_rect); void OnFlushDone(); void OnResetDone(); void OnNotifyError(uint32 error); diff --git a/content/common/gpu/gpu_memory_buffer_factory_ozone.cc b/content/common/gpu/gpu_memory_buffer_factory_ozone.cc index 8f4232dc45..ca119e8999 100644 --- a/content/common/gpu/gpu_memory_buffer_factory_ozone.cc +++ b/content/common/gpu/gpu_memory_buffer_factory_ozone.cc @@ -22,9 +22,8 @@ class GpuMemoryBufferFactoryImpl : public GpuMemoryBufferFactory { unsigned usage) OVERRIDE { switch (handle.type) { case gfx::OZONE_NATIVE_BUFFER: - return ui::GpuMemoryBufferFactoryOzoneNativeBuffer::GetInstance() - ->CreateGpuMemoryBuffer( - handle.global_id, size, internalformat, usage) + return ozone_buffer_factory.CreateGpuMemoryBuffer( + handle.global_id, size, internalformat, usage) ? handle : gfx::GpuMemoryBufferHandle(); default: @@ -36,8 +35,7 @@ class GpuMemoryBufferFactoryImpl : public GpuMemoryBufferFactory { const gfx::GpuMemoryBufferHandle& handle) OVERRIDE { switch (handle.type) { case gfx::OZONE_NATIVE_BUFFER: - ui::GpuMemoryBufferFactoryOzoneNativeBuffer::GetInstance() - ->DestroyGpuMemoryBuffer(handle.global_id); + ozone_buffer_factory.DestroyGpuMemoryBuffer(handle.global_id); break; default: NOTREACHED(); @@ -63,14 +61,16 @@ class GpuMemoryBufferFactoryImpl : public GpuMemoryBufferFactory { if (handle.global_id.secondary_id != client_id) return scoped_refptr<gfx::GLImage>(); - return ui::GpuMemoryBufferFactoryOzoneNativeBuffer::GetInstance() - ->CreateImageForGpuMemoryBuffer( - handle.global_id, size, internalformat); + return ozone_buffer_factory.CreateImageForGpuMemoryBuffer( + handle.global_id, size, internalformat); default: NOTREACHED(); return scoped_refptr<gfx::GLImage>(); } } + + private: + ui::GpuMemoryBufferFactoryOzoneNativeBuffer ozone_buffer_factory; }; } // namespace diff --git a/content/common/gpu/gpu_messages.h b/content/common/gpu/gpu_messages.h index 164052e644..a91bd1f419 100644 --- a/content/common/gpu/gpu_messages.h +++ b/content/common/gpu/gpu_messages.h @@ -696,9 +696,10 @@ IPC_MESSAGE_ROUTED1(AcceleratedVideoDecoderHostMsg_DismissPictureBuffer, int32) /* Picture buffer ID */ // Decoder reports that a picture is ready. -IPC_MESSAGE_ROUTED2(AcceleratedVideoDecoderHostMsg_PictureReady, - int32, /* Picture buffer ID */ - int32) /* Bitstream buffer ID */ +IPC_MESSAGE_ROUTED3(AcceleratedVideoDecoderHostMsg_PictureReady, + int32, /* Picture buffer ID */ + int32, /* Bitstream buffer ID */ + gfx::Rect) /* Visible rectangle */ // Confirm decoder has been flushed. IPC_MESSAGE_ROUTED0(AcceleratedVideoDecoderHostMsg_FlushDone) diff --git a/content/common/gpu/image_transport_surface_fbo_mac.mm b/content/common/gpu/image_transport_surface_fbo_mac.mm index c62205c470..fc7e5ec4bf 100644 --- a/content/common/gpu/image_transport_surface_fbo_mac.mm +++ b/content/common/gpu/image_transport_surface_fbo_mac.mm @@ -184,8 +184,6 @@ void ImageTransportSurfaceFBO::UnblockContextAfterPendingSwap() { void ImageTransportSurfaceFBO::OnResize(gfx::Size size, float scale_factor) { - // This trace event is used in gpu_feature_browsertest.cc - the test will need - // to be updated if this event is changed or moved. TRACE_EVENT2("gpu", "ImageTransportSurfaceFBO::OnResize", "old_width", size_.width(), "new_width", size.width()); // Caching |context_| from OnMakeCurrent. It should still be current. @@ -248,8 +246,6 @@ void ImageTransportSurfaceFBO::CreateFramebuffer() { if (has_complete_framebuffer_ && new_rounded_size == rounded_size_) return; - // This trace event is used in gpu_feature_browsertest.cc - the test will need - // to be updated if this event is changed or moved. TRACE_EVENT2("gpu", "ImageTransportSurfaceFBO::CreateFramebuffer", "width", new_rounded_size.width(), "height", new_rounded_size.height()); diff --git a/content/common/gpu/image_transport_surface_mac.mm b/content/common/gpu/image_transport_surface_mac.mm index c193f6f70d..3a48063c7a 100644 --- a/content/common/gpu/image_transport_surface_mac.mm +++ b/content/common/gpu/image_transport_surface_mac.mm @@ -18,7 +18,8 @@ namespace { class DRTSurfaceOSMesa : public gfx::GLSurfaceOSMesa { public: // Size doesn't matter, the surface is resized to the right size later. - DRTSurfaceOSMesa() : GLSurfaceOSMesa(GL_RGBA, gfx::Size(1, 1)) {} + DRTSurfaceOSMesa() + : GLSurfaceOSMesa(gfx::OSMesaSurfaceFormatRGBA, gfx::Size(1, 1)) {} // Implement a subset of GLSurface. virtual bool SwapBuffers() OVERRIDE; diff --git a/content/common/gpu/media/android_video_decode_accelerator.cc b/content/common/gpu/media/android_video_decode_accelerator.cc index b1de5b1354..0eee64152f 100644 --- a/content/common/gpu/media/android_video_decode_accelerator.cc +++ b/content/common/gpu/media/android_video_decode_accelerator.cc @@ -377,9 +377,10 @@ void AndroidVideoDecodeAccelerator::SendCurrentSurfaceToClient( base::MessageLoop::current()->PostTask( FROM_HERE, - base::Bind(&AndroidVideoDecodeAccelerator::NotifyPictureReady, - weak_this_factory_.GetWeakPtr(), - media::Picture(picture_buffer_id, bitstream_id))); + base::Bind( + &AndroidVideoDecodeAccelerator::NotifyPictureReady, + weak_this_factory_.GetWeakPtr(), + media::Picture(picture_buffer_id, bitstream_id, gfx::Rect(size_)))); } void AndroidVideoDecodeAccelerator::Decode( diff --git a/content/common/gpu/media/dxva_video_decode_accelerator.cc b/content/common/gpu/media/dxva_video_decode_accelerator.cc index 2e667d0bd1..1c9f6f313a 100644 --- a/content/common/gpu/media/dxva_video_decode_accelerator.cc +++ b/content/common/gpu/media/dxva_video_decode_accelerator.cc @@ -943,7 +943,8 @@ void DXVAVideoDecodeAccelerator::ProcessPendingSamples() { PLATFORM_FAILURE, ); media::Picture output_picture(index->second->id(), - sample_info.input_buffer_id); + sample_info.input_buffer_id, + gfx::Rect(index->second->size())); base::MessageLoop::current()->PostTask( FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::NotifyPictureReady, diff --git a/content/common/gpu/media/gpu_video_decode_accelerator.cc b/content/common/gpu/media/gpu_video_decode_accelerator.cc index 6ce9330f8c..c1cd5538e1 100644 --- a/content/common/gpu/media/gpu_video_decode_accelerator.cc +++ b/content/common/gpu/media/gpu_video_decode_accelerator.cc @@ -212,7 +212,8 @@ void GpuVideoDecodeAccelerator::PictureReady( if (!Send(new AcceleratedVideoDecoderHostMsg_PictureReady( host_route_id_, picture.picture_buffer_id(), - picture.bitstream_buffer_id()))) { + picture.bitstream_buffer_id(), + picture.visible_rect()))) { DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_PictureReady) failed"; } } diff --git a/content/common/gpu/media/rendering_helper.cc b/content/common/gpu/media/rendering_helper.cc index 7ee940148d..ce2f94b16d 100644 --- a/content/common/gpu/media/rendering_helper.cc +++ b/content/common/gpu/media/rendering_helper.cc @@ -9,6 +9,7 @@ #include <vector> #include "base/bind.h" +#include "base/callback_helpers.h" #include "base/command_line.h" #include "base/mac/scoped_nsautorelease_pool.h" #include "base/message_loop/message_loop.h" @@ -60,6 +61,25 @@ RenderingHelperParams::RenderingHelperParams() {} RenderingHelperParams::~RenderingHelperParams() {} +VideoFrameTexture::VideoFrameTexture(uint32 texture_target, + uint32 texture_id, + const base::Closure& no_longer_needed_cb) + : texture_target_(texture_target), + texture_id_(texture_id), + no_longer_needed_cb_(no_longer_needed_cb) { + DCHECK(!no_longer_needed_cb_.is_null()); +} + +VideoFrameTexture::~VideoFrameTexture() { + base::ResetAndReturn(&no_longer_needed_cb_).Run(); +} + +RenderingHelper::RenderedVideo::RenderedVideo() : last_frame_rendered(false) { +} + +RenderingHelper::RenderedVideo::~RenderedVideo() { +} + // static bool RenderingHelper::InitializeOneOff() { base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); @@ -78,15 +98,15 @@ RenderingHelper::RenderingHelper() { } RenderingHelper::~RenderingHelper() { - CHECK_EQ(clients_.size(), 0U) << "Must call UnInitialize before dtor."; + CHECK_EQ(videos_.size(), 0U) << "Must call UnInitialize before dtor."; Clear(); } void RenderingHelper::Initialize(const RenderingHelperParams& params, base::WaitableEvent* done) { - // Use cients_.size() != 0 as a proxy for the class having already been + // Use videos_.size() != 0 as a proxy for the class having already been // Initialize()'d, and UnInitialize() before continuing. - if (clients_.size()) { + if (videos_.size()) { base::WaitableEvent done(false, false); UnInitialize(&done); done.Wait(); @@ -153,12 +173,12 @@ void RenderingHelper::Initialize(const RenderingHelperParams& params, NULL, gl_surface_, gfx::PreferIntegratedGpu); gl_context_->MakeCurrent(gl_surface_); - clients_ = params.clients; - CHECK_GT(clients_.size(), 0U); - LayoutRenderingAreas(); + CHECK_GT(params.window_sizes.size(), 0U); + videos_.resize(params.window_sizes.size()); + LayoutRenderingAreas(params.window_sizes); if (render_as_thumbnails_) { - CHECK_EQ(clients_.size(), 1U); + CHECK_EQ(videos_.size(), 1U); GLint max_texture_size; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); @@ -370,6 +390,31 @@ void RenderingHelper::RenderThumbnail(uint32 texture_target, ++frame_count_; } +void RenderingHelper::QueueVideoFrame( + size_t window_id, + scoped_refptr<VideoFrameTexture> video_frame) { + CHECK_EQ(base::MessageLoop::current(), message_loop_); + RenderedVideo* video = &videos_[window_id]; + + // Pop the last frame if it has been rendered. + if (video->last_frame_rendered) { + // When last_frame_rendered is true, we should have only one pending frame. + // Since we are going to have a new frame, we can release the pending one. + DCHECK(video->pending_frames.size() == 1); + video->pending_frames.pop(); + video->last_frame_rendered = false; + } + + video->pending_frames.push(video_frame); +} + +void RenderingHelper::DropPendingFrames(size_t window_id) { + CHECK_EQ(base::MessageLoop::current(), message_loop_); + RenderedVideo* video = &videos_[window_id]; + video->pending_frames = std::queue<scoped_refptr<VideoFrameTexture> >(); + video->last_frame_rendered = false; +} + void RenderingHelper::RenderTexture(uint32 texture_target, uint32 texture_id) { // The ExternalOES sampler is bound to GL_TEXTURE1 and the Texture2D sampler // is bound to GL_TEXTURE0. @@ -385,6 +430,7 @@ void RenderingHelper::RenderTexture(uint32 texture_target, uint32 texture_id) { } void RenderingHelper::DeleteTexture(uint32 texture_id) { + CHECK_EQ(base::MessageLoop::current(), message_loop_); glDeleteTextures(1, &texture_id); CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); } @@ -398,7 +444,7 @@ void* RenderingHelper::GetGLDisplay() { } void RenderingHelper::Clear() { - clients_.clear(); + videos_.clear(); message_loop_ = NULL; gl_context_ = NULL; gl_surface_ = NULL; @@ -461,16 +507,30 @@ void RenderingHelper::RenderContent() { CHECK_EQ(base::MessageLoop::current(), message_loop_); glUniform1i(glGetUniformLocation(program_, "tex_flip"), 1); + // Frames that will be returned to the client (via the no_longer_needed_cb) + // after this vector falls out of scope at the end of this method. We need + // to keep references to them until after SwapBuffers() call below. + std::vector<scoped_refptr<VideoFrameTexture> > frames_to_be_returned; + if (render_as_thumbnails_) { // In render_as_thumbnails_ mode, we render the FBO content on the // screen instead of the decoded textures. - GLSetViewPort(render_areas_[0]); + GLSetViewPort(videos_[0].render_area); RenderTexture(GL_TEXTURE_2D, thumbnails_texture_id_); } else { - for (size_t i = 0; i < clients_.size(); ++i) { - if (clients_[i]) { - GLSetViewPort(render_areas_[i]); - clients_[i]->RenderContent(this); + for (size_t i = 0; i < videos_.size(); ++i) { + RenderedVideo* video = &videos_[i]; + if (video->pending_frames.empty()) + continue; + scoped_refptr<VideoFrameTexture> frame = video->pending_frames.front(); + GLSetViewPort(video->render_area); + RenderTexture(frame->texture_target(), frame->texture_id()); + + if (video->pending_frames.size() > 1) { + frames_to_be_returned.push_back(video->pending_frames.front()); + video->pending_frames.pop(); + } else { + video->last_frame_rendered = true; } } } @@ -492,11 +552,12 @@ static void ScaleAndCalculateOffsets(std::vector<int>* lengths, } } -void RenderingHelper::LayoutRenderingAreas() { +void RenderingHelper::LayoutRenderingAreas( + const std::vector<gfx::Size>& window_sizes) { // Find the number of colums and rows. - // The smallest n * n or n * (n + 1) > number of clients. - size_t cols = sqrt(clients_.size() - 1) + 1; - size_t rows = (clients_.size() + cols - 1) / cols; + // The smallest n * n or n * (n + 1) > number of windows. + size_t cols = sqrt(videos_.size() - 1) + 1; + size_t rows = (videos_.size() + cols - 1) / cols; // Find the widths and heights of the grid. std::vector<int> widths(cols); @@ -504,31 +565,30 @@ void RenderingHelper::LayoutRenderingAreas() { std::vector<int> offset_x(cols); std::vector<int> offset_y(rows); - for (size_t i = 0; i < clients_.size(); ++i) { - const gfx::Size& window_size = clients_[i]->GetWindowSize(); - widths[i % cols] = std::max(widths[i % cols], window_size.width()); - heights[i / cols] = std::max(heights[i / cols], window_size.height()); + for (size_t i = 0; i < window_sizes.size(); ++i) { + const gfx::Size& size = window_sizes[i]; + widths[i % cols] = std::max(widths[i % cols], size.width()); + heights[i / cols] = std::max(heights[i / cols], size.height()); } ScaleAndCalculateOffsets(&widths, &offset_x, screen_size_.width()); ScaleAndCalculateOffsets(&heights, &offset_y, screen_size_.height()); // Put each render_area_ in the center of each cell. - render_areas_.clear(); - for (size_t i = 0; i < clients_.size(); ++i) { - const gfx::Size& window_size = clients_[i]->GetWindowSize(); + for (size_t i = 0; i < window_sizes.size(); ++i) { + const gfx::Size& size = window_sizes[i]; float scale = - std::min(static_cast<float>(widths[i % cols]) / window_size.width(), - static_cast<float>(heights[i / cols]) / window_size.height()); + std::min(static_cast<float>(widths[i % cols]) / size.width(), + static_cast<float>(heights[i / cols]) / size.height()); // Don't scale up the texture. scale = std::min(1.0f, scale); - size_t w = scale * window_size.width(); - size_t h = scale * window_size.height(); + size_t w = scale * size.width(); + size_t h = scale * size.height(); size_t x = offset_x[i % cols] + (widths[i % cols] - w) / 2; size_t y = offset_y[i / cols] + (heights[i / cols] - h) / 2; - render_areas_.push_back(gfx::Rect(x, y, w, h)); + videos_[i].render_area = gfx::Rect(x, y, w, h); } } } // namespace content diff --git a/content/common/gpu/media/rendering_helper.h b/content/common/gpu/media/rendering_helper.h index a2dfb1bbf4..6b0013f5b9 100644 --- a/content/common/gpu/media/rendering_helper.h +++ b/content/common/gpu/media/rendering_helper.h @@ -6,6 +6,7 @@ #define CONTENT_COMMON_GPU_MEDIA_RENDERING_HELPER_H_ #include <map> +#include <queue> #include <vector> #include "base/basictypes.h" @@ -24,25 +25,53 @@ class WaitableEvent; namespace content { -struct RenderingHelperParams; +class VideoFrameTexture : public base::RefCounted<VideoFrameTexture> { + public: + uint32 texture_id() const { return texture_id_; } + uint32 texture_target() const { return texture_target_; } + + VideoFrameTexture(uint32 texture_target, + uint32 texture_id, + const base::Closure& no_longer_needed_cb); + + private: + friend class base::RefCounted<VideoFrameTexture>; + + uint32 texture_target_; + uint32 texture_id_; + base::Closure no_longer_needed_cb_; + + ~VideoFrameTexture(); +}; + +struct RenderingHelperParams { + RenderingHelperParams(); + ~RenderingHelperParams(); + + // The rendering FPS. + int rendering_fps; + + // The desired size of each window. We play each stream in its own window + // on the screen. + std::vector<gfx::Size> window_sizes; + + // The members below are only used for the thumbnail mode where all frames + // are rendered in sequence onto one FBO for comparison/verification purposes. + + // Whether the frames are rendered as scaled thumbnails within a + // larger FBO that is in turn rendered to the window. + bool render_as_thumbnails; + // The size of the FBO containing all visible thumbnails. + gfx::Size thumbnails_page_size; + // The size of each thumbnail within the FBO. + gfx::Size thumbnail_size; +}; // Creates and draws textures used by the video decoder. // This class is not thread safe and thus all the methods of this class // (except for ctor/dtor) ensure they're being run on a single thread. class RenderingHelper { public: - // Interface for the content provider of the RenderingHelper. - class Client { - public: - // Callback to tell client to render the content. - virtual void RenderContent(RenderingHelper* helper) = 0; - - // Callback to get the desired window size of the client. - virtual const gfx::Size& GetWindowSize() = 0; - - protected: - virtual ~Client() {} - }; RenderingHelper(); ~RenderingHelper(); @@ -67,9 +96,12 @@ class RenderingHelper { // |texture_target|. void RenderThumbnail(uint32 texture_target, uint32 texture_id); - // Render |texture_id| to the current view port of the screen using target - // |texture_target|. - void RenderTexture(uint32 texture_target, uint32 texture_id); + // Queues the |video_frame| for rendering. + void QueueVideoFrame(size_t window_id, + scoped_refptr<VideoFrameTexture> video_frame); + + // Drops all the pending video frames of the specified window. + void DropPendingFrames(size_t window_id); // Delete |texture_id|. void DeleteTexture(uint32 texture_id); @@ -87,11 +119,33 @@ class RenderingHelper { base::WaitableEvent* done); private: + struct RenderedVideo { + // The rect on the screen where the video will be rendered. + gfx::Rect render_area; + + // True if the last (and the only one) frame in pending_frames has + // been rendered. We keep the last remaining frame in pending_frames even + // after it has been rendered, so that we have something to display if the + // client is falling behind on providing us with new frames during + // timer-driven playback. + bool last_frame_rendered; + + // The video frames pending for rendering. + std::queue<scoped_refptr<VideoFrameTexture> > pending_frames; + + RenderedVideo(); + ~RenderedVideo(); + }; + void Clear(); void RenderContent(); - void LayoutRenderingAreas(); + void LayoutRenderingAreas(const std::vector<gfx::Size>& window_sizes); + + // Render |texture_id| to the current view port of the screen using target + // |texture_target|. + void RenderTexture(uint32 texture_target, uint32 texture_id); // Timer to trigger the RenderContent() repeatly. scoped_ptr<base::RepeatingTimer<RenderingHelper> > render_timer_; @@ -104,10 +158,7 @@ class RenderingHelper { gfx::Size screen_size_; - // The rendering area of each window on the screen. - std::vector<gfx::Rect> render_areas_; - - std::vector<base::WeakPtr<Client> > clients_; + std::vector<RenderedVideo> videos_; bool render_as_thumbnails_; int frame_count_; @@ -121,24 +172,6 @@ class RenderingHelper { DISALLOW_COPY_AND_ASSIGN(RenderingHelper); }; -struct RenderingHelperParams { - RenderingHelperParams(); - ~RenderingHelperParams(); - - // The rendering FPS. - int rendering_fps; - - // The clients who provide the content for rendering. - std::vector<base::WeakPtr<RenderingHelper::Client> > clients; - - // Whether the frames are rendered as scaled thumbnails within a - // larger FBO that is in turn rendered to the window. - bool render_as_thumbnails; - // The size of the FBO containing all visible thumbnails. - gfx::Size thumbnails_page_size; - // The size of each thumbnail within the FBO. - gfx::Size thumbnail_size; -}; } // namespace content #endif // CONTENT_COMMON_GPU_MEDIA_RENDERING_HELPER_H_ diff --git a/content/common/gpu/media/v4l2_image_processor.cc b/content/common/gpu/media/v4l2_image_processor.cc index 1a9dd29218..f988e90421 100644 --- a/content/common/gpu/media/v4l2_image_processor.cc +++ b/content/common/gpu/media/v4l2_image_processor.cc @@ -214,6 +214,7 @@ void V4L2ImageProcessor::DestroyTask() { } bool V4L2ImageProcessor::CreateInputBuffers() { + DVLOG(3) << __func__; DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); DCHECK(!input_streamon_); @@ -284,6 +285,7 @@ bool V4L2ImageProcessor::CreateInputBuffers() { } bool V4L2ImageProcessor::CreateOutputBuffers() { + DVLOG(3) << __func__; DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); DCHECK(!output_streamon_); diff --git a/content/common/gpu/media/v4l2_video_decode_accelerator.cc b/content/common/gpu/media/v4l2_video_decode_accelerator.cc index 315b2f516e..cea1c7b3bb 100644 --- a/content/common/gpu/media/v4l2_video_decode_accelerator.cc +++ b/content/common/gpu/media/v4l2_video_decode_accelerator.cc @@ -1092,7 +1092,9 @@ void V4L2VideoDecodeAccelerator::Dequeue() { DVLOG(3) << "Dequeue(): returning input_id=" << dqbuf.timestamp.tv_sec << " as picture_id=" << output_record.picture_id; const media::Picture& picture = - media::Picture(output_record.picture_id, dqbuf.timestamp.tv_sec); + media::Picture(output_record.picture_id, + dqbuf.timestamp.tv_sec, + gfx::Rect(frame_buffer_size_)); pending_picture_ready_.push( PictureRecord(output_record.cleared, picture)); SendPictureReady(); diff --git a/content/common/gpu/media/v4l2_video_device.cc b/content/common/gpu/media/v4l2_video_device.cc index e9c54229c7..0a094ba6e4 100644 --- a/content/common/gpu/media/v4l2_video_device.cc +++ b/content/common/gpu/media/v4l2_video_device.cc @@ -106,6 +106,11 @@ gfx::Size V4L2Device::CodedSizeFromV4L2Format(struct v4l2_format format) { int horiz_bpp = media::VideoFrame::PlaneHorizontalBitsPerPixel(frame_format, 0); + DVLOG(3) << __func__ << ": bytesperline=" << bytesperline + << ", sizeimage=" << sizeimage + << ", visible_size=" << visible_size.ToString() << ", frame_format=" + << media::VideoFrame::FormatToString(frame_format) + << ", horiz_bpp=" << horiz_bpp; if (sizeimage == 0 || bytesperline == 0 || horiz_bpp == 0 || (bytesperline * 8) % horiz_bpp != 0) { DLOG(ERROR) << "Invalid format provided"; @@ -118,6 +123,7 @@ gfx::Size V4L2Device::CodedSizeFromV4L2Format(struct v4l2_format format) { sizeimage = ((sizeimage + bytesperline - 1) / bytesperline) * bytesperline; coded_size.SetSize(bytesperline * 8 / horiz_bpp, sizeimage / bytesperline); + DVLOG(3) << "coded_size=" << coded_size.ToString(); // Sanity checks. Calculated coded size has to contain given visible size // and fulfill buffer byte size requirements for each plane. @@ -125,11 +131,9 @@ gfx::Size V4L2Device::CodedSizeFromV4L2Format(struct v4l2_format format) { if (V4L2_TYPE_IS_MULTIPLANAR(format.type)) { for (size_t i = 0; i < format.fmt.pix_mp.num_planes; ++i) { - DCHECK_LE( - format.fmt.pix_mp.plane_fmt[i].sizeimage, - media::VideoFrame::PlaneAllocationSize(frame_format, i, coded_size)); - DCHECK_LE(format.fmt.pix_mp.plane_fmt[i].bytesperline, - base::checked_cast<__u32>(coded_size.width())); + DCHECK_EQ(format.fmt.pix_mp.plane_fmt[i].bytesperline, + base::checked_cast<__u32>(media::VideoFrame::RowBytes( + i, frame_format, coded_size.width()))); } } diff --git a/content/common/gpu/media/v4l2_video_encode_accelerator.cc b/content/common/gpu/media/v4l2_video_encode_accelerator.cc index 25320f4603..1f10e840bf 100644 --- a/content/common/gpu/media/v4l2_video_encode_accelerator.cc +++ b/content/common/gpu/media/v4l2_video_encode_accelerator.cc @@ -860,6 +860,7 @@ bool V4L2VideoEncodeAccelerator::SetOutputFormat( bool V4L2VideoEncodeAccelerator::NegotiateInputFormat( media::VideoFrame::Format input_format) { + DVLOG(3) << "NegotiateInputFormat()"; DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); DCHECK(!input_streamon_); DCHECK(!output_streamon_); diff --git a/content/common/gpu/media/vaapi_video_decode_accelerator.cc b/content/common/gpu/media/vaapi_video_decode_accelerator.cc index afcfc8a3b0..0b3001272a 100644 --- a/content/common/gpu/media/vaapi_video_decode_accelerator.cc +++ b/content/common/gpu/media/vaapi_video_decode_accelerator.cc @@ -371,8 +371,11 @@ void VaapiVideoDecodeAccelerator::OutputPicture( TRACE_COUNTER1("Video Decoder", "Textures at client", num_frames_at_client_); DVLOG(4) << "Notifying output picture id " << output_id << " for input "<< input_id << " is ready"; + // TODO(posciak): Use visible size from decoder here instead + // (crbug.com/402760). if (client_) - client_->PictureReady(media::Picture(output_id, input_id)); + client_->PictureReady( + media::Picture(output_id, input_id, gfx::Rect(tfp_picture->size()))); } void VaapiVideoDecodeAccelerator::TryOutputSurface() { diff --git a/content/common/gpu/media/video_decode_accelerator_unittest.cc b/content/common/gpu/media/video_decode_accelerator_unittest.cc index 071dced9f0..65cc9397a6 100644 --- a/content/common/gpu/media/video_decode_accelerator_unittest.cc +++ b/content/common/gpu/media/video_decode_accelerator_unittest.cc @@ -193,9 +193,10 @@ enum ClientState { // the TESTs below. class GLRenderingVDAClient : public VideoDecodeAccelerator::Client, - public RenderingHelper::Client, public base::SupportsWeakPtr<GLRenderingVDAClient> { public: + // |window_id| the window_id of the client, which is used to identify the + // rendering area in the |rendering_helper|. // Doesn't take ownership of |rendering_helper| or |note|, which must outlive // |*this|. // |num_play_throughs| indicates how many times to play through the video. @@ -212,7 +213,8 @@ class GLRenderingVDAClient // will start delaying the call to ReusePictureBuffer() for kReuseDelay. // |decode_calls_per_second| is the number of VDA::Decode calls per second. // If |decode_calls_per_second| > 0, |num_in_flight_decodes| must be 1. - GLRenderingVDAClient(RenderingHelper* rendering_helper, + GLRenderingVDAClient(size_t window_id, + RenderingHelper* rendering_helper, ClientStateNotification<ClientState>* note, const std::string& encoded_data, int num_in_flight_decodes, @@ -242,14 +244,8 @@ class GLRenderingVDAClient virtual void NotifyResetDone() OVERRIDE; virtual void NotifyError(VideoDecodeAccelerator::Error error) OVERRIDE; - // RenderingHelper::Client implementation. - virtual void RenderContent(RenderingHelper*) OVERRIDE; - virtual const gfx::Size& GetWindowSize() OVERRIDE; - void OutputFrameDeliveryTimes(base::File* output); - void NotifyFrameDropped(int32 picture_buffer_id); - // Simple getters for inspecting the state of the Client. int num_done_bitstream_buffers() { return num_done_bitstream_buffers_; } int num_skipped_fragments() { return num_skipped_fragments_; } @@ -285,6 +281,7 @@ class GLRenderingVDAClient // Request decode of the next fragment in the encoded data. void DecodeNextFragment(); + size_t window_id_; RenderingHelper* rendering_helper_; gfx::Size frame_size_; std::string encoded_data_; @@ -319,13 +316,12 @@ class GLRenderingVDAClient // The number of VDA::Decode calls per second. This is to simulate webrtc. int decode_calls_per_second_; bool render_as_thumbnails_; - bool pending_picture_updated_; - std::deque<int32> pending_picture_buffer_ids_; DISALLOW_IMPLICIT_CONSTRUCTORS(GLRenderingVDAClient); }; GLRenderingVDAClient::GLRenderingVDAClient( + size_t window_id, RenderingHelper* rendering_helper, ClientStateNotification<ClientState>* note, const std::string& encoded_data, @@ -340,7 +336,8 @@ GLRenderingVDAClient::GLRenderingVDAClient( int delay_reuse_after_frame_num, int decode_calls_per_second, bool render_as_thumbnails) - : rendering_helper_(rendering_helper), + : window_id_(window_id), + rendering_helper_(rendering_helper), frame_size_(frame_width, frame_height), encoded_data_(encoded_data), num_in_flight_decodes_(num_in_flight_decodes), @@ -360,8 +357,7 @@ GLRenderingVDAClient::GLRenderingVDAClient( suppress_rendering_(suppress_rendering), delay_reuse_after_frame_num_(delay_reuse_after_frame_num), decode_calls_per_second_(decode_calls_per_second), - render_as_thumbnails_(render_as_thumbnails), - pending_picture_updated_(true) { + render_as_thumbnails_(render_as_thumbnails) { CHECK_GT(num_in_flight_decodes, 0); CHECK_GT(num_play_throughs, 0); // |num_in_flight_decodes_| is unsupported if |decode_calls_per_second_| > 0. @@ -459,42 +455,6 @@ void GLRenderingVDAClient::DismissPictureBuffer(int32 picture_buffer_id) { picture_buffers_by_id_.erase(it); } -void GLRenderingVDAClient::RenderContent(RenderingHelper*) { - CHECK(!render_as_thumbnails_); - - // No decoded texture for rendering yet, just skip. - if (pending_picture_buffer_ids_.size() == 0) - return; - - int32 buffer_id = pending_picture_buffer_ids_.front(); - media::PictureBuffer* picture_buffer = picture_buffers_by_id_[buffer_id]; - - CHECK(picture_buffer); - if (!pending_picture_updated_) { - // Frame dropped, just redraw the last texture. - rendering_helper_->RenderTexture(texture_target_, - picture_buffer->texture_id()); - return; - } - - base::TimeTicks now = base::TimeTicks::Now(); - frame_delivery_times_.push_back(now); - - rendering_helper_->RenderTexture(texture_target_, - picture_buffer->texture_id()); - - if (pending_picture_buffer_ids_.size() == 1) { - pending_picture_updated_ = false; - } else { - pending_picture_buffer_ids_.pop_front(); - ReturnPicture(buffer_id); - } -} - -const gfx::Size& GLRenderingVDAClient::GetWindowSize() { - return render_as_thumbnails_ ? kThumbnailsPageSize : frame_size_; -} - void GLRenderingVDAClient::PictureReady(const media::Picture& picture) { // We shouldn't be getting pictures delivered after Reset has completed. CHECK_LT(state_, CS_RESET); @@ -503,6 +463,9 @@ void GLRenderingVDAClient::PictureReady(const media::Picture& picture) { return; base::TimeTicks now = base::TimeTicks::Now(); + + frame_delivery_times_.push_back(now); + // Save the decode time of this picture. std::map<int, base::TimeTicks>::iterator it = decode_start_time_.find(picture.bitstream_buffer_id()); @@ -524,25 +487,22 @@ void GLRenderingVDAClient::PictureReady(const media::Picture& picture) { encoded_data_next_pos_to_decode_ = 0; } + media::PictureBuffer* picture_buffer = + picture_buffers_by_id_[picture.picture_buffer_id()]; + CHECK(picture_buffer); + + scoped_refptr<VideoFrameTexture> video_frame = + new VideoFrameTexture(texture_target_, + picture_buffer->texture_id(), + base::Bind(&GLRenderingVDAClient::ReturnPicture, + AsWeakPtr(), + picture.picture_buffer_id())); + if (render_as_thumbnails_) { - frame_delivery_times_.push_back(now); - media::PictureBuffer* picture_buffer = - picture_buffers_by_id_[picture.picture_buffer_id()]; - CHECK(picture_buffer); - rendering_helper_->RenderThumbnail(texture_target_, - picture_buffer->texture_id()); - ReturnPicture(picture.picture_buffer_id()); + rendering_helper_->RenderThumbnail(video_frame->texture_target(), + video_frame->texture_id()); } else if (!suppress_rendering_) { - // Keep the picture for rendering. - pending_picture_buffer_ids_.push_back(picture.picture_buffer_id()); - if (pending_picture_buffer_ids_.size() > 1 && !pending_picture_updated_) { - ReturnPicture(pending_picture_buffer_ids_.front()); - pending_picture_buffer_ids_.pop_front(); - pending_picture_updated_ = true; - } - } else { - frame_delivery_times_.push_back(now); - ReturnPicture(picture.picture_buffer_id()); + rendering_helper_->QueueVideoFrame(window_id_, video_frame); } } @@ -590,12 +550,7 @@ void GLRenderingVDAClient::NotifyResetDone() { if (decoder_deleted()) return; - // Clear pending_pictures and reuse them. - while (!pending_picture_buffer_ids_.empty()) { - decoder_->ReusePictureBuffer(pending_picture_buffer_ids_.front()); - pending_picture_buffer_ids_.pop_front(); - } - pending_picture_updated_ = true; + rendering_helper_->DropPendingFrames(window_id_); if (reset_after_frame_num_ == MID_STREAM_RESET) { reset_after_frame_num_ = END_OF_STREAM_RESET; @@ -637,10 +592,6 @@ void GLRenderingVDAClient::OutputFrameDeliveryTimes(base::File* output) { } } -void GLRenderingVDAClient::NotifyFrameDropped(int32 picture_buffer_id) { - decoder_->ReusePictureBuffer(picture_buffer_id); -} - static bool LookingAtNAL(const std::string& encoded, size_t pos) { return encoded[pos] == 0 && encoded[pos + 1] == 0 && encoded[pos + 2] == 0 && encoded[pos + 3] == 1; @@ -1127,7 +1078,8 @@ TEST_P(VideoDecodeAcceleratorParamTest, TestSimpleDecode) { } GLRenderingVDAClient* client = - new GLRenderingVDAClient(&rendering_helper_, + new GLRenderingVDAClient(index, + &rendering_helper_, note, video_file->data_str, num_in_flight_decodes, @@ -1143,7 +1095,10 @@ TEST_P(VideoDecodeAcceleratorParamTest, TestSimpleDecode) { render_as_thumbnails); clients[index] = client; - helper_params.clients.push_back(client->AsWeakPtr()); + helper_params.window_sizes.push_back( + render_as_thumbnails + ? kThumbnailsPageSize + : gfx::Size(video_file->width, video_file->height)); } InitializeRenderingHelper(helper_params); @@ -1376,7 +1331,8 @@ TEST_F(VideoDecodeAcceleratorTest, TestDecodeTimeMedian) { ClientStateNotification<ClientState>* note = new ClientStateNotification<ClientState>(); GLRenderingVDAClient* client = - new GLRenderingVDAClient(&rendering_helper_, + new GLRenderingVDAClient(0, + &rendering_helper_, note, test_video_files_[0]->data_str, 1, @@ -1390,7 +1346,8 @@ TEST_F(VideoDecodeAcceleratorTest, TestDecodeTimeMedian) { std::numeric_limits<int>::max(), kWebRtcDecodeCallsPerSecond, false /* render_as_thumbnail */); - helper_params.clients.push_back(client->AsWeakPtr()); + helper_params.window_sizes.push_back( + gfx::Size(test_video_files_[0]->width, test_video_files_[0]->height)); InitializeRenderingHelper(helper_params); CreateAndStartDecoder(client, note); WaitUntilDecodeFinish(note); diff --git a/content/common/gpu/media/vt_video_decode_accelerator.cc b/content/common/gpu/media/vt_video_decode_accelerator.cc index 5b916501b1..8e4c40819c 100644 --- a/content/common/gpu/media/vt_video_decode_accelerator.cc +++ b/content/common/gpu/media/vt_video_decode_accelerator.cc @@ -376,7 +376,8 @@ void VTVideoDecodeAccelerator::SendPictures() { 0)); // plane picture_bindings_[picture_id] = frame.image_buffer; - client_->PictureReady(media::Picture(picture_id, frame.bitstream_id)); + client_->PictureReady(media::Picture( + picture_id, frame.bitstream_id, gfx::Rect(texture_size_))); client_->NotifyEndOfBitstreamBuffer(frame.bitstream_id); } |