Home | History | Annotate | Download | only in linux
      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