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/capture/video/linux/video_capture_device_chromeos.h"
8 #include "base/memory/ref_counted.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "ui/gfx/display.h"
12 #include "ui/gfx/display_observer.h"
13 #include "ui/gfx/screen.h"
17 // This is a delegate class used to transfer Display change events from the UI
18 // thread to the media thread.
19 class VideoCaptureDeviceChromeOS::ScreenObserverDelegate
20 : public gfx::DisplayObserver
,
21 public base::RefCountedThreadSafe
<ScreenObserverDelegate
> {
23 ScreenObserverDelegate(
24 VideoCaptureDeviceChromeOS
* capture_device
,
25 scoped_refptr
<base::SingleThreadTaskRunner
> ui_task_runner
)
26 : capture_device_(capture_device
),
27 ui_task_runner_(ui_task_runner
),
28 capture_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
29 ui_task_runner_
->PostTask(
31 base::Bind(&ScreenObserverDelegate::AddObserverOnUIThread
, this));
34 void RemoveObserver() {
35 DCHECK(capture_task_runner_
->BelongsToCurrentThread());
36 capture_device_
= NULL
;
37 ui_task_runner_
->PostTask(
39 base::Bind(&ScreenObserverDelegate::RemoveObserverOnUIThread
, this));
43 friend class base::RefCountedThreadSafe
<ScreenObserverDelegate
>;
45 ~ScreenObserverDelegate() override
{ DCHECK(!capture_device_
); }
47 void OnDisplayAdded(const gfx::Display
& /*new_display*/) override
{}
48 void OnDisplayRemoved(const gfx::Display
& /*old_display*/) override
{}
49 void OnDisplayMetricsChanged(const gfx::Display
& display
,
50 uint32_t metrics
) override
{
51 DCHECK(ui_task_runner_
->BelongsToCurrentThread());
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 // Post the screen rotation change from the UI thread to capture thread
76 void SendDisplayRotation(const gfx::Display
& display
) {
77 DCHECK(ui_task_runner_
->BelongsToCurrentThread());
78 capture_task_runner_
->PostTask(
80 base::Bind(&ScreenObserverDelegate::SendDisplayRotationOnCaptureThread
,
84 void SendDisplayRotationOnCaptureThread(const gfx::Display
& display
) {
85 DCHECK(capture_task_runner_
->BelongsToCurrentThread());
87 capture_device_
->SetDisplayRotation(display
);
90 VideoCaptureDeviceChromeOS
* capture_device_
;
91 scoped_refptr
<base::SingleThreadTaskRunner
> ui_task_runner_
;
92 scoped_refptr
<base::SingleThreadTaskRunner
> capture_task_runner_
;
93 DISALLOW_IMPLICIT_CONSTRUCTORS(ScreenObserverDelegate
);
96 VideoCaptureDeviceChromeOS::VideoCaptureDeviceChromeOS(
97 scoped_refptr
<base::SingleThreadTaskRunner
> ui_task_runner
,
98 const Name
& device_name
)
99 : VideoCaptureDeviceLinux(device_name
),
100 screen_observer_delegate_(
101 new ScreenObserverDelegate(this, ui_task_runner
)) {
104 VideoCaptureDeviceChromeOS::~VideoCaptureDeviceChromeOS() {
105 screen_observer_delegate_
->RemoveObserver();
108 void VideoCaptureDeviceChromeOS::SetDisplayRotation(
109 const gfx::Display
& display
) {
110 if (display
.IsInternal())
111 SetRotation(display
.rotation() * 90);