1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// found in the LICENSE file. 4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "media/video/capture/linux/video_capture_device_chromeos.h" 6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/bind.h" 8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/memory/ref_counted.h" 9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h" 10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/gfx/display.h" 11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/gfx/display_observer.h" 12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/gfx/screen.h" 13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace media { 15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// This is a delegate class used to transfer Display change events from the UI 17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// thread to the media thread. 18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class VideoCaptureDeviceChromeOS::ScreenObserverDelegate 19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) : public gfx::DisplayObserver, 20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public base::RefCountedThreadSafe<ScreenObserverDelegate> { 21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public: 22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ScreenObserverDelegate( 23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) VideoCaptureDeviceChromeOS* capture_device, 24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) 25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) : capture_device_(capture_device), 26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ui_task_runner_(ui_task_runner), 27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) capture_task_runner_(base::MessageLoopProxy::current()) { 28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ui_task_runner_->PostTask( 29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FROM_HERE, 30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(&ScreenObserverDelegate::AddObserverOnUIThread, this)); 31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void RemoveObserver() { 34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(capture_task_runner_->BelongsToCurrentThread()); 35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) capture_device_ = NULL; 36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ui_task_runner_->PostTask( 37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FROM_HERE, 38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(&ScreenObserverDelegate::RemoveObserverOnUIThread, this)); 39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private: 42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) friend class base::RefCountedThreadSafe<ScreenObserverDelegate>; 43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual ~ScreenObserverDelegate() { 45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(!capture_device_); 46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual void OnDisplayAdded(const gfx::Display& /*new_display*/) OVERRIDE {} 49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual void OnDisplayRemoved(const gfx::Display& /*old_display*/) OVERRIDE {} 50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual void OnDisplayMetricsChanged(const gfx::Display& display, 51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32_t metrics) OVERRIDE { 5246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK(ui_task_runner_->BelongsToCurrentThread()); 53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!(metrics & DISPLAY_METRIC_ROTATION)) 54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SendDisplayRotation(display); 56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void AddObserverOnUIThread() { 59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(ui_task_runner_->BelongsToCurrentThread()); 60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) gfx::Screen* screen = 61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_ALTERNATE); 62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (screen) { 63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) screen->AddObserver(this); 64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SendDisplayRotation(screen->GetPrimaryDisplay()); 65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void RemoveObserverOnUIThread() { 69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(ui_task_runner_->BelongsToCurrentThread()); 70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) gfx::Screen* screen = 71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_ALTERNATE); 72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (screen) 73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) screen->RemoveObserver(this); 74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 7646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Post the screen rotation change from the UI thread to capture thread 77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void SendDisplayRotation(const gfx::Display& display) { 7846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK(ui_task_runner_->BelongsToCurrentThread()); 79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) capture_task_runner_->PostTask( 80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FROM_HERE, 81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(&ScreenObserverDelegate::SendDisplayRotationOnCaptureThread, 82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this, display)); 83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void SendDisplayRotationOnCaptureThread(const gfx::Display& display) { 86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(capture_task_runner_->BelongsToCurrentThread()); 8746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (capture_device_) 8846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) capture_device_->SetDisplayRotation(display); 89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) VideoCaptureDeviceChromeOS* capture_device_; 92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; 93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner_; 94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DISALLOW_IMPLICIT_CONSTRUCTORS(ScreenObserverDelegate); 95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)VideoCaptureDeviceChromeOS::VideoCaptureDeviceChromeOS( 99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, 100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const Name& device_name) 101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) : VideoCaptureDeviceLinux(device_name), 102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) screen_observer_delegate_(new ScreenObserverDelegate(this, 103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ui_task_runner)) { 104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)VideoCaptureDeviceChromeOS::~VideoCaptureDeviceChromeOS() { 107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) screen_observer_delegate_->RemoveObserver(); 108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void VideoCaptureDeviceChromeOS::SetDisplayRotation( 111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const gfx::Display& display) { 112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (display.IsInternal()) 113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SetRotation(display.rotation() * 90); 114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} // namespace media 117