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 OnSwapBuffers(). The TryCapture() entry point is |
| 58 // 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:: |
| 80 DoDestroyInternalsOnImplThread, |
| 81 base::Owned(this))); |
| 82 } |
| 83 |
| 84 void BrowserCompositorOutputSurfaceCapturer::NotifyCaptureParameters( |
| 85 const gfx::Size& buffer_size, |
| 86 const gfx::Rect& visible_rect) { |
| 87 DCHECK(compositor_impl_message_loop_proxy_->BelongsToCurrentThread()); |
| 88 |
| 89 ui_compositor_message_loop_proxy_->PostTask( |
| 90 FROM_HERE, |
| 91 base::Bind(&SurfaceCapturer::Client::NotifyCaptureParameters, |
| 92 client_, |
| 93 buffer_size, |
| 94 visible_rect)); |
| 95 } |
| 96 |
| 97 void BrowserCompositorOutputSurfaceCapturer::NotifyCopyCaptureDone( |
| 98 const scoped_refptr<media::VideoFrame>& frame) { |
| 99 DCHECK(compositor_impl_message_loop_proxy_->BelongsToCurrentThread()); |
| 100 ui_compositor_message_loop_proxy_->PostTask( |
| 101 FROM_HERE, |
| 102 base::Bind( |
| 103 &SurfaceCapturer::Client::NotifyCopyCaptureDone, client_, frame)); |
| 104 } |
| 105 |
| 106 void BrowserCompositorOutputSurfaceCapturer::NotifyError(Error error) { |
| 107 DLOG(ERROR) << "NotifyError(): error=" << error; |
| 108 DCHECK(compositor_impl_message_loop_proxy_->BelongsToCurrentThread()); |
| 109 ui_compositor_message_loop_proxy_->PostTask( |
| 110 FROM_HERE, |
| 111 base::Bind(&SurfaceCapturer::Client::NotifyError, client_, error)); |
| 112 } |
| 113 |
| 114 void BrowserCompositorOutputSurfaceCapturer::OnReshape(const gfx::Size& size) { |
| 115 // Ignored. |
| 116 } |
| 117 |
| 118 void BrowserCompositorOutputSurfaceCapturer::OnSwapBuffers() { |
| 119 DCHECK(compositor_impl_message_loop_proxy_->BelongsToCurrentThread()); |
| 120 capturer_->TryCapture(); |
| 121 } |
| 122 |
| 123 void BrowserCompositorOutputSurfaceCapturer::OnPostSubBuffer( |
| 124 const gfx::Rect& rect) { |
| 125 // Ignored |
| 126 } |
| 127 |
| 128 void BrowserCompositorOutputSurfaceCapturer::OnDelete() { |
| 129 DoDestroyInternalsOnImplThread(); |
| 130 } |
| 131 |
| 132 void BrowserCompositorOutputSurfaceCapturer::DoInitializeOnImplThread( |
| 133 media::VideoFrame::Format format) { |
| 134 DCHECK(compositor_impl_message_loop_proxy_->BelongsToCurrentThread()); |
| 135 DCHECK(!capturer_); |
| 136 |
| 137 BrowserCompositorOutputSurface* surface = |
| 138 output_surface_map_->Lookup(output_surface_id_); |
| 139 if (!surface) { |
| 140 NotifyError(kPlatformFailureError); |
| 141 return; |
| 142 } |
| 143 CommandBufferProxyImpl* command_buffer = |
| 144 static_cast<WebGraphicsContext3DCommandBufferImpl*>( |
| 145 surface->context_provider()->Context3d())->GetCommandBufferProxy(); |
| 146 if (!command_buffer) { |
| 147 NotifyError(kPlatformFailureError); |
| 148 return; |
| 149 } |
| 150 capturer_ = command_buffer->CreateSurfaceCapturer(this).Pass(); |
| 151 if (!capturer_) { |
| 152 NotifyError(kPlatformFailureError); |
| 153 return; |
| 154 } |
| 155 surface->AddObserver(this); |
| 156 capturer_->Initialize(format); |
| 157 } |
| 158 |
| 159 void |
| 160 BrowserCompositorOutputSurfaceCapturer::DoCopyCaptureToVideoFrameOnImplThread( |
| 161 const scoped_refptr<media::VideoFrame>& frame) { |
| 162 DCHECK(compositor_impl_message_loop_proxy_->BelongsToCurrentThread()); |
| 163 capturer_->CopyCaptureToVideoFrame(frame); |
| 164 } |
| 165 |
| 166 void BrowserCompositorOutputSurfaceCapturer::DoDestroyInternalsOnImplThread() { |
| 167 DCHECK(compositor_impl_message_loop_proxy_->BelongsToCurrentThread()); |
| 168 BrowserCompositorOutputSurface* surface = |
| 169 output_surface_map_->Lookup(output_surface_id_); |
| 170 if (surface) |
| 171 surface->RemoveObserver(this); |
| 172 if (capturer_) |
| 173 capturer_.release()->Destroy(); |
| 174 } |
| 175 |
| 176 } // namespace content |
OLD | NEW |