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

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: 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 using namespace arc::mojom;
16
17 // This is a delegate class used to transfer Display change events from the UI
18 // thread to the media thread.
19 class VideoCaptureDeviceArcChromeOS::ScreenObserverDelegate
chfremer 2017/04/26 21:13:05 Please add comment explaining why the raw pointer
jcliang 2017/04/27 07:07:56 Done.
20 : public display::DisplayObserver,
21 public base::RefCountedThreadSafe<ScreenObserverDelegate> {
22 public:
23 ScreenObserverDelegate(
24 VideoCaptureDeviceArcChromeOS* capture_device,
25 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
26 : capture_device_(capture_device),
27 ui_task_runner_(ui_task_runner),
28 capture_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
29 ui_task_runner_->PostTask(
30 FROM_HERE,
31 base::Bind(&ScreenObserverDelegate::AddObserverOnUIThread, this));
32 }
33
34 void RemoveObserver() {
35 DCHECK(capture_task_runner_->BelongsToCurrentThread());
36 capture_device_ = nullptr;
37 ui_task_runner_->PostTask(
38 FROM_HERE,
39 base::Bind(&ScreenObserverDelegate::RemoveObserverOnUIThread, this));
40 }
41
42 private:
43 friend class base::RefCountedThreadSafe<ScreenObserverDelegate>;
44
45 ~ScreenObserverDelegate() override { DCHECK(!capture_device_); }
46
47 void OnDisplayAdded(const display::Display& /*new_display*/) override {}
48 void OnDisplayRemoved(const display::Display& /*old_display*/) override {}
49 void OnDisplayMetricsChanged(const display::Display& display,
50 uint32_t metrics) override {
51 DCHECK(ui_task_runner_->BelongsToCurrentThread());
52 if (!(metrics & DISPLAY_METRIC_ROTATION))
53 return;
54 SendDisplayRotation(display);
55 }
56
57 void AddObserverOnUIThread() {
58 DCHECK(ui_task_runner_->BelongsToCurrentThread());
59 display::Screen* screen = display::Screen::GetScreen();
60 if (screen) {
61 screen->AddObserver(this);
62 SendDisplayRotation(screen->GetPrimaryDisplay());
63 }
64 }
65
66 void RemoveObserverOnUIThread() {
67 DCHECK(ui_task_runner_->BelongsToCurrentThread());
68 display::Screen* screen = display::Screen::GetScreen();
69 if (screen)
70 screen->RemoveObserver(this);
71 }
72
73 // Post the screen rotation change from the UI thread to capture thread
74 void SendDisplayRotation(const display::Display& display) {
75 DCHECK(ui_task_runner_->BelongsToCurrentThread());
76 capture_task_runner_->PostTask(
77 FROM_HERE,
78 base::Bind(&ScreenObserverDelegate::SendDisplayRotationOnCaptureThread,
79 this, display));
80 }
81
82 void SendDisplayRotationOnCaptureThread(const display::Display& display) {
83 DCHECK(capture_task_runner_->BelongsToCurrentThread());
84 if (capture_device_)
85 capture_device_->SetDisplayRotation(display);
86 }
87
88 VideoCaptureDeviceArcChromeOS* capture_device_;
89 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
90 scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner_;
91 DISALLOW_IMPLICIT_CONSTRUCTORS(ScreenObserverDelegate);
92 };
93
94 VideoCaptureDeviceArcChromeOS::VideoCaptureDeviceArcChromeOS(
95 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
96 const VideoCaptureDeviceDescriptor& device_descriptor,
97 scoped_refptr<CameraHalDelegate> camera_hal_delegate)
98 : device_descriptor_(device_descriptor),
99 camera_hal_delegate_(camera_hal_delegate),
100 capture_task_runner_(base::ThreadTaskRunnerHandle::Get()),
101 device_thread_("CameraDeviceThread"),
102 starting_(false),
103 stopping_(false),
104 // TODO(jcliang): Determine |lens_facing_| and |camera_orientation_| from
105 // static characteristics. We should probably defer the
106 // initialization of |screen_observer_delegate_| until
107 // after we get the static characteristics in
108 // OnGotCameraInfo.
109 screen_observer_delegate_(
110 new ScreenObserverDelegate(this, ui_task_runner)),
111 lens_facing_(VideoFacingMode::MEDIA_VIDEO_FACING_USER),
112 camera_orientation_(0),
113 // External cameras have lens_facing as MEDIA_VIDEO_FACING_NONE.
114 // We don't want to rotate the frame even if the device rotates.
115 rotates_with_device_(lens_facing_ !=
116 VideoFacingMode::MEDIA_VIDEO_FACING_NONE) {}
117
118 VideoCaptureDeviceArcChromeOS::~VideoCaptureDeviceArcChromeOS() {
119 DCHECK(capture_task_runner_->BelongsToCurrentThread());
120 DCHECK(!device_thread_.IsRunning());
121 screen_observer_delegate_->RemoveObserver();
122 }
123
124 // static
125 VideoPixelFormat VideoCaptureDeviceArcChromeOS::PixFormatHalToChromium(
126 HalPixelFormat from) {
127 return CameraDeviceDelegate::PixFormatHalToChromium(from);
128 }
129
130 // static
131 uint32_t VideoCaptureDeviceArcChromeOS::PixFormatChromiumToDrm(
132 VideoPixelFormat from) {
133 return CameraDeviceDelegate::PixFormatChromiumToDrm(from);
134 }
135
136 // VideoCaptureDevice implementation.
137 void VideoCaptureDeviceArcChromeOS::AllocateAndStart(
138 const VideoCaptureParams& params,
139 std::unique_ptr<Client> client) {
140 DCHECK(capture_task_runner_->BelongsToCurrentThread());
141 DCHECK(!camera_device_delegate_);
chfremer 2017/04/26 21:13:05 Would we be hitting this when a client calls Alloc
jcliang 2017/04/27 07:07:56 It wouldn't hit this DCHECK. I'll add some comment
142 starting_ = true;
143 int32_t camera_id = std::stoi(device_descriptor_.device_id);
144 camera_hal_delegate_->GetCameraInfo(
145 camera_id,
146 base::Bind(&VideoCaptureDeviceArcChromeOS::OnGotCameraInfo,
147 base::Unretained(this), params, base::Passed(&client)));
148 }
149
150 void VideoCaptureDeviceArcChromeOS::StopAndDeAllocate() {
151 DCHECK(capture_task_runner_->BelongsToCurrentThread());
152 stopping_ = true;
153 // StopAndDeAllocate is called only after AllocateAndStart. We have two cases
154 // here: |camera_device_delegate_| is either created, or being created. If
155 // |camera_device_delegate_| is already created then we simply close the
156 // camera device here; otherwise we defer to CreateDeviceOnCaptureThread to
157 // close the camera device right after camera HAL has opened the camera
158 // device.
159 if (camera_device_delegate_) {
160 base::WaitableEvent closed(base::WaitableEvent::ResetPolicy::MANUAL,
161 base::WaitableEvent::InitialState::NOT_SIGNALED);
162 device_thread_.task_runner()->PostTask(
163 FROM_HERE,
164 base::Bind(&CameraDeviceDelegate::StopAndDeAllocate,
165 camera_device_delegate_, base::Unretained(&closed)));
166 closed.Wait();
167 camera_device_delegate_ = nullptr;
168 device_thread_.Stop();
169 stopping_ = false;
170 }
171 }
172
173 void VideoCaptureDeviceArcChromeOS::TakePhoto(TakePhotoCallback callback) {
174 DCHECK(capture_task_runner_->BelongsToCurrentThread());
175 DCHECK(camera_device_delegate_);
176 device_thread_.task_runner()->PostTask(
177 FROM_HERE, base::Bind(&CameraDeviceDelegate::TakePhoto,
178 camera_device_delegate_, base::Passed(&callback)));
179 }
180
181 void VideoCaptureDeviceArcChromeOS::GetPhotoCapabilities(
182 GetPhotoCapabilitiesCallback callback) {
183 DCHECK(capture_task_runner_->BelongsToCurrentThread());
184 device_thread_.task_runner()->PostTask(
185 FROM_HERE, base::Bind(&CameraDeviceDelegate::GetPhotoCapabilities,
186 camera_device_delegate_, base::Passed(&callback)));
187 }
188
189 void VideoCaptureDeviceArcChromeOS::OnGotCameraInfo(
190 const VideoCaptureParams& params,
191 std::unique_ptr<Client> client,
192 int32_t result,
193 CameraInfoPtr camera_info) {
194 // This method runs on |module_task_runner_| of |camera_hal_delegate_|.
195 if (result) {
196 client->OnError(FROM_HERE, "Failed to get camera info");
197 return;
198 }
199 int32_t camera_id = std::stoi(device_descriptor_.device_id);
200 camera_hal_delegate_->OpenDevice(
201 camera_id,
202 base::Bind(&VideoCaptureDeviceArcChromeOS::OnOpenedDevice,
203 base::Unretained(this), params, base::Passed(&client),
204 base::Passed(&camera_info->static_camera_characteristics)));
205 }
206
207 void VideoCaptureDeviceArcChromeOS::OnOpenedDevice(
208 const VideoCaptureParams& params,
209 std::unique_ptr<Client> client,
210 CameraMetadataPtr static_metadata,
211 int32_t result,
212 Camera3DeviceOpsPtr device_ops) {
213 // This method runs on |module_task_runner_| of |camera_hal_delegate_|.
214 if (result) {
215 client->OnError(FROM_HERE, "Failed to open camera device");
216 return;
217 }
218 mojo::InterfacePtrInfo<Camera3DeviceOps> device_ops_info =
219 device_ops.PassInterface();
220 capture_task_runner_->PostTask(
221 FROM_HERE,
222 base::Bind(&VideoCaptureDeviceArcChromeOS::CreateDeviceOnCaptureThread,
223 base::Unretained(this), params, base::Passed(&client),
224 base::Passed(&static_metadata), result,
225 base::Passed(&device_ops_info)));
226 }
227
228 void VideoCaptureDeviceArcChromeOS::CreateDeviceOnCaptureThread(
229 const VideoCaptureParams& params,
230 std::unique_ptr<Client> client,
231 CameraMetadataPtr static_metadata,
232 int32_t result,
233 mojo::InterfacePtrInfo<Camera3DeviceOps> device_ops_info) {
234 DCHECK(capture_task_runner_->BelongsToCurrentThread());
235
236 starting_ = false;
237 if (stopping_) {
238 // A StopAndDeAllocate call was made.
239 Camera3DeviceOpsPtr device_ops;
240 device_ops.Bind(std::move(device_ops_info));
241 base::Callback<void(int32_t)> dont_care = base::Bind([](int32_t result) {});
242 // We don't need to worry about the return value of the Close mojo call here
243 // since the Camera3DeviceOps proxy will be terminated immediately. The next
244 // AllocateAndStart will create a new Camera3DeviceOps proxy.
245 device_ops->Close(dont_care);
246 stopping_ = false;
247 return;
248 }
249 device_thread_.Start();
250 camera_device_delegate_ = new CameraDeviceDelegate(
251 device_descriptor_, std::move(static_metadata),
252 std::move(device_ops_info), device_thread_.task_runner());
253 device_thread_.task_runner()->PostTask(
254 FROM_HERE,
255 base::Bind(&CameraDeviceDelegate::AllocateAndStart,
256 camera_device_delegate_, params, base::Passed(&client)));
257 }
258
259 void VideoCaptureDeviceArcChromeOS::SetPhotoOptions(
260 mojom::PhotoSettingsPtr settings,
261 SetPhotoOptionsCallback callback) {
262 DCHECK(capture_task_runner_->BelongsToCurrentThread());
263 device_thread_.task_runner()->PostTask(
264 FROM_HERE, base::Bind(&CameraDeviceDelegate::SetPhotoOptions,
265 camera_device_delegate_, base::Passed(&settings),
266 base::Passed(&callback)));
267 }
268
269 void VideoCaptureDeviceArcChromeOS::SetRotation(int rotation) {
270 DCHECK(capture_task_runner_->BelongsToCurrentThread());
271 if (!rotates_with_device_) {
272 rotation = 0;
273 } else if (lens_facing_ == VideoFacingMode::MEDIA_VIDEO_FACING_ENVIRONMENT) {
274 // Original frame when |rotation| = 0
275 // -----------------------
276 // | * |
277 // | * * |
278 // | * * |
279 // | ******* |
280 // | * * |
281 // | * * |
282 // -----------------------
283 //
284 // |rotation| = 90, this is what back camera sees
285 // -----------------------
286 // | ******** |
287 // | * **** |
288 // | * *** |
289 // | * *** |
290 // | * **** |
291 // | ******** |
292 // -----------------------
293 //
294 // |rotation| = 90, this is what front camera sees
295 // -----------------------
296 // | ******** |
297 // | **** * |
298 // | *** * |
299 // | *** * |
300 // | **** * |
301 // | ******** |
302 // -----------------------
303 //
304 // Therefore, for back camera, we need to rotate (360 - |rotation|).
305 rotation = (360 - rotation) % 360;
306 }
307 // Take into account camera orientation w.r.t. the display. External cameras
308 // would have camera_orientation_ as 0.
309 rotation = (rotation + camera_orientation_) % 360;
310 if (device_thread_.IsRunning()) {
311 device_thread_.task_runner()->PostTask(
312 FROM_HERE, base::Bind(&CameraDeviceDelegate::SetRotation,
313 camera_device_delegate_, rotation));
314 }
315 }
316
317 void VideoCaptureDeviceArcChromeOS::SetDisplayRotation(
318 const display::Display& display) {
319 DCHECK(capture_task_runner_->BelongsToCurrentThread());
320 if (display.IsInternal())
321 SetRotation(display.rotation() * 90);
322 }
323
324 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698