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

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 comments Created 3 years, 7 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 "media/capture/video/chromeos/camera_device_delegate.h"
8 #include "media/capture/video/chromeos/camera_hal_delegate.h"
9 #include "ui/display/display.h"
10 #include "ui/display/display_observer.h"
11 #include "ui/display/screen.h"
12
13 namespace media {
14
15 namespace {
16
17 const base::TimeDelta kEventWaitTimeoutMs =
18 base::TimeDelta::FromMilliseconds(3000);
19
20 } // namespace
21
22 // This is a delegate class used to transfer Display change events from the UI
23 // thread to the media thread.
24 class VideoCaptureDeviceArcChromeOS::ScreenObserverDelegate
25 : public display::DisplayObserver,
26 public base::RefCountedThreadSafe<ScreenObserverDelegate> {
27 public:
28 // It is safe to use the raw pointer |capture_device| as
29 // VideoCaptureDeviceArcChromeOS owns the ScreenObserverDelegate instance and
30 // we make sure the VideoCaptureDeviceArcChromeOS instance outlives the
31 // ScreenObserverDelegate instance.
32 ScreenObserverDelegate(
33 VideoCaptureDeviceArcChromeOS* capture_device,
34 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
35 : capture_device_(capture_device),
36 ui_task_runner_(ui_task_runner),
37 capture_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
38 ui_task_runner_->PostTask(
39 FROM_HERE,
40 base::Bind(&ScreenObserverDelegate::AddObserverOnUIThread, this));
41 }
42
43 void RemoveObserver() {
44 DCHECK(capture_task_runner_->BelongsToCurrentThread());
45 capture_device_ = nullptr;
46 ui_task_runner_->PostTask(
47 FROM_HERE,
48 base::Bind(&ScreenObserverDelegate::RemoveObserverOnUIThread, this));
49 }
50
51 private:
52 friend class base::RefCountedThreadSafe<ScreenObserverDelegate>;
53
54 ~ScreenObserverDelegate() override { DCHECK(!capture_device_); }
55
56 void OnDisplayAdded(const display::Display& /*new_display*/) override {}
57 void OnDisplayRemoved(const display::Display& /*old_display*/) override {}
58 void OnDisplayMetricsChanged(const display::Display& display,
59 uint32_t metrics) override {
60 DCHECK(ui_task_runner_->BelongsToCurrentThread());
61 if (!(metrics & DISPLAY_METRIC_ROTATION))
62 return;
63 SendDisplayRotation(display);
64 }
65
66 void AddObserverOnUIThread() {
67 DCHECK(ui_task_runner_->BelongsToCurrentThread());
68 display::Screen* screen = display::Screen::GetScreen();
69 if (screen) {
70 screen->AddObserver(this);
71 SendDisplayRotation(screen->GetPrimaryDisplay());
72 }
73 }
74
75 void RemoveObserverOnUIThread() {
76 DCHECK(ui_task_runner_->BelongsToCurrentThread());
77 display::Screen* screen = display::Screen::GetScreen();
78 if (screen)
79 screen->RemoveObserver(this);
80 }
81
82 // Post the screen rotation change from the UI thread to capture thread
83 void SendDisplayRotation(const display::Display& display) {
84 DCHECK(ui_task_runner_->BelongsToCurrentThread());
85 capture_task_runner_->PostTask(
86 FROM_HERE,
87 base::Bind(&ScreenObserverDelegate::SendDisplayRotationOnCaptureThread,
88 this, display));
89 }
90
91 void SendDisplayRotationOnCaptureThread(const display::Display& display) {
92 DCHECK(capture_task_runner_->BelongsToCurrentThread());
93 if (capture_device_)
94 capture_device_->SetDisplayRotation(display);
95 }
96
97 VideoCaptureDeviceArcChromeOS* capture_device_;
98 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
99 scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner_;
100 DISALLOW_IMPLICIT_CONSTRUCTORS(ScreenObserverDelegate);
101 };
102
103 VideoCaptureDeviceArcChromeOS::VideoCaptureDeviceArcChromeOS(
104 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
105 const VideoCaptureDeviceDescriptor& device_descriptor,
106 scoped_refptr<CameraHalDelegate> camera_hal_delegate)
107 : device_descriptor_(device_descriptor),
108 camera_hal_delegate_(camera_hal_delegate),
109 capture_task_runner_(base::ThreadTaskRunnerHandle::Get()),
110 device_thread_("CameraDeviceThread"),
111 screen_observer_delegate_(
112 new ScreenObserverDelegate(this, std::move(ui_task_runner))),
113 lens_facing_(device_descriptor.facing),
114 camera_orientation_(0),
115 // External cameras have lens_facing as MEDIA_VIDEO_FACING_NONE.
116 // We don't want to rotate the frame even if the device rotates.
117 rotates_with_device_(lens_facing_ !=
118 VideoFacingMode::MEDIA_VIDEO_FACING_NONE) {}
119
120 VideoCaptureDeviceArcChromeOS::~VideoCaptureDeviceArcChromeOS() {
121 DCHECK(capture_task_runner_->BelongsToCurrentThread());
122 DCHECK(!device_thread_.IsRunning());
123 screen_observer_delegate_->RemoveObserver();
124 }
125
126 // static
127 VideoPixelFormat VideoCaptureDeviceArcChromeOS::PixFormatHalToChromium(
128 arc::mojom::HalPixelFormat from) {
129 return CameraDeviceDelegate::PixFormatHalToChromium(from);
130 }
131
132 // static
133 uint32_t VideoCaptureDeviceArcChromeOS::PixFormatChromiumToDrm(
134 VideoPixelFormat from) {
135 return CameraDeviceDelegate::PixFormatChromiumToDrm(from);
136 }
137
138 // VideoCaptureDevice implementation.
139 void VideoCaptureDeviceArcChromeOS::AllocateAndStart(
140 const VideoCaptureParams& params,
141 std::unique_ptr<Client> client) {
142 DCHECK(capture_task_runner_->BelongsToCurrentThread());
143 DCHECK(!camera_device_delegate_);
144 base::WaitableEvent started(base::WaitableEvent::ResetPolicy::MANUAL,
145 base::WaitableEvent::InitialState::NOT_SIGNALED);
146 int32_t camera_id = std::stoi(device_descriptor_.device_id);
147 device_thread_.Start();
148 // We need to get the static camera metadata of the camera deivce first.
149 camera_hal_delegate_->GetCameraInfo(
150 camera_id, base::Bind(&VideoCaptureDeviceArcChromeOS::OnGotCameraInfo,
151 base::Unretained(this), params,
152 base::Passed(&client), base::Unretained(&started)));
153 started.TimedWait(kEventWaitTimeoutMs);
154 }
155
156 void VideoCaptureDeviceArcChromeOS::StopAndDeAllocate() {
157 DCHECK(capture_task_runner_->BelongsToCurrentThread());
158 if (camera_device_delegate_) {
159 base::WaitableEvent closed(base::WaitableEvent::ResetPolicy::MANUAL,
160 base::WaitableEvent::InitialState::NOT_SIGNALED);
161 device_thread_.task_runner()->PostTask(
162 FROM_HERE,
163 base::Bind(&CameraDeviceDelegate::StopAndDeAllocate,
164 camera_device_delegate_, base::Unretained(&closed)));
165 closed.TimedWait(kEventWaitTimeoutMs);
166 camera_device_delegate_ = nullptr;
167 }
168 device_thread_.Stop();
169 }
170
171 void VideoCaptureDeviceArcChromeOS::TakePhoto(TakePhotoCallback callback) {
172 DCHECK(capture_task_runner_->BelongsToCurrentThread());
173 DCHECK(camera_device_delegate_);
174 device_thread_.task_runner()->PostTask(
175 FROM_HERE, base::Bind(&CameraDeviceDelegate::TakePhoto,
176 camera_device_delegate_, base::Passed(&callback)));
177 }
178
179 void VideoCaptureDeviceArcChromeOS::GetPhotoCapabilities(
180 GetPhotoCapabilitiesCallback callback) {
181 DCHECK(capture_task_runner_->BelongsToCurrentThread());
182 device_thread_.task_runner()->PostTask(
183 FROM_HERE, base::Bind(&CameraDeviceDelegate::GetPhotoCapabilities,
184 camera_device_delegate_, base::Passed(&callback)));
185 }
186
187 void VideoCaptureDeviceArcChromeOS::SetPhotoOptions(
188 mojom::PhotoSettingsPtr settings,
189 SetPhotoOptionsCallback callback) {
190 DCHECK(capture_task_runner_->BelongsToCurrentThread());
191 device_thread_.task_runner()->PostTask(
192 FROM_HERE, base::Bind(&CameraDeviceDelegate::SetPhotoOptions,
193 camera_device_delegate_, base::Passed(&settings),
194 base::Passed(&callback)));
195 }
196
197 void VideoCaptureDeviceArcChromeOS::OnGotCameraInfo(
198 const VideoCaptureParams& params,
199 std::unique_ptr<Client> client,
200 base::WaitableEvent* started,
201 int32_t result,
202 arc::mojom::CameraInfoPtr camera_info) {
203 // This method runs on |module_task_runner_| of |camera_hal_delegate_|.
204 if (result) {
205 client->OnError(FROM_HERE, "Failed to get camera info");
206 return;
207 }
208 int32_t camera_id = std::stoi(device_descriptor_.device_id);
209 camera_hal_delegate_->OpenDevice(
210 camera_id,
211 base::Bind(&VideoCaptureDeviceArcChromeOS::OnOpenedDevice,
212 base::Unretained(this), params, base::Passed(&client),
213 base::Unretained(started),
214 base::Passed(&camera_info->static_camera_characteristics)));
215 }
216
217 void VideoCaptureDeviceArcChromeOS::OnOpenedDevice(
218 const VideoCaptureParams& params,
219 std::unique_ptr<Client> client,
220 base::WaitableEvent* started,
221 arc::mojom::CameraMetadataPtr static_metadata,
222 int32_t result,
223 arc::mojom::Camera3DeviceOpsPtr device_ops) {
224 // This method runs on |module_task_runner_| of |camera_hal_delegate_|.
225 if (result) {
226 client->OnError(FROM_HERE, "Failed to open camera device");
227 return;
228 }
229 mojo::InterfacePtrInfo<arc::mojom::Camera3DeviceOps> device_ops_info =
230 device_ops.PassInterface();
231 camera_device_delegate_ = new CameraDeviceDelegate(
232 device_descriptor_, std::move(static_metadata),
233 std::move(device_ops_info), device_thread_.task_runner());
234 device_thread_.task_runner()->PostTask(
235 FROM_HERE,
236 base::Bind(&CameraDeviceDelegate::AllocateAndStart,
237 camera_device_delegate_, params, base::Passed(&client)));
238 started->Signal();
239 }
240
241 void VideoCaptureDeviceArcChromeOS::SetRotation(int rotation) {
242 DCHECK(capture_task_runner_->BelongsToCurrentThread());
243 if (!rotates_with_device_) {
244 rotation = 0;
245 } else if (lens_facing_ == VideoFacingMode::MEDIA_VIDEO_FACING_ENVIRONMENT) {
246 // Original frame when |rotation| = 0
247 // -----------------------
248 // | * |
249 // | * * |
250 // | * * |
251 // | ******* |
252 // | * * |
253 // | * * |
254 // -----------------------
255 //
256 // |rotation| = 90, this is what back camera sees
257 // -----------------------
258 // | ******** |
259 // | * **** |
260 // | * *** |
261 // | * *** |
262 // | * **** |
263 // | ******** |
264 // -----------------------
265 //
266 // |rotation| = 90, this is what front camera sees
267 // -----------------------
268 // | ******** |
269 // | **** * |
270 // | *** * |
271 // | *** * |
272 // | **** * |
273 // | ******** |
274 // -----------------------
275 //
276 // Therefore, for back camera, we need to rotate (360 - |rotation|).
277 rotation = (360 - rotation) % 360;
278 }
279 // Take into account camera orientation w.r.t. the display. External cameras
280 // would have camera_orientation_ as 0.
281 rotation = (rotation + camera_orientation_) % 360;
282 if (device_thread_.IsRunning()) {
283 device_thread_.task_runner()->PostTask(
284 FROM_HERE, base::Bind(&CameraDeviceDelegate::SetRotation,
285 camera_device_delegate_, rotation));
286 }
287 }
288
289 void VideoCaptureDeviceArcChromeOS::SetDisplayRotation(
290 const display::Display& display) {
291 DCHECK(capture_task_runner_->BelongsToCurrentThread());
292 if (display.IsInternal())
293 SetRotation(display.rotation() * 90);
294 }
295
296 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698