Fri, 16 Jan 2015 04:50:19 +0100
Replace accessor implementation with direct member state manipulation, by
request https://trac.torproject.org/projects/tor/ticket/9701#comment:32
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 #ifndef MEDIAENGINEWEBRTC_H_
6 #define MEDIAENGINEWEBRTC_H_
8 #include "prcvar.h"
9 #include "prthread.h"
10 #include "nsIThread.h"
11 #include "nsIRunnable.h"
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"
23 #include "VideoUtils.h"
24 #include "MediaEngine.h"
25 #include "VideoSegment.h"
26 #include "AudioSegment.h"
27 #include "StreamBuffer.h"
28 #include "MediaStreamGraph.h"
30 #include "MediaEngineWrapper.h"
32 // WebRTC library includes follow
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"
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
59 #include "NullTransport.h"
60 #include "AudioOutputObserver.h"
62 namespace mozilla {
64 #ifdef MOZ_B2G_CAMERA
65 class CameraAllocateRunnable;
66 class GetCameraNameRunnable;
67 #endif
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; }
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
141 ~MediaEngineWebRTCVideoSource() { Shutdown(); }
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);
161 virtual bool IsFake() {
162 return false;
163 }
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
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);
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
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);
194 tmp->Append(NS_LITERAL_STRING("webrtc_snapshot.jpeg"));
195 rv = tmp->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600);
196 NS_ENSURE_SUCCESS(rv, rv);
198 mSnapshotPath = new nsString();
199 rv = tmp->GetPath(*mSnapshotPath);
200 NS_ENSURE_SUCCESS(rv, rv);
202 return NS_OK;
203 }
205 private:
206 static const unsigned int KMaxDeviceNameLength = 128;
207 static const unsigned int KMaxUniqueIdLength = 256;
209 // Initialize the needed Video engine interfaces.
210 void Init();
211 void Shutdown();
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.
229 int mCaptureIndex;
230 int mFps; // Track rate (30 fps by default)
231 int mMinFps; // Min rate we want to accept
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;
242 nsTArray<SourceMediaStream *> mSources; // When this goes empty, we shut down HW
244 bool mInitDone;
245 bool mInSnapshotMode;
246 nsString* mSnapshotPath;
248 nsString mDeviceName;
249 nsString mUniqueId;
251 void ChooseCapability(const VideoTrackConstraintsN &aConstraints,
252 const MediaEnginePrefs &aPrefs);
254 void GuessCapability(const VideoTrackConstraintsN &aConstraints,
255 const MediaEnginePrefs &aPrefs);
256 };
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(); }
285 virtual void GetName(nsAString&);
286 virtual void GetUUID(nsAString&);
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);
299 virtual void NotifyPull(MediaStreamGraph* aGraph,
300 SourceMediaStream *aSource,
301 TrackID aId,
302 StreamTime aDesiredTime,
303 TrackTicks &aLastEndTime);
305 virtual bool IsFake() {
306 return false;
307 }
309 // VoEMediaProcess.
310 void Process(int channel, webrtc::ProcessingTypes type,
311 int16_t audio10ms[], int length,
312 int samplingFreq, bool isStereo);
314 NS_DECL_THREADSAFE_ISUPPORTS
316 private:
317 static const unsigned int KMaxDeviceNameLength = 128;
318 static const unsigned int KMaxUniqueIdLength = 256;
320 void Init();
321 void Shutdown();
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;
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
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
343 nsString mDeviceName;
344 nsString mDeviceUUID;
346 bool mEchoOn, mAgcOn, mNoiseOn;
347 webrtc::EcModes mEchoCancel;
348 webrtc::AgcModes mAGC;
349 webrtc::NsModes mNoiseSuppress;
350 int32_t mPlayoutDelay;
352 NullTransport *mNullTransport;
353 };
355 class MediaEngineWebRTC : public MediaEngine
356 {
357 public:
358 MediaEngineWebRTC(MediaEnginePrefs &aPrefs);
360 // Clients should ensure to clean-up sources video/audio sources
361 // before invoking Shutdown on this class.
362 void Shutdown();
364 virtual void EnumerateVideoDevices(nsTArray<nsRefPtr<MediaEngineVideoSource> >*);
365 virtual void EnumerateAudioDevices(nsTArray<nsRefPtr<MediaEngineAudioSource> >*);
367 private:
368 ~MediaEngineWebRTC() {
369 Shutdown();
370 #ifdef MOZ_B2G_CAMERA
371 AsyncLatencyLogger::Get()->Release();
372 #endif
373 // XXX
374 gFarendObserver = nullptr;
375 }
377 Mutex mMutex;
378 // protected with mMutex:
380 webrtc::VideoEngine* mVideoEngine;
381 webrtc::VoiceEngine* mVoiceEngine;
383 // Need this to avoid unneccesary WebRTC calls while enumerating.
384 bool mVideoEngineInit;
385 bool mAudioEngineInit;
386 bool mHasTabVideoSource;
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 };
394 }
396 #endif /* NSMEDIAENGINEWEBRTC_H_ */