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