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.
4
5 #include "media/video/capture/linux/video_capture_device_chromeos.h"
6
7 #include "base/bind.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"
13
14 namespace media {
15
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> {
21 public:
ScreenObserverDelegate(VideoCaptureDeviceChromeOS * capture_device,scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)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(
29 FROM_HERE,
30 base::Bind(&ScreenObserverDelegate::AddObserverOnUIThread, this));
31 }
32
RemoveObserver()33 void RemoveObserver() {
34 DCHECK(capture_task_runner_->BelongsToCurrentThread());
35 capture_device_ = NULL;
36 ui_task_runner_->PostTask(
37 FROM_HERE,
38 base::Bind(&ScreenObserverDelegate::RemoveObserverOnUIThread, this));
39 }
40
41 private:
42 friend class base::RefCountedThreadSafe<ScreenObserverDelegate>;
43
~ScreenObserverDelegate()44 virtual ~ScreenObserverDelegate() {
45 DCHECK(!capture_device_);
46 }
47
OnDisplayAdded(const gfx::Display &)48 virtual void OnDisplayAdded(const gfx::Display& /*new_display*/) OVERRIDE {}
OnDisplayRemoved(const gfx::Display &)49 virtual void OnDisplayRemoved(const gfx::Display& /*old_display*/) OVERRIDE {}
OnDisplayMetricsChanged(const gfx::Display & display,uint32_t metrics)50 virtual void OnDisplayMetricsChanged(const gfx::Display& display,
51 uint32_t metrics) OVERRIDE {
52 DCHECK(ui_task_runner_->BelongsToCurrentThread());
53 if (!(metrics & DISPLAY_METRIC_ROTATION))
54 return;
55 SendDisplayRotation(display);
56 }
57
AddObserverOnUIThread()58 void AddObserverOnUIThread() {
59 DCHECK(ui_task_runner_->BelongsToCurrentThread());
60 gfx::Screen* screen =
61 gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_ALTERNATE);
62 if (screen) {
63 screen->AddObserver(this);
64 SendDisplayRotation(screen->GetPrimaryDisplay());
65 }
66 }
67
RemoveObserverOnUIThread()68 void RemoveObserverOnUIThread() {
69 DCHECK(ui_task_runner_->BelongsToCurrentThread());
70 gfx::Screen* screen =
71 gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_ALTERNATE);
72 if (screen)
73 screen->RemoveObserver(this);
74 }
75
76 // Post the screen rotation change from the UI thread to capture thread
SendDisplayRotation(const gfx::Display & display)77 void SendDisplayRotation(const gfx::Display& display) {
78 DCHECK(ui_task_runner_->BelongsToCurrentThread());
79 capture_task_runner_->PostTask(
80 FROM_HERE,
81 base::Bind(&ScreenObserverDelegate::SendDisplayRotationOnCaptureThread,
82 this, display));
83 }
84
SendDisplayRotationOnCaptureThread(const gfx::Display & display)85 void SendDisplayRotationOnCaptureThread(const gfx::Display& display) {
86 DCHECK(capture_task_runner_->BelongsToCurrentThread());
87 if (capture_device_)
88 capture_device_->SetDisplayRotation(display);
89 }
90
91 VideoCaptureDeviceChromeOS* capture_device_;
92 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
93 scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner_;
94 DISALLOW_IMPLICIT_CONSTRUCTORS(ScreenObserverDelegate);
95 };
96
97
VideoCaptureDeviceChromeOS(scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,const Name & device_name)98 VideoCaptureDeviceChromeOS::VideoCaptureDeviceChromeOS(
99 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
100 const Name& device_name)
101 : VideoCaptureDeviceLinux(device_name),
102 screen_observer_delegate_(new ScreenObserverDelegate(this,
103 ui_task_runner)) {
104 }
105
~VideoCaptureDeviceChromeOS()106 VideoCaptureDeviceChromeOS::~VideoCaptureDeviceChromeOS() {
107 screen_observer_delegate_->RemoveObserver();
108 }
109
SetDisplayRotation(const gfx::Display & display)110 void VideoCaptureDeviceChromeOS::SetDisplayRotation(
111 const gfx::Display& display) {
112 if (display.IsInternal())
113 SetRotation(display.rotation() * 90);
114 }
115
116 } // namespace media
117