1 // Copyright 2014 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.
5 #include "remoting/host/chromeos/aura_desktop_capturer.h"
9 #include "cc/output/copy_output_request.h"
10 #include "cc/output/copy_output_result.h"
11 #include "third_party/skia/include/core/SkBitmap.h"
12 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
13 #include "ui/aura/window.h"
14 #include "ui/aura/window_tree_host.h"
20 // DesktopFrame implementation used by screen capture on ChromeOS.
21 // Frame data is stored in a SkBitmap.
22 class SkiaBitmapDesktopFrame
: public webrtc::DesktopFrame
{
24 static SkiaBitmapDesktopFrame
* Create(scoped_ptr
<SkBitmap
> bitmap
);
25 virtual ~SkiaBitmapDesktopFrame();
28 SkiaBitmapDesktopFrame(webrtc::DesktopSize size
,
31 scoped_ptr
<SkBitmap
> bitmap
);
33 scoped_ptr
<SkBitmap
> bitmap_
;
35 DISALLOW_COPY_AND_ASSIGN(SkiaBitmapDesktopFrame
);
39 SkiaBitmapDesktopFrame
* SkiaBitmapDesktopFrame::Create(
40 scoped_ptr
<SkBitmap
> bitmap
) {
42 webrtc::DesktopSize
size(bitmap
->width(), bitmap
->height());
43 DCHECK_EQ(kRGBA_8888_SkColorType
, bitmap
->info().colorType())
44 << "DesktopFrame objects always hold RGBA data.";
46 uint8_t* bitmap_data
= reinterpret_cast<uint8_t*>(bitmap
->getPixels());
48 SkiaBitmapDesktopFrame
* result
= new SkiaBitmapDesktopFrame(
49 size
, bitmap
->rowBytes(), bitmap_data
, bitmap
.Pass());
54 SkiaBitmapDesktopFrame::SkiaBitmapDesktopFrame(webrtc::DesktopSize size
,
57 scoped_ptr
<SkBitmap
> bitmap
)
58 : DesktopFrame(size
, stride
, data
, NULL
), bitmap_(bitmap
.Pass()) {
61 SkiaBitmapDesktopFrame::~SkiaBitmapDesktopFrame() {
66 AuraDesktopCapturer::AuraDesktopCapturer()
67 : callback_(NULL
), desktop_window_(NULL
), weak_factory_(this) {
70 AuraDesktopCapturer::~AuraDesktopCapturer() {
73 void AuraDesktopCapturer::Start(webrtc::DesktopCapturer::Callback
* callback
) {
74 if (ash::Shell::HasInstance()) {
75 // TODO(kelvinp): Use ash::Shell::GetAllRootWindows() when multiple monitor
76 // support is implemented.
77 desktop_window_
= ash::Shell::GetPrimaryRootWindow();
78 DCHECK(desktop_window_
) << "Failed to retrieve the Aura Shell root window";
81 DCHECK(!callback_
) << "Start() can only be called once";
86 void AuraDesktopCapturer::Capture(const webrtc::DesktopRegion
&) {
87 scoped_ptr
<cc::CopyOutputRequest
> request
=
88 cc::CopyOutputRequest::CreateBitmapRequest(
90 &AuraDesktopCapturer::OnFrameCaptured
,
91 weak_factory_
.GetWeakPtr()));
93 gfx::Rect
window_rect(desktop_window_
->bounds().size());
95 request
->set_area(window_rect
);
96 desktop_window_
->layer()->RequestCopyOfOutput(request
.Pass());
99 void AuraDesktopCapturer::OnFrameCaptured(
100 scoped_ptr
<cc::CopyOutputResult
> result
) {
101 DCHECK(result
->HasBitmap());
103 scoped_ptr
<SkBitmap
> bitmap
= result
->TakeBitmap();
105 scoped_ptr
<webrtc::DesktopFrame
> frame(
106 SkiaBitmapDesktopFrame::Create(bitmap
.Pass()));
108 // |VideoScheduler| will not encode the frame if |updated_region| is empty.
109 const webrtc::DesktopRect
& rect
= webrtc::DesktopRect::MakeWH(
110 frame
->size().width(), frame
->size().height());
112 // TODO(kelvinp): Set Frame DPI according to the screen resolution.
113 // See cc::Layer::contents_scale_(x|y)() and frame->set_depi().
114 frame
->mutable_updated_region()->SetRect(rect
);
116 callback_
->OnCaptureCompleted(frame
.release());
119 } // namespace remoting