Fri, 16 Jan 2015 18:13:44 +0100
Integrate suggestion from review to improve consistency with existing code.
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 FAKE_MEDIA_STREAM_H_
6 #define FAKE_MEDIA_STREAM_H_
8 #include <set>
10 #include "nsNetCID.h"
11 #include "nsITimer.h"
12 #include "nsComponentManagerUtils.h"
13 #include "nsIComponentManager.h"
14 #include "nsIComponentRegistrar.h"
16 // #includes from MediaStream.h
17 #include "mozilla/Mutex.h"
18 #include "AudioSegment.h"
19 #include "MediaSegment.h"
20 #include "StreamBuffer.h"
21 #include "nsTArray.h"
22 #include "nsIRunnable.h"
23 #include "nsISupportsImpl.h"
24 #include "nsIDOMMediaStream.h"
26 class nsIDOMWindow;
28 namespace mozilla {
29 class MediaStreamGraph;
30 class MediaSegment;
31 };
33 class Fake_SourceMediaStream;
35 static const int64_t USECS_PER_S = 1000000;
37 class Fake_MediaStreamListener
38 {
39 public:
40 virtual ~Fake_MediaStreamListener() {}
42 virtual void NotifyQueuedTrackChanges(mozilla::MediaStreamGraph* aGraph, mozilla::TrackID aID,
43 mozilla::TrackRate aTrackRate,
44 mozilla::TrackTicks aTrackOffset,
45 uint32_t aTrackEvents,
46 const mozilla::MediaSegment& aQueuedMedia) = 0;
47 virtual void NotifyPull(mozilla::MediaStreamGraph* aGraph, mozilla::StreamTime aDesiredTime) = 0;
49 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Fake_MediaStreamListener)
50 };
52 class Fake_MediaStreamDirectListener : public Fake_MediaStreamListener
53 {
54 public:
55 virtual ~Fake_MediaStreamDirectListener() {}
57 virtual void NotifyRealtimeData(mozilla::MediaStreamGraph* graph, mozilla::TrackID tid,
58 mozilla::TrackRate rate,
59 mozilla::TrackTicks offset,
60 uint32_t events,
61 const mozilla::MediaSegment& media) = 0;
62 };
64 // Note: only one listener supported
65 class Fake_MediaStream {
66 public:
67 Fake_MediaStream () : mListeners(), mMutex("Fake MediaStream") {}
68 virtual ~Fake_MediaStream() { Stop(); }
70 void AddListener(Fake_MediaStreamListener *aListener) {
71 mozilla::MutexAutoLock lock(mMutex);
72 mListeners.insert(aListener);
73 }
75 void RemoveListener(Fake_MediaStreamListener *aListener) {
76 mozilla::MutexAutoLock lock(mMutex);
77 mListeners.erase(aListener);
78 }
80 virtual Fake_SourceMediaStream *AsSourceStream() { return nullptr; }
82 virtual nsresult Start() { return NS_OK; }
83 virtual nsresult Stop() { return NS_OK; }
84 virtual void StopStream() {}
86 virtual void Periodic() {}
88 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Fake_MediaStream);
90 protected:
91 std::set<Fake_MediaStreamListener *> mListeners;
92 mozilla::Mutex mMutex; // Lock to prevent the listener list from being modified while
93 // executing Periodic().
94 };
96 class Fake_MediaPeriodic : public nsITimerCallback {
97 public:
98 Fake_MediaPeriodic(Fake_MediaStream *aStream) : mStream(aStream),
99 mCount(0) {}
100 virtual ~Fake_MediaPeriodic() {}
101 void Detach() {
102 mStream = nullptr;
103 }
105 int GetTimesCalled() { return mCount; }
107 NS_DECL_THREADSAFE_ISUPPORTS
108 NS_DECL_NSITIMERCALLBACK
110 protected:
111 Fake_MediaStream *mStream;
112 int mCount;
113 };
116 class Fake_SourceMediaStream : public Fake_MediaStream {
117 public:
118 Fake_SourceMediaStream() : mSegmentsAdded(0),
119 mDesiredTime(0),
120 mPullEnabled(false),
121 mStop(false),
122 mPeriodic(new Fake_MediaPeriodic(this)) {}
124 void AddTrack(mozilla::TrackID aID, mozilla::TrackRate aRate, mozilla::TrackTicks aStart,
125 mozilla::MediaSegment* aSegment) {}
126 void EndTrack(mozilla::TrackID aID) {}
128 bool AppendToTrack(mozilla::TrackID aID, mozilla::MediaSegment* aSegment,
129 mozilla::MediaSegment *aRawSegment) {
130 return AppendToTrack(aID, aSegment);
131 }
133 bool AppendToTrack(mozilla::TrackID aID, mozilla::MediaSegment* aSegment) {
134 bool nonZeroSample = false;
135 MOZ_ASSERT(aSegment);
136 if(aSegment->GetType() == mozilla::MediaSegment::AUDIO) {
137 //On audio segment append, we verify for validity
138 //of the audio samples.
139 mozilla::AudioSegment* audio =
140 static_cast<mozilla::AudioSegment*>(aSegment);
141 mozilla::AudioSegment::ChunkIterator iter(*audio);
142 while(!iter.IsEnded()) {
143 mozilla::AudioChunk& chunk = *(iter);
144 MOZ_ASSERT(chunk.mBuffer);
145 const int16_t* buf =
146 static_cast<const int16_t*>(chunk.mChannelData[0]);
147 for(int i=0; i<chunk.mDuration; i++) {
148 if(buf[i]) {
149 //atleast one non-zero sample found.
150 nonZeroSample = true;
151 break;
152 }
153 }
154 //process next chunk
155 iter.Next();
156 }
157 if(nonZeroSample) {
158 //we increment segments count if
159 //atleast one non-zero samples was found.
160 ++mSegmentsAdded;
161 }
162 } else {
163 //in the case of video segment appended, we just increase the
164 //segment count.
165 ++mSegmentsAdded;
166 }
167 return true;
168 }
170 void AdvanceKnownTracksTime(mozilla::StreamTime aKnownTime) {}
172 void SetPullEnabled(bool aEnabled) {
173 mPullEnabled = aEnabled;
174 }
175 void AddDirectListener(Fake_MediaStreamListener* aListener) {}
176 void RemoveDirectListener(Fake_MediaStreamListener* aListener) {}
178 //Don't pull anymore data,if mStop is true.
179 virtual void StopStream() {
180 mStop = true;
181 }
183 virtual Fake_SourceMediaStream *AsSourceStream() { return this; }
185 virtual nsresult Start();
186 virtual nsresult Stop();
188 virtual void Periodic();
190 virtual int GetSegmentsAdded() {
191 return mSegmentsAdded;
192 }
194 protected:
195 int mSegmentsAdded;
196 uint64_t mDesiredTime;
197 bool mPullEnabled;
198 bool mStop;
199 nsRefPtr<Fake_MediaPeriodic> mPeriodic;
200 nsCOMPtr<nsITimer> mTimer;
201 };
204 class Fake_DOMMediaStream : public nsIDOMMediaStream
205 {
206 public:
207 Fake_DOMMediaStream() : mMediaStream(new Fake_MediaStream()) {}
208 Fake_DOMMediaStream(Fake_MediaStream *stream) :
209 mMediaStream(stream) {}
211 virtual ~Fake_DOMMediaStream() {
212 // Note: memory leak
213 mMediaStream->Stop();
214 }
216 NS_DECL_THREADSAFE_ISUPPORTS
218 static already_AddRefed<Fake_DOMMediaStream>
219 CreateSourceStream(nsIDOMWindow* aWindow, uint32_t aHintContents) {
220 Fake_SourceMediaStream *source = new Fake_SourceMediaStream();
222 nsRefPtr<Fake_DOMMediaStream> ds = new Fake_DOMMediaStream(source);
223 ds->SetHintContents(aHintContents);
225 return ds.forget();
226 }
228 virtual void Stop() {} // Really DOMLocalMediaStream
230 virtual bool AddDirectListener(Fake_MediaStreamListener *aListener) { return false; }
231 virtual void RemoveDirectListener(Fake_MediaStreamListener *aListener) {}
233 Fake_MediaStream *GetStream() { return mMediaStream; }
235 // Hints to tell the SDP generator about whether this
236 // MediaStream probably has audio and/or video
237 typedef uint8_t TrackTypeHints;
238 enum {
239 HINT_CONTENTS_AUDIO = 0x01,
240 HINT_CONTENTS_VIDEO = 0x02
241 };
242 uint32_t GetHintContents() const { return mHintContents; }
243 void SetHintContents(uint32_t aHintContents) { mHintContents = aHintContents; }
245 private:
246 nsRefPtr<Fake_MediaStream> mMediaStream;
248 // tells the SDP generator about whether this
249 // MediaStream probably has audio and/or video
250 uint32_t mHintContents;
251 };
253 class Fake_MediaStreamGraph
254 {
255 public:
256 virtual ~Fake_MediaStreamGraph() {}
257 };
261 class Fake_MediaStreamBase : public Fake_MediaStream {
262 public:
263 Fake_MediaStreamBase() : mPeriodic(new Fake_MediaPeriodic(this)) {}
265 virtual nsresult Start();
266 virtual nsresult Stop();
268 virtual int GetSegmentsAdded() {
269 return mPeriodic->GetTimesCalled();
270 }
272 private:
273 nsCOMPtr<nsITimer> mTimer;
274 nsRefPtr<Fake_MediaPeriodic> mPeriodic;
275 };
278 class Fake_AudioStreamSource : public Fake_MediaStreamBase {
279 public:
280 Fake_AudioStreamSource() : Fake_MediaStreamBase(),
281 mCount(0),
282 mStop(false) {}
283 //Signaling Agent indicates us to stop generating
284 //further audio.
285 void StopStream() {
286 mStop = true;
287 }
288 virtual void Periodic();
289 int mCount;
290 bool mStop;
291 };
293 class Fake_VideoStreamSource : public Fake_MediaStreamBase {
294 public:
295 Fake_VideoStreamSource() : Fake_MediaStreamBase() {}
296 };
299 namespace mozilla {
300 typedef Fake_MediaStream MediaStream;
301 typedef Fake_SourceMediaStream SourceMediaStream;
302 typedef Fake_MediaStreamListener MediaStreamListener;
303 typedef Fake_MediaStreamDirectListener MediaStreamDirectListener;
304 typedef Fake_DOMMediaStream DOMMediaStream;
305 typedef Fake_DOMMediaStream DOMLocalMediaStream;
306 }
308 #endif