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: 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 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 44 virtual ~ScreenObserverDelegate() { 45 DCHECK(!capture_device_); 46 } 47 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 DCHECK(ui_task_runner_->BelongsToCurrentThread()); 53 if (!(metrics & DISPLAY_METRIC_ROTATION)) 54 return; 55 SendDisplayRotation(display); 56 } 57 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 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 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 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 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 106 VideoCaptureDeviceChromeOS::~VideoCaptureDeviceChromeOS() { 107 screen_observer_delegate_->RemoveObserver(); 108 } 109 110 void VideoCaptureDeviceChromeOS::SetDisplayRotation( 111 const gfx::Display& display) { 112 if (display.IsInternal()) 113 SetRotation(display.rotation() * 90); 114 } 115 116 } // namespace media 117