OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "content/browser/aura/browser_compositor_output_surface_capturer.h" |
| 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/location.h" |
| 9 #include "base/message_loop/message_loop_proxy.h" |
| 10 #include "content/browser/aura/browser_compositor_output_surface.h" |
| 11 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h" |
| 12 #include "media/base/video_frame.h" |
| 13 #include "media/base/video_util.h" |
| 14 #include "ui/compositor/compositor.h" |
| 15 |
| 16 const int kNumCaptureBuffers = 2; |
| 17 |
| 18 namespace content { |
| 19 |
| 20 BrowserCompositorOutputSurfaceCapturer::BrowserCompositorOutputSurfaceCapturer( |
| 21 IDMap<BrowserCompositorOutputSurface>* output_surface_map, |
| 22 int output_surface_id, |
| 23 SurfaceCapturer::Client* client) |
| 24 : output_surface_map_(output_surface_map), |
| 25 output_surface_id_(output_surface_id), |
| 26 client_ptr_factory_(client), |
| 27 client_(client_ptr_factory_.GetWeakPtr()), |
| 28 ui_compositor_message_loop_proxy_(base::MessageLoopProxy::current()) { |
| 29 // |compositor_impl_message_loop_proxy_| will be the browser compositor impl |
| 30 // thread, if threaded compositing is turned on. |
| 31 compositor_impl_message_loop_proxy_ = |
| 32 ui::Compositor::GetCompositorMessageLoop(); |
| 33 if (!compositor_impl_message_loop_proxy_) |
| 34 compositor_impl_message_loop_proxy_ = ui_compositor_message_loop_proxy_; |
| 35 } |
| 36 |
| 37 BrowserCompositorOutputSurfaceCapturer:: |
| 38 ~BrowserCompositorOutputSurfaceCapturer() { |
| 39 DCHECK(compositor_impl_message_loop_proxy_->BelongsToCurrentThread()); |
| 40 DCHECK(!capturer_); |
| 41 } |
| 42 |
| 43 void BrowserCompositorOutputSurfaceCapturer::Initialize( |
| 44 media::VideoFrame::Format format) { |
| 45 DCHECK(ui_compositor_message_loop_proxy_->BelongsToCurrentThread()); |
| 46 compositor_impl_message_loop_proxy_->PostTask( |
| 47 FROM_HERE, |
| 48 base::Bind( |
| 49 &BrowserCompositorOutputSurfaceCapturer::DoInitializeOnImplThread, |
| 50 base::Unretained(this), |
| 51 format)); |
| 52 } |
| 53 |
| 54 void BrowserCompositorOutputSurfaceCapturer::TryCapture() { |
| 55 DCHECK(ui_compositor_message_loop_proxy_->BelongsToCurrentThread()); |
| 56 // BrowserCompositorOutputSurfaceCapturer expects to be notified about |
| 57 // backbuffer swaps through NotifySwapBuffersOnImplThread(). The |
| 58 // TryCapture() entry point is ignored. |
| 59 NOTIMPLEMENTED(); |
| 60 } |
| 61 |
| 62 void BrowserCompositorOutputSurfaceCapturer::CopyCaptureToVideoFrame( |
| 63 const scoped_refptr<media::VideoFrame>& frame) { |
| 64 DCHECK(ui_compositor_message_loop_proxy_->BelongsToCurrentThread()); |
| 65 compositor_impl_message_loop_proxy_->PostTask( |
| 66 FROM_HERE, |
| 67 base::Bind(&BrowserCompositorOutputSurfaceCapturer:: |
| 68 DoCopyCaptureToVideoFrameOnImplThread, |
| 69 base::Unretained(this), |
| 70 frame)); |
| 71 } |
| 72 |
| 73 void BrowserCompositorOutputSurfaceCapturer::Destroy() { |
| 74 DCHECK(ui_compositor_message_loop_proxy_->BelongsToCurrentThread()); |
| 75 client_ptr_factory_.InvalidateWeakPtrs(); |
| 76 // Post |this| pointer as owned so we delete this after call. |
| 77 compositor_impl_message_loop_proxy_->PostTask( |
| 78 FROM_HERE, |
| 79 base::Bind(&BrowserCompositorOutputSurfaceCapturer::DoDestroyOnImplThread, |
| 80 base::Owned(this))); |
| 81 } |
| 82 |
| 83 void BrowserCompositorOutputSurfaceCapturer::NotifyCaptureParameters( |
| 84 const gfx::Size& buffer_size, |
| 85 const gfx::Rect& visible_rect) { |
| 86 DCHECK(compositor_impl_message_loop_proxy_->BelongsToCurrentThread()); |
| 87 |
| 88 ui_compositor_message_loop_proxy_->PostTask( |
| 89 FROM_HERE, |
| 90 base::Bind(&SurfaceCapturer::Client::NotifyCaptureParameters, |
| 91 client_, |
| 92 buffer_size, |
| 93 visible_rect)); |
| 94 } |
| 95 |
| 96 void BrowserCompositorOutputSurfaceCapturer::NotifyCopyCaptureDone( |
| 97 const scoped_refptr<media::VideoFrame>& frame) { |
| 98 DCHECK(compositor_impl_message_loop_proxy_->BelongsToCurrentThread()); |
| 99 ui_compositor_message_loop_proxy_->PostTask( |
| 100 FROM_HERE, |
| 101 base::Bind( |
| 102 &SurfaceCapturer::Client::NotifyCopyCaptureDone, client_, frame)); |
| 103 } |
| 104 |
| 105 void BrowserCompositorOutputSurfaceCapturer::NotifyError(Error error) { |
| 106 DLOG(ERROR) << "NotifyError(): error=" << error; |
| 107 DCHECK(compositor_impl_message_loop_proxy_->BelongsToCurrentThread()); |
| 108 ui_compositor_message_loop_proxy_->PostTask( |
| 109 FROM_HERE, |
| 110 base::Bind(&SurfaceCapturer::Client::NotifyError, client_, error)); |
| 111 } |
| 112 |
| 113 void BrowserCompositorOutputSurfaceCapturer::NotifySwapBuffersOnImplThread() { |
| 114 DCHECK(compositor_impl_message_loop_proxy_->BelongsToCurrentThread()); |
| 115 capturer_->TryCapture(); |
| 116 } |
| 117 |
| 118 void BrowserCompositorOutputSurfaceCapturer::DoDestroyOnImplThread() { |
| 119 DCHECK(compositor_impl_message_loop_proxy_->BelongsToCurrentThread()); |
| 120 BrowserCompositorOutputSurface* surface = |
| 121 output_surface_map_->Lookup(output_surface_id_); |
| 122 if (surface) |
| 123 surface->RemoveCapturer(this); |
| 124 if (capturer_) |
| 125 capturer_.release()->Destroy(); |
| 126 } |
| 127 |
| 128 void BrowserCompositorOutputSurfaceCapturer::DoInitializeOnImplThread( |
| 129 media::VideoFrame::Format format) { |
| 130 DCHECK(compositor_impl_message_loop_proxy_->BelongsToCurrentThread()); |
| 131 DCHECK(!capturer_); |
| 132 |
| 133 BrowserCompositorOutputSurface* surface = |
| 134 output_surface_map_->Lookup(output_surface_id_); |
| 135 if (!surface) { |
| 136 NotifyError(kPlatformFailureError); |
| 137 return; |
| 138 } |
| 139 CommandBufferProxyImpl* command_buffer = |
| 140 static_cast<WebGraphicsContext3DCommandBufferImpl*>( |
| 141 surface->context_provider()->Context3d())->GetCommandBufferProxy(); |
| 142 if (!command_buffer) { |
| 143 NotifyError(kPlatformFailureError); |
| 144 return; |
| 145 } |
| 146 capturer_ = command_buffer->CreateSurfaceCapturer(this).Pass(); |
| 147 if (!capturer_) { |
| 148 NotifyError(kPlatformFailureError); |
| 149 return; |
| 150 } |
| 151 surface->AddCapturer(this); |
| 152 capturer_->Initialize(format); |
| 153 } |
| 154 |
| 155 void |
| 156 BrowserCompositorOutputSurfaceCapturer::DoCopyCaptureToVideoFrameOnImplThread( |
| 157 const scoped_refptr<media::VideoFrame>& frame) { |
| 158 DCHECK(compositor_impl_message_loop_proxy_->BelongsToCurrentThread()); |
| 159 capturer_->CopyCaptureToVideoFrame(frame); |
| 160 } |
| 161 |
| 162 } // namespace content |
OLD | NEW |