Index: content/browser/aura/browser_compositor_output_surface_capturer.cc |
diff --git a/content/browser/aura/browser_compositor_output_surface_capturer.cc b/content/browser/aura/browser_compositor_output_surface_capturer.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ad9dc6bfabb1d729fe65ef2e0495c92251eb82d3 |
--- /dev/null |
+++ b/content/browser/aura/browser_compositor_output_surface_capturer.cc |
@@ -0,0 +1,162 @@ |
+// Copyright (c) 2013 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/browser/aura/browser_compositor_output_surface_capturer.h" |
+ |
+#include "base/bind.h" |
+#include "base/location.h" |
+#include "base/message_loop/message_loop_proxy.h" |
+#include "content/browser/aura/browser_compositor_output_surface.h" |
+#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h" |
+#include "media/base/video_frame.h" |
+#include "media/base/video_util.h" |
+#include "ui/compositor/compositor.h" |
+ |
+const int kNumCaptureBuffers = 2; |
+ |
+namespace content { |
+ |
+BrowserCompositorOutputSurfaceCapturer::BrowserCompositorOutputSurfaceCapturer( |
+ IDMap<BrowserCompositorOutputSurface>* output_surface_map, |
+ int output_surface_id, |
+ SurfaceCapturer::Client* client) |
+ : output_surface_map_(output_surface_map), |
+ output_surface_id_(output_surface_id), |
+ client_ptr_factory_(client), |
+ client_(client_ptr_factory_.GetWeakPtr()), |
+ ui_compositor_message_loop_proxy_(base::MessageLoopProxy::current()) { |
+ // |compositor_impl_message_loop_proxy_| will be the browser compositor impl |
+ // thread, if threaded compositing is turned on. |
+ compositor_impl_message_loop_proxy_ = |
+ ui::Compositor::GetCompositorMessageLoop(); |
+ if (!compositor_impl_message_loop_proxy_) |
+ compositor_impl_message_loop_proxy_ = ui_compositor_message_loop_proxy_; |
+} |
+ |
+BrowserCompositorOutputSurfaceCapturer:: |
+ ~BrowserCompositorOutputSurfaceCapturer() { |
+ DCHECK(compositor_impl_message_loop_proxy_->BelongsToCurrentThread()); |
+ DCHECK(!capturer_); |
+} |
+ |
+void BrowserCompositorOutputSurfaceCapturer::Initialize( |
+ media::VideoFrame::Format format) { |
+ DCHECK(ui_compositor_message_loop_proxy_->BelongsToCurrentThread()); |
+ compositor_impl_message_loop_proxy_->PostTask( |
+ FROM_HERE, |
+ base::Bind( |
+ &BrowserCompositorOutputSurfaceCapturer::DoInitializeOnImplThread, |
+ base::Unretained(this), |
+ format)); |
+} |
+ |
+void BrowserCompositorOutputSurfaceCapturer::TryCapture() { |
+ DCHECK(ui_compositor_message_loop_proxy_->BelongsToCurrentThread()); |
+ // BrowserCompositorOutputSurfaceCapturer expects to be notified about |
+ // backbuffer swaps through NotifySwapBuffersOnImplThread(). The |
+ // TryCapture() entry point is ignored. |
+ NOTIMPLEMENTED(); |
+} |
+ |
+void BrowserCompositorOutputSurfaceCapturer::CopyCaptureToVideoFrame( |
+ const scoped_refptr<media::VideoFrame>& frame) { |
+ DCHECK(ui_compositor_message_loop_proxy_->BelongsToCurrentThread()); |
+ compositor_impl_message_loop_proxy_->PostTask( |
+ FROM_HERE, |
+ base::Bind(&BrowserCompositorOutputSurfaceCapturer:: |
+ DoCopyCaptureToVideoFrameOnImplThread, |
+ base::Unretained(this), |
+ frame)); |
+} |
+ |
+void BrowserCompositorOutputSurfaceCapturer::Destroy() { |
+ DCHECK(ui_compositor_message_loop_proxy_->BelongsToCurrentThread()); |
+ client_ptr_factory_.InvalidateWeakPtrs(); |
+ // Post |this| pointer as owned so we delete this after call. |
+ compositor_impl_message_loop_proxy_->PostTask( |
+ FROM_HERE, |
+ base::Bind(&BrowserCompositorOutputSurfaceCapturer::DoDestroyOnImplThread, |
+ base::Owned(this))); |
+} |
+ |
+void BrowserCompositorOutputSurfaceCapturer::NotifyCaptureParameters( |
+ const gfx::Size& buffer_size, |
+ const gfx::Rect& visible_rect) { |
+ DCHECK(compositor_impl_message_loop_proxy_->BelongsToCurrentThread()); |
+ |
+ ui_compositor_message_loop_proxy_->PostTask( |
+ FROM_HERE, |
+ base::Bind(&SurfaceCapturer::Client::NotifyCaptureParameters, |
+ client_, |
+ buffer_size, |
+ visible_rect)); |
+} |
+ |
+void BrowserCompositorOutputSurfaceCapturer::NotifyCopyCaptureDone( |
+ const scoped_refptr<media::VideoFrame>& frame) { |
+ DCHECK(compositor_impl_message_loop_proxy_->BelongsToCurrentThread()); |
+ ui_compositor_message_loop_proxy_->PostTask( |
+ FROM_HERE, |
+ base::Bind( |
+ &SurfaceCapturer::Client::NotifyCopyCaptureDone, client_, frame)); |
+} |
+ |
+void BrowserCompositorOutputSurfaceCapturer::NotifyError(Error error) { |
+ DLOG(ERROR) << "NotifyError(): error=" << error; |
+ DCHECK(compositor_impl_message_loop_proxy_->BelongsToCurrentThread()); |
+ ui_compositor_message_loop_proxy_->PostTask( |
+ FROM_HERE, |
+ base::Bind(&SurfaceCapturer::Client::NotifyError, client_, error)); |
+} |
+ |
+void BrowserCompositorOutputSurfaceCapturer::NotifySwapBuffersOnImplThread() { |
+ DCHECK(compositor_impl_message_loop_proxy_->BelongsToCurrentThread()); |
+ capturer_->TryCapture(); |
+} |
+ |
+void BrowserCompositorOutputSurfaceCapturer::DoDestroyOnImplThread() { |
+ DCHECK(compositor_impl_message_loop_proxy_->BelongsToCurrentThread()); |
+ BrowserCompositorOutputSurface* surface = |
+ output_surface_map_->Lookup(output_surface_id_); |
+ if (surface) |
+ surface->RemoveCapturer(this); |
+ if (capturer_) |
+ capturer_.release()->Destroy(); |
+} |
+ |
+void BrowserCompositorOutputSurfaceCapturer::DoInitializeOnImplThread( |
+ media::VideoFrame::Format format) { |
+ DCHECK(compositor_impl_message_loop_proxy_->BelongsToCurrentThread()); |
+ DCHECK(!capturer_); |
+ |
+ BrowserCompositorOutputSurface* surface = |
+ output_surface_map_->Lookup(output_surface_id_); |
+ if (!surface) { |
+ NotifyError(kPlatformFailureError); |
+ return; |
+ } |
+ CommandBufferProxyImpl* command_buffer = |
+ static_cast<WebGraphicsContext3DCommandBufferImpl*>( |
+ surface->context_provider()->Context3d())->GetCommandBufferProxy(); |
+ if (!command_buffer) { |
+ NotifyError(kPlatformFailureError); |
+ return; |
+ } |
+ capturer_ = command_buffer->CreateSurfaceCapturer(this).Pass(); |
+ if (!capturer_) { |
+ NotifyError(kPlatformFailureError); |
+ return; |
+ } |
+ surface->AddCapturer(this); |
+ capturer_->Initialize(format); |
+} |
+ |
+void |
+BrowserCompositorOutputSurfaceCapturer::DoCopyCaptureToVideoFrameOnImplThread( |
+ const scoped_refptr<media::VideoFrame>& frame) { |
+ DCHECK(compositor_impl_message_loop_proxy_->BelongsToCurrentThread()); |
+ capturer_->CopyCaptureToVideoFrame(frame); |
+} |
+ |
+} // namespace content |