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 "media/video/capture/linux/video_capture_device_chromeos.h"
8 #include "base/memory/ref_counted.h"
9 #include "base/message_loop/message_loop_proxy.h"
10 #include "ui/gfx/display.h"
11 #include "ui/gfx/display_observer.h"
12 #include "ui/gfx/screen.h"
16 // This is a delegate class used to transfer Display change events from the UI
17 // thread to the media thread.
18 class VideoCaptureDeviceChromeOS::ScreenObserverDelegate
19 : public gfx::DisplayObserver
,
20 public base::RefCountedThreadSafe
<ScreenObserverDelegate
> {
22 ScreenObserverDelegate(
23 VideoCaptureDeviceChromeOS
* capture_device
,
24 scoped_refptr
<base::SingleThreadTaskRunner
> ui_task_runner
)
25 : capture_device_(capture_device
),
26 ui_task_runner_(ui_task_runner
),
27 capture_task_runner_(base::MessageLoopProxy::current()) {
28 ui_task_runner_
->PostTask(
30 base::Bind(&ScreenObserverDelegate::AddObserverOnUIThread
, this));
33 void RemoveObserver() {
34 DCHECK(capture_task_runner_
->BelongsToCurrentThread());
35 capture_device_
= NULL
;
36 ui_task_runner_
->PostTask(
38 base::Bind(&ScreenObserverDelegate::RemoveObserverOnUIThread
, this));
42 friend class base::RefCountedThreadSafe
<ScreenObserverDelegate
>;
44 virtual ~ScreenObserverDelegate() {
45 DCHECK(!capture_device_
);
48 virtual void OnDisplayAdded(const gfx::Display
& /*new_display*/) OVERRIDE
{}
49 virtual void OnDisplayRemoved(const gfx::Display
& /*old_display*/) OVERRIDE
{}
50 virtual void OnDisplayMetricsChanged(const gfx::Display
& display
,
51 uint32_t metrics
) OVERRIDE
{
52 if (!(metrics
& DISPLAY_METRIC_ROTATION
))
54 SendDisplayRotation(display
);
57 void AddObserverOnUIThread() {
58 DCHECK(ui_task_runner_
->BelongsToCurrentThread());
60 gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_ALTERNATE
);
62 screen
->AddObserver(this);
63 SendDisplayRotation(screen
->GetPrimaryDisplay());
67 void RemoveObserverOnUIThread() {
68 DCHECK(ui_task_runner_
->BelongsToCurrentThread());
70 gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_ALTERNATE
);
72 screen
->RemoveObserver(this);
75 void SendDisplayRotation(const gfx::Display
& display
) {
76 DCHECK(capture_task_runner_
->BelongsToCurrentThread());
77 capture_task_runner_
->PostTask(
79 base::Bind(&ScreenObserverDelegate::SendDisplayRotationOnCaptureThread
,
83 void SendDisplayRotationOnCaptureThread(const gfx::Display
& display
) {
84 DCHECK(capture_task_runner_
->BelongsToCurrentThread());
85 capture_device_
->SetDisplayRotation(display
);
88 VideoCaptureDeviceChromeOS
* capture_device_
;
89 scoped_refptr
<base::SingleThreadTaskRunner
> ui_task_runner_
;
90 scoped_refptr
<base::SingleThreadTaskRunner
> capture_task_runner_
;
91 DISALLOW_IMPLICIT_CONSTRUCTORS(ScreenObserverDelegate
);
95 VideoCaptureDeviceChromeOS::VideoCaptureDeviceChromeOS(
96 scoped_refptr
<base::SingleThreadTaskRunner
> ui_task_runner
,
97 const Name
& device_name
)
98 : VideoCaptureDeviceLinux(device_name
),
99 screen_observer_delegate_(new ScreenObserverDelegate(this,
103 VideoCaptureDeviceChromeOS::~VideoCaptureDeviceChromeOS() {
104 screen_observer_delegate_
->RemoveObserver();
107 void VideoCaptureDeviceChromeOS::SetDisplayRotation(
108 const gfx::Display
& display
) {
109 if (display
.IsInternal())
110 SetRotation(display
.rotation() * 90);