Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(412)

Side by Side Diff: media/capture/video/chromeos/video_capture_device_arc_chromeos.cc

Issue 2837273004: media: add video capture device for ARC++ camera HAL v3 (Closed)
Patch Set: address wuchengli's and chfremer's comments Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 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/capture/video/chromeos/video_capture_device_arc_chromeos.h"
6
7 #include "base/threading/platform_thread.h"
8 #include "media/capture/video/chromeos/camera_device_delegate.h"
9 #include "media/capture/video/chromeos/camera_hal_delegate.h"
10 #include "ui/display/display.h"
11 #include "ui/display/display_observer.h"
12 #include "ui/display/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 capture thread.
18 class VideoCaptureDeviceArcChromeOS::ScreenObserverDelegate
19 : public display::DisplayObserver,
20 public base::RefCountedThreadSafe<ScreenObserverDelegate> {
21 public:
22 // It is safe to use the raw pointer |capture_device| because
23 // ~VideoCaptureDeviceArcChromeOS() calls RemoveObserver() and sets
24 // |capture_device_| to nullptr.
25 ScreenObserverDelegate(VideoCaptureDeviceArcChromeOS* capture_device,
26 scoped_refptr<base::SingleThreadTaskRunner>
27 task_runner_for_screen_observer)
28 : capture_device_(capture_device),
29 task_runner_(task_runner_for_screen_observer),
30 capture_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
31 task_runner_->PostTask(
32 FROM_HERE,
33 base::Bind(&ScreenObserverDelegate::AddObserverOnUIThread, this));
34 }
35
36 void RemoveObserver() {
37 DCHECK(capture_task_runner_->BelongsToCurrentThread());
38 capture_device_ = nullptr;
39 task_runner_->PostTask(
40 FROM_HERE,
41 base::Bind(&ScreenObserverDelegate::RemoveObserverOnUIThread, this));
42 }
43
44 private:
45 friend class base::RefCountedThreadSafe<ScreenObserverDelegate>;
46
47 ~ScreenObserverDelegate() override { DCHECK(!capture_device_); }
48
49 void OnDisplayAdded(const display::Display& /*new_display*/) override {}
50 void OnDisplayRemoved(const display::Display& /*old_display*/) override {}
51 void OnDisplayMetricsChanged(const display::Display& display,
52 uint32_t metrics) override {
53 DCHECK(task_runner_->BelongsToCurrentThread());
54 if (!(metrics & DISPLAY_METRIC_ROTATION))
55 return;
56 SendDisplayRotation(display);
57 }
58
59 void AddObserverOnUIThread() {
60 DCHECK(task_runner_->BelongsToCurrentThread());
61 display::Screen* screen = display::Screen::GetScreen();
62 if (screen) {
63 screen->AddObserver(this);
64 SendDisplayRotation(screen->GetPrimaryDisplay());
65 }
66 }
67
68 void RemoveObserverOnUIThread() {
69 DCHECK(task_runner_->BelongsToCurrentThread());
70 display::Screen* screen = display::Screen::GetScreen();
71 if (screen)
72 screen->RemoveObserver(this);
73 }
74
75 // Post the screen rotation change from the UI thread to capture thread
76 void SendDisplayRotation(const display::Display& display) {
77 DCHECK(task_runner_->BelongsToCurrentThread());
78 capture_task_runner_->PostTask(
79 FROM_HERE,
80 base::Bind(&ScreenObserverDelegate::SendDisplayRotationOnCaptureThread,
81 this, display));
82 }
83
84 void SendDisplayRotationOnCaptureThread(const display::Display& display) {
85 DCHECK(capture_task_runner_->BelongsToCurrentThread());
86 if (capture_device_)
87 capture_device_->SetDisplayRotation(display);
88 }
89
90 VideoCaptureDeviceArcChromeOS* capture_device_;
91 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
92 scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner_;
93 DISALLOW_IMPLICIT_CONSTRUCTORS(ScreenObserverDelegate);
94 };
95
96 VideoCaptureDeviceArcChromeOS::VideoCaptureDeviceArcChromeOS(
97 scoped_refptr<base::SingleThreadTaskRunner> task_runner_for_screen_observer,
98 const VideoCaptureDeviceDescriptor& device_descriptor,
99 scoped_refptr<CameraHalDelegate> camera_hal_delegate)
100 : device_descriptor_(device_descriptor),
101 camera_hal_delegate_(camera_hal_delegate),
102 capture_task_runner_(base::ThreadTaskRunnerHandle::Get()),
103 device_thread_("CameraDeviceThread"),
104 screen_observer_delegate_(new ScreenObserverDelegate(
105 this,
106 std::move(task_runner_for_screen_observer))),
107 lens_facing_(device_descriptor.facing),
108 camera_orientation_(0),
109 // External cameras have lens_facing as MEDIA_VIDEO_FACING_NONE.
110 // We don't want to rotate the frame even if the device rotates.
111 rotates_with_device_(lens_facing_ !=
112 VideoFacingMode::MEDIA_VIDEO_FACING_NONE),
113 rotation_(0) {}
114
115 VideoCaptureDeviceArcChromeOS::~VideoCaptureDeviceArcChromeOS() {
116 DCHECK(capture_task_runner_->BelongsToCurrentThread());
117 DCHECK(!device_thread_.IsRunning());
118 screen_observer_delegate_->RemoveObserver();
119 }
120
121 // VideoCaptureDevice implementation.
122 void VideoCaptureDeviceArcChromeOS::AllocateAndStart(
123 const VideoCaptureParams& params,
124 std::unique_ptr<Client> client) {
125 DCHECK(capture_task_runner_->BelongsToCurrentThread());
126 DCHECK(!camera_device_delegate_);
127
128 if (!device_thread_.Start()) {
129 std::string error_msg = "Failed to start device thread";
130 LOG(ERROR) << error_msg;
131 client->OnError(FROM_HERE, error_msg);
132 return;
133 }
134 camera_device_delegate_ = new CameraDeviceDelegate(
135 device_descriptor_, camera_hal_delegate_, device_thread_.task_runner());
136 device_thread_.task_runner()->PostTask(
137 FROM_HERE,
138 base::Bind(&CameraDeviceDelegate::AllocateAndStart,
139 camera_device_delegate_, params, base::Passed(&client)));
140 device_thread_.task_runner()->PostTask(
141 FROM_HERE, base::Bind(&CameraDeviceDelegate::SetRotation,
142 camera_device_delegate_, rotation_));
143 }
144
145 void VideoCaptureDeviceArcChromeOS::StopAndDeAllocate() {
146 DCHECK(capture_task_runner_->BelongsToCurrentThread());
147
148 if (!camera_device_delegate_) {
149 return;
150 }
151 device_thread_.task_runner()->PostTask(
152 FROM_HERE, base::Bind(&CameraDeviceDelegate::StopAndDeAllocate,
153 camera_device_delegate_));
154 // Wait until all other references to |camera_device_delegate_| are dropped to
155 // make sure all the IPC calls are done.
156 base::TimeTicks wait_until =
157 base::TimeTicks() + base::TimeDelta::FromSeconds(3);
158 while (!camera_device_delegate_->HasOneRef()) {
159 if (base::TimeTicks() >= wait_until) {
160 LOG(ERROR) << "Timed out waiting capture device to stop";
161 break;
162 }
163 base::PlatformThread::YieldCurrentThread();
164 }
165 device_thread_.Stop();
166 camera_device_delegate_ = nullptr;
167 }
168
169 void VideoCaptureDeviceArcChromeOS::TakePhoto(TakePhotoCallback callback) {
170 DCHECK(capture_task_runner_->BelongsToCurrentThread());
171 DCHECK(camera_device_delegate_);
172 device_thread_.task_runner()->PostTask(
173 FROM_HERE, base::Bind(&CameraDeviceDelegate::TakePhoto,
174 camera_device_delegate_, base::Passed(&callback)));
175 }
176
177 void VideoCaptureDeviceArcChromeOS::GetPhotoCapabilities(
178 GetPhotoCapabilitiesCallback callback) {
179 DCHECK(capture_task_runner_->BelongsToCurrentThread());
180 device_thread_.task_runner()->PostTask(
181 FROM_HERE, base::Bind(&CameraDeviceDelegate::GetPhotoCapabilities,
182 camera_device_delegate_, base::Passed(&callback)));
183 }
184
185 void VideoCaptureDeviceArcChromeOS::SetPhotoOptions(
186 mojom::PhotoSettingsPtr settings,
187 SetPhotoOptionsCallback callback) {
188 DCHECK(capture_task_runner_->BelongsToCurrentThread());
189 device_thread_.task_runner()->PostTask(
190 FROM_HERE, base::Bind(&CameraDeviceDelegate::SetPhotoOptions,
191 camera_device_delegate_, base::Passed(&settings),
192 base::Passed(&callback)));
193 }
194
195 void VideoCaptureDeviceArcChromeOS::SetRotation(int rotation) {
196 DCHECK(capture_task_runner_->BelongsToCurrentThread());
197 if (!rotates_with_device_) {
198 rotation = 0;
199 } else if (lens_facing_ == VideoFacingMode::MEDIA_VIDEO_FACING_ENVIRONMENT) {
200 // Original frame when |rotation| = 0
201 // -----------------------
202 // | * |
203 // | * * |
204 // | * * |
205 // | ******* |
206 // | * * |
207 // | * * |
208 // -----------------------
209 //
210 // |rotation| = 90, this is what back camera sees
211 // -----------------------
212 // | ******** |
213 // | * **** |
214 // | * *** |
215 // | * *** |
216 // | * **** |
217 // | ******** |
218 // -----------------------
219 //
220 // |rotation| = 90, this is what front camera sees
221 // -----------------------
222 // | ******** |
223 // | **** * |
224 // | *** * |
225 // | *** * |
226 // | **** * |
227 // | ******** |
228 // -----------------------
229 //
230 // Therefore, for back camera, we need to rotate (360 - |rotation|).
231 rotation = (360 - rotation) % 360;
232 }
233 // Take into account camera orientation w.r.t. the display. External cameras
234 // would have camera_orientation_ as 0.
235 rotation_ = (rotation + camera_orientation_) % 360;
236 if (device_thread_.IsRunning()) {
237 device_thread_.task_runner()->PostTask(
238 FROM_HERE, base::Bind(&CameraDeviceDelegate::SetRotation,
239 camera_device_delegate_, rotation_));
240 }
241 }
242
243 void VideoCaptureDeviceArcChromeOS::SetDisplayRotation(
244 const display::Display& display) {
245 DCHECK(capture_task_runner_->BelongsToCurrentThread());
246 if (display.IsInternal())
247 SetRotation(display.rotation() * 90);
248 }
249
250 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698