Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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/. */
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"
13 using namespace mozilla;
14 using namespace mozilla::dom;
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 }
25 DOMCameraControlListener::~DOMCameraControlListener()
26 {
27 DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
28 }
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 }
44 virtual void RunCallback(nsDOMCameraControl* aDOMCameraControl) = 0;
46 NS_IMETHOD
47 Run() MOZ_OVERRIDE
48 {
49 MOZ_ASSERT(NS_IsMainThread());
51 nsRefPtr<nsDOMCameraControl> camera = mDOMCameraControl.get();
52 if (camera) {
53 RunCallback(camera);
54 }
55 return NS_OK;
56 }
58 protected:
59 nsMainThreadPtrHandle<nsDOMCameraControl> mDOMCameraControl;
60 };
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 { }
75 void
76 RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE
77 {
78 aDOMCameraControl->OnHardwareStateChange(mState);
79 }
81 protected:
82 HardwareState mState;
83 };
85 NS_DispatchToMainThread(new Callback(mDOMCameraControl, aState));
86 }
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 { }
100 void
101 RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE
102 {
103 aDOMCameraControl->OnPreviewStateChange(mState);
104 }
106 protected:
107 PreviewState mState;
108 };
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;
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;
128 case kPreviewStarted:
129 DOM_CAMERA_LOGI("Preview started\n");
130 break;
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 }
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 { }
157 void
158 RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE
159 {
160 aDOMCameraControl->OnRecorderStateChange(mState, mStatus, mTrackNum);
161 }
163 protected:
164 RecorderState mState;
165 int32_t mStatus;
166 int32_t mTrackNum;
167 };
169 NS_DispatchToMainThread(new Callback(mDOMCameraControl, aState, aStatus, aTrackNum));
170 }
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 { }
184 void
185 RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE
186 {
187 nsRefPtr<nsDOMCameraControl::DOMCameraConfiguration> config =
188 new nsDOMCameraControl::DOMCameraConfiguration();
190 switch (mConfiguration.mMode) {
191 case ICameraControl::kVideoMode:
192 config->mMode = CameraMode::Video;
193 break;
195 case ICameraControl::kPictureMode:
196 config->mMode = CameraMode::Picture;
197 break;
199 default:
200 DOM_CAMERA_LOGI("Camera mode still unspecified, nothing to do\n");
201 return;
202 }
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;
211 aDOMCameraControl->OnConfigurationChange(config);
212 }
214 protected:
215 const CameraListenerConfiguration mConfiguration;
216 };
218 NS_DispatchToMainThread(new Callback(mDOMCameraControl, aConfiguration));
219 }
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 { }
232 void
233 RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE
234 {
235 aDOMCameraControl->OnAutoFocusMoving(mIsMoving);
236 }
238 protected:
239 bool mIsMoving;
240 };
242 NS_DispatchToMainThread(new Callback(mDOMCameraControl, aIsMoving));
243 }
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 { }
257 void
258 RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE
259 {
260 aDOMCameraControl->OnFacesDetected(mFaces);
261 }
263 protected:
264 const nsTArray<ICameraControl::Face> mFaces;
265 };
267 NS_DispatchToMainThread(new Callback(mDOMCameraControl, aFaces));
268 }
270 void
271 DOMCameraControlListener::OnShutter()
272 {
273 class Callback : public DOMCallback
274 {
275 public:
276 Callback(nsMainThreadPtrHandle<nsDOMCameraControl> aDOMCameraControl)
277 : DOMCallback(aDOMCameraControl)
278 { }
280 void
281 RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE
282 {
283 aDOMCameraControl->OnShutter();
284 }
285 };
287 NS_DispatchToMainThread(new Callback(mDOMCameraControl));
288 }
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);
295 mStream->SetCurrentFrame(gfxIntSize(aWidth, aHeight), aImage);
296 return true;
297 }
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 { }
311 void
312 RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE
313 {
314 aDOMCameraControl->OnAutoFocusComplete(mAutoFocusSucceeded);
315 }
317 protected:
318 bool mAutoFocusSucceeded;
319 };
321 NS_DispatchToMainThread(new Callback(mDOMCameraControl, aAutoFocusSucceeded));
322 }
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 { }
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 }
347 protected:
348 uint8_t* mData;
349 uint32_t mLength;
350 nsString mMimeType;
351 };
353 NS_DispatchToMainThread(new Callback(mDOMCameraControl, aData, aLength, aMimeType));
354 }
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 { }
370 virtual void
371 RunCallback(nsDOMCameraControl* aDOMCameraControl) MOZ_OVERRIDE
372 {
373 nsString error;
375 switch (mError) {
376 case kErrorServiceFailed:
377 error = NS_LITERAL_STRING("ErrorServiceFailed");
378 break;
380 case kErrorSetPictureSizeFailed:
381 error = NS_LITERAL_STRING("ErrorSetPictureSizeFailed");
382 break;
384 case kErrorSetThumbnailSizeFailed:
385 error = NS_LITERAL_STRING("ErrorSetThumbnailSizeFailed");
386 break;
388 case kErrorApiFailed:
389 // XXXmikeh legacy error placeholder
390 error = NS_LITERAL_STRING("FAILURE");
391 break;
393 default:
394 error = NS_LITERAL_STRING("ErrorUnknown");
395 break;
396 }
397 aDOMCameraControl->OnError(mContext, error);
398 }
400 protected:
401 CameraErrorContext mContext;
402 CameraError mError;
403 };
405 NS_DispatchToMainThread(new Callback(mDOMCameraControl, aContext, aError));
406 }