|
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 #ifndef MEDIAENGINEWEBRTC_H_ |
|
6 #define MEDIAENGINEWEBRTC_H_ |
|
7 |
|
8 #include "prcvar.h" |
|
9 #include "prthread.h" |
|
10 #include "nsIThread.h" |
|
11 #include "nsIRunnable.h" |
|
12 |
|
13 #include "mozilla/Mutex.h" |
|
14 #include "mozilla/Monitor.h" |
|
15 #include "nsCOMPtr.h" |
|
16 #include "nsDOMFile.h" |
|
17 #include "nsThreadUtils.h" |
|
18 #include "DOMMediaStream.h" |
|
19 #include "nsDirectoryServiceDefs.h" |
|
20 #include "nsComponentManagerUtils.h" |
|
21 #include "nsRefPtrHashtable.h" |
|
22 |
|
23 #include "VideoUtils.h" |
|
24 #include "MediaEngine.h" |
|
25 #include "VideoSegment.h" |
|
26 #include "AudioSegment.h" |
|
27 #include "StreamBuffer.h" |
|
28 #include "MediaStreamGraph.h" |
|
29 |
|
30 #include "MediaEngineWrapper.h" |
|
31 |
|
32 // WebRTC library includes follow |
|
33 |
|
34 // Audio Engine |
|
35 #include "webrtc/voice_engine/include/voe_base.h" |
|
36 #include "webrtc/voice_engine/include/voe_codec.h" |
|
37 #include "webrtc/voice_engine/include/voe_hardware.h" |
|
38 #include "webrtc/voice_engine/include/voe_network.h" |
|
39 #include "webrtc/voice_engine/include/voe_audio_processing.h" |
|
40 #include "webrtc/voice_engine/include/voe_volume_control.h" |
|
41 #include "webrtc/voice_engine/include/voe_external_media.h" |
|
42 #include "webrtc/voice_engine/include/voe_audio_processing.h" |
|
43 #include "webrtc/voice_engine/include/voe_call_report.h" |
|
44 |
|
45 // Video Engine |
|
46 #include "webrtc/video_engine/include/vie_base.h" |
|
47 #include "webrtc/video_engine/include/vie_codec.h" |
|
48 #include "webrtc/video_engine/include/vie_render.h" |
|
49 #include "webrtc/video_engine/include/vie_capture.h" |
|
50 #ifdef MOZ_B2G_CAMERA |
|
51 #include "CameraControlListener.h" |
|
52 #include "ICameraControl.h" |
|
53 #include "ImageContainer.h" |
|
54 #include "nsGlobalWindow.h" |
|
55 #include "prprf.h" |
|
56 #include "mozilla/Hal.h" |
|
57 #endif |
|
58 |
|
59 #include "NullTransport.h" |
|
60 #include "AudioOutputObserver.h" |
|
61 |
|
62 namespace mozilla { |
|
63 |
|
64 #ifdef MOZ_B2G_CAMERA |
|
65 class CameraAllocateRunnable; |
|
66 class GetCameraNameRunnable; |
|
67 #endif |
|
68 |
|
69 /** |
|
70 * The WebRTC implementation of the MediaEngine interface. |
|
71 * |
|
72 * On B2G platform, member data may accessed from different thread after construction: |
|
73 * |
|
74 * MediaThread: |
|
75 * mState, mImage, mWidth, mHeight, mCapability, mPrefs, mDeviceName, mUniqueId, mInitDone, |
|
76 * mImageContainer, mSources, mState, mImage |
|
77 * |
|
78 * MainThread: |
|
79 * mCaptureIndex, mLastCapture, mState, mWidth, mHeight, |
|
80 * |
|
81 * Where mWidth, mHeight, mImage are protected by mMonitor |
|
82 * mState is protected by mCallbackMonitor |
|
83 * Other variable is accessed only from single thread |
|
84 */ |
|
85 class MediaEngineWebRTCVideoSource : public MediaEngineVideoSource |
|
86 , public nsRunnable |
|
87 #ifdef MOZ_B2G_CAMERA |
|
88 , public CameraControlListener |
|
89 , public mozilla::hal::ScreenConfigurationObserver |
|
90 #else |
|
91 , public webrtc::ExternalRenderer |
|
92 #endif |
|
93 { |
|
94 public: |
|
95 #ifdef MOZ_B2G_CAMERA |
|
96 MediaEngineWebRTCVideoSource(int aIndex) |
|
97 : mCameraControl(nullptr) |
|
98 , mCallbackMonitor("WebRTCCamera.CallbackMonitor") |
|
99 , mRotation(0) |
|
100 , mBackCamera(false) |
|
101 , mCaptureIndex(aIndex) |
|
102 , mMonitor("WebRTCCamera.Monitor") |
|
103 , mWidth(0) |
|
104 , mHeight(0) |
|
105 , mInitDone(false) |
|
106 , mInSnapshotMode(false) |
|
107 , mSnapshotPath(nullptr) |
|
108 { |
|
109 mState = kReleased; |
|
110 Init(); |
|
111 } |
|
112 #else |
|
113 // ViEExternalRenderer. |
|
114 virtual int FrameSizeChange(unsigned int, unsigned int, unsigned int); |
|
115 virtual int DeliverFrame(unsigned char*,int, uint32_t , int64_t, |
|
116 void *handle); |
|
117 /** |
|
118 * Does DeliverFrame() support a null buffer and non-null handle |
|
119 * (video texture)? |
|
120 * XXX Investigate! Especially for Android/B2G |
|
121 */ |
|
122 virtual bool IsTextureSupported() { return false; } |
|
123 |
|
124 MediaEngineWebRTCVideoSource(webrtc::VideoEngine* aVideoEnginePtr, int aIndex) |
|
125 : mVideoEngine(aVideoEnginePtr) |
|
126 , mCaptureIndex(aIndex) |
|
127 , mFps(-1) |
|
128 , mMinFps(-1) |
|
129 , mMonitor("WebRTCCamera.Monitor") |
|
130 , mWidth(0) |
|
131 , mHeight(0) |
|
132 , mInitDone(false) |
|
133 , mInSnapshotMode(false) |
|
134 , mSnapshotPath(nullptr) { |
|
135 MOZ_ASSERT(aVideoEnginePtr); |
|
136 mState = kReleased; |
|
137 Init(); |
|
138 } |
|
139 #endif |
|
140 |
|
141 ~MediaEngineWebRTCVideoSource() { Shutdown(); } |
|
142 |
|
143 virtual void GetName(nsAString&); |
|
144 virtual void GetUUID(nsAString&); |
|
145 virtual nsresult Allocate(const VideoTrackConstraintsN &aConstraints, |
|
146 const MediaEnginePrefs &aPrefs); |
|
147 virtual nsresult Deallocate(); |
|
148 virtual nsresult Start(SourceMediaStream*, TrackID); |
|
149 virtual nsresult Stop(SourceMediaStream*, TrackID); |
|
150 virtual nsresult Snapshot(uint32_t aDuration, nsIDOMFile** aFile); |
|
151 virtual nsresult Config(bool aEchoOn, uint32_t aEcho, |
|
152 bool aAgcOn, uint32_t aAGC, |
|
153 bool aNoiseOn, uint32_t aNoise, |
|
154 int32_t aPlayoutDelay) { return NS_OK; }; |
|
155 virtual void NotifyPull(MediaStreamGraph* aGraph, |
|
156 SourceMediaStream *aSource, |
|
157 TrackID aId, |
|
158 StreamTime aDesiredTime, |
|
159 TrackTicks &aLastEndTime); |
|
160 |
|
161 virtual bool IsFake() { |
|
162 return false; |
|
163 } |
|
164 |
|
165 #ifndef MOZ_B2G_CAMERA |
|
166 NS_DECL_THREADSAFE_ISUPPORTS |
|
167 #else |
|
168 // We are subclassed from CameraControlListener, which implements a |
|
169 // threadsafe reference-count for us. |
|
170 NS_DECL_ISUPPORTS_INHERITED |
|
171 |
|
172 void OnHardwareStateChange(HardwareState aState); |
|
173 bool OnNewPreviewFrame(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight); |
|
174 void OnError(CameraErrorContext aContext, CameraError aError); |
|
175 void OnTakePictureComplete(uint8_t* aData, uint32_t aLength, const nsAString& aMimeType); |
|
176 |
|
177 void AllocImpl(); |
|
178 void DeallocImpl(); |
|
179 void StartImpl(webrtc::CaptureCapability aCapability); |
|
180 void StopImpl(); |
|
181 void SnapshotImpl(); |
|
182 void RotateImage(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight); |
|
183 void Notify(const mozilla::hal::ScreenConfiguration& aConfiguration); |
|
184 #endif |
|
185 |
|
186 // This runnable is for creating a temporary file on the main thread. |
|
187 NS_IMETHODIMP |
|
188 Run() |
|
189 { |
|
190 nsCOMPtr<nsIFile> tmp; |
|
191 nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(tmp)); |
|
192 NS_ENSURE_SUCCESS(rv, rv); |
|
193 |
|
194 tmp->Append(NS_LITERAL_STRING("webrtc_snapshot.jpeg")); |
|
195 rv = tmp->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600); |
|
196 NS_ENSURE_SUCCESS(rv, rv); |
|
197 |
|
198 mSnapshotPath = new nsString(); |
|
199 rv = tmp->GetPath(*mSnapshotPath); |
|
200 NS_ENSURE_SUCCESS(rv, rv); |
|
201 |
|
202 return NS_OK; |
|
203 } |
|
204 |
|
205 private: |
|
206 static const unsigned int KMaxDeviceNameLength = 128; |
|
207 static const unsigned int KMaxUniqueIdLength = 256; |
|
208 |
|
209 // Initialize the needed Video engine interfaces. |
|
210 void Init(); |
|
211 void Shutdown(); |
|
212 |
|
213 // Engine variables. |
|
214 #ifdef MOZ_B2G_CAMERA |
|
215 nsRefPtr<ICameraControl> mCameraControl; |
|
216 mozilla::ReentrantMonitor mCallbackMonitor; // Monitor for camera callback handling |
|
217 nsRefPtr<nsIDOMFile> mLastCapture; |
|
218 int mRotation; |
|
219 int mCameraAngle; // See dom/base/ScreenOrientation.h |
|
220 bool mBackCamera; |
|
221 #else |
|
222 webrtc::VideoEngine* mVideoEngine; // Weak reference, don't free. |
|
223 webrtc::ViEBase* mViEBase; |
|
224 webrtc::ViECapture* mViECapture; |
|
225 webrtc::ViERender* mViERender; |
|
226 #endif |
|
227 webrtc::CaptureCapability mCapability; // Doesn't work on OS X. |
|
228 |
|
229 int mCaptureIndex; |
|
230 int mFps; // Track rate (30 fps by default) |
|
231 int mMinFps; // Min rate we want to accept |
|
232 |
|
233 // mMonitor protects mImage access/changes, and transitions of mState |
|
234 // from kStarted to kStopped (which are combined with EndTrack() and |
|
235 // image changes). Note that mSources is not accessed from other threads |
|
236 // for video and is not protected. |
|
237 Monitor mMonitor; // Monitor for processing WebRTC frames. |
|
238 int mWidth, mHeight; |
|
239 nsRefPtr<layers::Image> mImage; |
|
240 nsRefPtr<layers::ImageContainer> mImageContainer; |
|
241 |
|
242 nsTArray<SourceMediaStream *> mSources; // When this goes empty, we shut down HW |
|
243 |
|
244 bool mInitDone; |
|
245 bool mInSnapshotMode; |
|
246 nsString* mSnapshotPath; |
|
247 |
|
248 nsString mDeviceName; |
|
249 nsString mUniqueId; |
|
250 |
|
251 void ChooseCapability(const VideoTrackConstraintsN &aConstraints, |
|
252 const MediaEnginePrefs &aPrefs); |
|
253 |
|
254 void GuessCapability(const VideoTrackConstraintsN &aConstraints, |
|
255 const MediaEnginePrefs &aPrefs); |
|
256 }; |
|
257 |
|
258 class MediaEngineWebRTCAudioSource : public MediaEngineAudioSource, |
|
259 public webrtc::VoEMediaProcess |
|
260 { |
|
261 public: |
|
262 MediaEngineWebRTCAudioSource(webrtc::VoiceEngine* aVoiceEnginePtr, int aIndex, |
|
263 const char* name, const char* uuid) |
|
264 : mVoiceEngine(aVoiceEnginePtr) |
|
265 , mMonitor("WebRTCMic.Monitor") |
|
266 , mCapIndex(aIndex) |
|
267 , mChannel(-1) |
|
268 , mInitDone(false) |
|
269 , mStarted(false) |
|
270 , mSamples(0) |
|
271 , mEchoOn(false), mAgcOn(false), mNoiseOn(false) |
|
272 , mEchoCancel(webrtc::kEcDefault) |
|
273 , mAGC(webrtc::kAgcDefault) |
|
274 , mNoiseSuppress(webrtc::kNsDefault) |
|
275 , mPlayoutDelay(0) |
|
276 , mNullTransport(nullptr) { |
|
277 MOZ_ASSERT(aVoiceEnginePtr); |
|
278 mState = kReleased; |
|
279 mDeviceName.Assign(NS_ConvertUTF8toUTF16(name)); |
|
280 mDeviceUUID.Assign(NS_ConvertUTF8toUTF16(uuid)); |
|
281 Init(); |
|
282 } |
|
283 ~MediaEngineWebRTCAudioSource() { Shutdown(); } |
|
284 |
|
285 virtual void GetName(nsAString&); |
|
286 virtual void GetUUID(nsAString&); |
|
287 |
|
288 virtual nsresult Allocate(const AudioTrackConstraintsN &aConstraints, |
|
289 const MediaEnginePrefs &aPrefs); |
|
290 virtual nsresult Deallocate(); |
|
291 virtual nsresult Start(SourceMediaStream*, TrackID); |
|
292 virtual nsresult Stop(SourceMediaStream*, TrackID); |
|
293 virtual nsresult Snapshot(uint32_t aDuration, nsIDOMFile** aFile); |
|
294 virtual nsresult Config(bool aEchoOn, uint32_t aEcho, |
|
295 bool aAgcOn, uint32_t aAGC, |
|
296 bool aNoiseOn, uint32_t aNoise, |
|
297 int32_t aPlayoutDelay); |
|
298 |
|
299 virtual void NotifyPull(MediaStreamGraph* aGraph, |
|
300 SourceMediaStream *aSource, |
|
301 TrackID aId, |
|
302 StreamTime aDesiredTime, |
|
303 TrackTicks &aLastEndTime); |
|
304 |
|
305 virtual bool IsFake() { |
|
306 return false; |
|
307 } |
|
308 |
|
309 // VoEMediaProcess. |
|
310 void Process(int channel, webrtc::ProcessingTypes type, |
|
311 int16_t audio10ms[], int length, |
|
312 int samplingFreq, bool isStereo); |
|
313 |
|
314 NS_DECL_THREADSAFE_ISUPPORTS |
|
315 |
|
316 private: |
|
317 static const unsigned int KMaxDeviceNameLength = 128; |
|
318 static const unsigned int KMaxUniqueIdLength = 256; |
|
319 |
|
320 void Init(); |
|
321 void Shutdown(); |
|
322 |
|
323 webrtc::VoiceEngine* mVoiceEngine; |
|
324 ScopedCustomReleasePtr<webrtc::VoEBase> mVoEBase; |
|
325 ScopedCustomReleasePtr<webrtc::VoEExternalMedia> mVoERender; |
|
326 ScopedCustomReleasePtr<webrtc::VoENetwork> mVoENetwork; |
|
327 ScopedCustomReleasePtr<webrtc::VoEAudioProcessing> mVoEProcessing; |
|
328 ScopedCustomReleasePtr<webrtc::VoECallReport> mVoECallReport; |
|
329 |
|
330 // mMonitor protects mSources[] access/changes, and transitions of mState |
|
331 // from kStarted to kStopped (which are combined with EndTrack()). |
|
332 // mSources[] is accessed from webrtc threads. |
|
333 Monitor mMonitor; |
|
334 nsTArray<SourceMediaStream *> mSources; // When this goes empty, we shut down HW |
|
335 |
|
336 int mCapIndex; |
|
337 int mChannel; |
|
338 TrackID mTrackID; |
|
339 bool mInitDone; |
|
340 bool mStarted; |
|
341 int mSamples; // int to avoid conversions when comparing/etc to samplingFreq & length |
|
342 |
|
343 nsString mDeviceName; |
|
344 nsString mDeviceUUID; |
|
345 |
|
346 bool mEchoOn, mAgcOn, mNoiseOn; |
|
347 webrtc::EcModes mEchoCancel; |
|
348 webrtc::AgcModes mAGC; |
|
349 webrtc::NsModes mNoiseSuppress; |
|
350 int32_t mPlayoutDelay; |
|
351 |
|
352 NullTransport *mNullTransport; |
|
353 }; |
|
354 |
|
355 class MediaEngineWebRTC : public MediaEngine |
|
356 { |
|
357 public: |
|
358 MediaEngineWebRTC(MediaEnginePrefs &aPrefs); |
|
359 |
|
360 // Clients should ensure to clean-up sources video/audio sources |
|
361 // before invoking Shutdown on this class. |
|
362 void Shutdown(); |
|
363 |
|
364 virtual void EnumerateVideoDevices(nsTArray<nsRefPtr<MediaEngineVideoSource> >*); |
|
365 virtual void EnumerateAudioDevices(nsTArray<nsRefPtr<MediaEngineAudioSource> >*); |
|
366 |
|
367 private: |
|
368 ~MediaEngineWebRTC() { |
|
369 Shutdown(); |
|
370 #ifdef MOZ_B2G_CAMERA |
|
371 AsyncLatencyLogger::Get()->Release(); |
|
372 #endif |
|
373 // XXX |
|
374 gFarendObserver = nullptr; |
|
375 } |
|
376 |
|
377 Mutex mMutex; |
|
378 // protected with mMutex: |
|
379 |
|
380 webrtc::VideoEngine* mVideoEngine; |
|
381 webrtc::VoiceEngine* mVoiceEngine; |
|
382 |
|
383 // Need this to avoid unneccesary WebRTC calls while enumerating. |
|
384 bool mVideoEngineInit; |
|
385 bool mAudioEngineInit; |
|
386 bool mHasTabVideoSource; |
|
387 |
|
388 // Store devices we've already seen in a hashtable for quick return. |
|
389 // Maps UUID to MediaEngineSource (one set for audio, one for video). |
|
390 nsRefPtrHashtable<nsStringHashKey, MediaEngineWebRTCVideoSource > mVideoSources; |
|
391 nsRefPtrHashtable<nsStringHashKey, MediaEngineWebRTCAudioSource > mAudioSources; |
|
392 }; |
|
393 |
|
394 } |
|
395 |
|
396 #endif /* NSMEDIAENGINEWEBRTC_H_ */ |