dom/camera/DOMCameraControlListener.cpp

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:29e79965cf41
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 #include "DOMCameraControlListener.h"
6 #include "nsThreadUtils.h"
7 #include "nsDOMFile.h"
8 #include "CameraCommon.h"
9 #include "DOMCameraControl.h"
10 #include "CameraPreviewMediaStream.h"
11 #include "mozilla/dom/CameraManagerBinding.h"
12
13 using namespace mozilla;
14 using namespace mozilla::dom;
15
16 DOMCameraControlListener::DOMCameraControlListener(nsDOMCameraControl* aDOMCameraControl,
17 CameraPreviewMediaStream* aStream)
18 : mDOMCameraControl(new nsMainThreadPtrHolder<nsDOMCameraControl>(aDOMCameraControl))
19 , mStream(aStream)
20 {
21 DOM_CAMERA_LOGT("%s:%d : this=%p, camera=%p, stream=%p\n",
22 __func__, __LINE__, this, aDOMCameraControl, aStream);
23 }
24
25 DOMCameraControlListener::~DOMCameraControlListener()
26 {
27 DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
28 }
29
30 // Boilerplate callback runnable
31 class DOMCameraControlListener::DOMCallback : public nsRunnable
32 {
33 public:
34 DOMCallback(nsMainThreadPtrHandle<nsDOMCameraControl> aDOMCameraControl)
35 : mDOMCameraControl(aDOMCameraControl)
36 {
37 MOZ_COUNT_CTOR(DOMCameraControlListener::DOMCallback);
38 }
39 virtual ~DOMCallback()
40 {
41 MOZ_COUNT_DTOR(DOMCameraControlListener::DOMCallback);
42 }
43
44 virtual void RunCallback(nsDOMCameraControl* aDOMCameraControl) = 0;
45
46 NS_IMETHOD
47 Run() MOZ_OVERRIDE
48 {
49 MOZ_ASSERT(NS_IsMainThread());
50
51 nsRefPtr<nsDOMCameraControl> camera = mDOMCameraControl.get();
52 if (camera) {
53 RunCallback(camera);
54 }
55 return NS_OK;
56 }
57
58 protected:
59 nsMainThreadPtrHandle<nsDOMCameraControl> mDOMCameraControl;
60 };
61
62 // Specific callback handlers
63 void
64 DOMCameraControlListener::OnHardwareStateChange(HardwareState aState)
65 {
66 class Callback : public DOMCallback
67 {
68 public:
69 Callback(nsMainThreadPtrHandle<nsDOMCameraControl> aDOMCameraControl,
70 HardwareState aState)
71 : DOMCallback(aDOMCameraControl)
72 , mState(aState)
73 { }
74
75 void
76 RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE
77 {
78 aDOMCameraControl->OnHardwareStateChange(mState);
79 }
80
81 protected:
82 HardwareState mState;
83 };
84
85 NS_DispatchToMainThread(new Callback(mDOMCameraControl, aState));
86 }
87
88 void
89 DOMCameraControlListener::OnPreviewStateChange(PreviewState aState)
90 {
91 class Callback : public DOMCallback
92 {
93 public:
94 Callback(nsMainThreadPtrHandle<nsDOMCameraControl> aDOMCameraControl,
95 PreviewState aState)
96 : DOMCallback(aDOMCameraControl)
97 , mState(aState)
98 { }
99
100 void
101 RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE
102 {
103 aDOMCameraControl->OnPreviewStateChange(mState);
104 }
105
106 protected:
107 PreviewState mState;
108 };
109
110 switch (aState) {
111 case kPreviewStopped:
112 // Clear the current frame right away, without dispatching a
113 // runnable. This is an ugly coupling between the camera's
114 // SurfaceTextureClient and the MediaStream/ImageContainer,
115 // but without it, the preview can fail to start.
116 DOM_CAMERA_LOGI("Preview stopped, clearing current frame\n");
117 mStream->ClearCurrentFrame();
118 break;
119
120 case kPreviewPaused:
121 // In the paused state, we still want to reflect the change
122 // in preview state, but we don't want to clear the current
123 // frame as above, since doing so seems to cause genlock
124 // problems when we restart the preview. See bug 957749.
125 DOM_CAMERA_LOGI("Preview paused\n");
126 break;
127
128 case kPreviewStarted:
129 DOM_CAMERA_LOGI("Preview started\n");
130 break;
131
132 default:
133 DOM_CAMERA_LOGE("Unknown preview state %d\n", aState);
134 MOZ_ASSUME_UNREACHABLE("Invalid preview state");
135 return;
136 }
137 NS_DispatchToMainThread(new Callback(mDOMCameraControl, aState));
138 }
139
140 void
141 DOMCameraControlListener::OnRecorderStateChange(RecorderState aState,
142 int32_t aStatus, int32_t aTrackNum)
143 {
144 class Callback : public DOMCallback
145 {
146 public:
147 Callback(nsMainThreadPtrHandle<nsDOMCameraControl> aDOMCameraControl,
148 RecorderState aState,
149 int32_t aStatus,
150 int32_t aTrackNum)
151 : DOMCallback(aDOMCameraControl)
152 , mState(aState)
153 , mStatus(aStatus)
154 , mTrackNum(aTrackNum)
155 { }
156
157 void
158 RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE
159 {
160 aDOMCameraControl->OnRecorderStateChange(mState, mStatus, mTrackNum);
161 }
162
163 protected:
164 RecorderState mState;
165 int32_t mStatus;
166 int32_t mTrackNum;
167 };
168
169 NS_DispatchToMainThread(new Callback(mDOMCameraControl, aState, aStatus, aTrackNum));
170 }
171
172 void
173 DOMCameraControlListener::OnConfigurationChange(const CameraListenerConfiguration& aConfiguration)
174 {
175 class Callback : public DOMCallback
176 {
177 public:
178 Callback(nsMainThreadPtrHandle<nsDOMCameraControl> aDOMCameraControl,
179 const CameraListenerConfiguration& aConfiguration)
180 : DOMCallback(aDOMCameraControl)
181 , mConfiguration(aConfiguration)
182 { }
183
184 void
185 RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE
186 {
187 nsRefPtr<nsDOMCameraControl::DOMCameraConfiguration> config =
188 new nsDOMCameraControl::DOMCameraConfiguration();
189
190 switch (mConfiguration.mMode) {
191 case ICameraControl::kVideoMode:
192 config->mMode = CameraMode::Video;
193 break;
194
195 case ICameraControl::kPictureMode:
196 config->mMode = CameraMode::Picture;
197 break;
198
199 default:
200 DOM_CAMERA_LOGI("Camera mode still unspecified, nothing to do\n");
201 return;
202 }
203
204 // Map CameraControl parameters to their DOM-facing equivalents
205 config->mRecorderProfile = mConfiguration.mRecorderProfile;
206 config->mPreviewSize.mWidth = mConfiguration.mPreviewSize.width;
207 config->mPreviewSize.mHeight = mConfiguration.mPreviewSize.height;
208 config->mMaxMeteringAreas = mConfiguration.mMaxMeteringAreas;
209 config->mMaxFocusAreas = mConfiguration.mMaxFocusAreas;
210
211 aDOMCameraControl->OnConfigurationChange(config);
212 }
213
214 protected:
215 const CameraListenerConfiguration mConfiguration;
216 };
217
218 NS_DispatchToMainThread(new Callback(mDOMCameraControl, aConfiguration));
219 }
220
221 void
222 DOMCameraControlListener::OnAutoFocusMoving(bool aIsMoving)
223 {
224 class Callback : public DOMCallback
225 {
226 public:
227 Callback(nsMainThreadPtrHandle<nsDOMCameraControl> aDOMCameraControl, bool aIsMoving)
228 : DOMCallback(aDOMCameraControl)
229 , mIsMoving(aIsMoving)
230 { }
231
232 void
233 RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE
234 {
235 aDOMCameraControl->OnAutoFocusMoving(mIsMoving);
236 }
237
238 protected:
239 bool mIsMoving;
240 };
241
242 NS_DispatchToMainThread(new Callback(mDOMCameraControl, aIsMoving));
243 }
244
245 void
246 DOMCameraControlListener::OnFacesDetected(const nsTArray<ICameraControl::Face>& aFaces)
247 {
248 class Callback : public DOMCallback
249 {
250 public:
251 Callback(nsMainThreadPtrHandle<nsDOMCameraControl> aDOMCameraControl,
252 const nsTArray<ICameraControl::Face>& aFaces)
253 : DOMCallback(aDOMCameraControl)
254 , mFaces(aFaces)
255 { }
256
257 void
258 RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE
259 {
260 aDOMCameraControl->OnFacesDetected(mFaces);
261 }
262
263 protected:
264 const nsTArray<ICameraControl::Face> mFaces;
265 };
266
267 NS_DispatchToMainThread(new Callback(mDOMCameraControl, aFaces));
268 }
269
270 void
271 DOMCameraControlListener::OnShutter()
272 {
273 class Callback : public DOMCallback
274 {
275 public:
276 Callback(nsMainThreadPtrHandle<nsDOMCameraControl> aDOMCameraControl)
277 : DOMCallback(aDOMCameraControl)
278 { }
279
280 void
281 RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE
282 {
283 aDOMCameraControl->OnShutter();
284 }
285 };
286
287 NS_DispatchToMainThread(new Callback(mDOMCameraControl));
288 }
289
290 bool
291 DOMCameraControlListener::OnNewPreviewFrame(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight)
292 {
293 DOM_CAMERA_LOGI("OnNewPreviewFrame: got %d x %d frame\n", aWidth, aHeight);
294
295 mStream->SetCurrentFrame(gfxIntSize(aWidth, aHeight), aImage);
296 return true;
297 }
298
299 void
300 DOMCameraControlListener::OnAutoFocusComplete(bool aAutoFocusSucceeded)
301 {
302 class Callback : public DOMCallback
303 {
304 public:
305 Callback(nsMainThreadPtrHandle<nsDOMCameraControl> aDOMCameraControl,
306 bool aAutoFocusSucceeded)
307 : DOMCallback(aDOMCameraControl)
308 , mAutoFocusSucceeded(aAutoFocusSucceeded)
309 { }
310
311 void
312 RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE
313 {
314 aDOMCameraControl->OnAutoFocusComplete(mAutoFocusSucceeded);
315 }
316
317 protected:
318 bool mAutoFocusSucceeded;
319 };
320
321 NS_DispatchToMainThread(new Callback(mDOMCameraControl, aAutoFocusSucceeded));
322 }
323
324 void
325 DOMCameraControlListener::OnTakePictureComplete(uint8_t* aData, uint32_t aLength, const nsAString& aMimeType)
326 {
327 class Callback : public DOMCallback
328 {
329 public:
330 Callback(nsMainThreadPtrHandle<nsDOMCameraControl> aDOMCameraControl,
331 uint8_t* aData, uint32_t aLength, const nsAString& aMimeType)
332 : DOMCallback(aDOMCameraControl)
333 , mData(aData)
334 , mLength(aLength)
335 , mMimeType(aMimeType)
336 { }
337
338 void
339 RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE
340 {
341 nsCOMPtr<nsIDOMBlob> picture = new nsDOMMemoryFile(static_cast<void*>(mData),
342 static_cast<uint64_t>(mLength),
343 mMimeType);
344 aDOMCameraControl->OnTakePictureComplete(picture);
345 }
346
347 protected:
348 uint8_t* mData;
349 uint32_t mLength;
350 nsString mMimeType;
351 };
352
353 NS_DispatchToMainThread(new Callback(mDOMCameraControl, aData, aLength, aMimeType));
354 }
355
356 void
357 DOMCameraControlListener::OnError(CameraErrorContext aContext, CameraError aError)
358 {
359 class Callback : public DOMCallback
360 {
361 public:
362 Callback(nsMainThreadPtrHandle<nsDOMCameraControl> aDOMCameraControl,
363 CameraErrorContext aContext,
364 CameraError aError)
365 : DOMCallback(aDOMCameraControl)
366 , mContext(aContext)
367 , mError(aError)
368 { }
369
370 virtual void
371 RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE
372 {
373 nsString error;
374
375 switch (mError) {
376 case kErrorServiceFailed:
377 error = NS_LITERAL_STRING("ErrorServiceFailed");
378 break;
379
380 case kErrorSetPictureSizeFailed:
381 error = NS_LITERAL_STRING("ErrorSetPictureSizeFailed");
382 break;
383
384 case kErrorSetThumbnailSizeFailed:
385 error = NS_LITERAL_STRING("ErrorSetThumbnailSizeFailed");
386 break;
387
388 case kErrorApiFailed:
389 // XXXmikeh legacy error placeholder
390 error = NS_LITERAL_STRING("FAILURE");
391 break;
392
393 default:
394 error = NS_LITERAL_STRING("ErrorUnknown");
395 break;
396 }
397 aDOMCameraControl->OnError(mContext, error);
398 }
399
400 protected:
401 CameraErrorContext mContext;
402 CameraError mError;
403 };
404
405 NS_DispatchToMainThread(new Callback(mDOMCameraControl, aContext, aError));
406 }

mercurial