michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef FAKE_MEDIA_STREAM_H_ michael@0: #define FAKE_MEDIA_STREAM_H_ michael@0: michael@0: #include michael@0: michael@0: #include "nsNetCID.h" michael@0: #include "nsITimer.h" michael@0: #include "nsComponentManagerUtils.h" michael@0: #include "nsIComponentManager.h" michael@0: #include "nsIComponentRegistrar.h" michael@0: michael@0: // #includes from MediaStream.h michael@0: #include "mozilla/Mutex.h" michael@0: #include "AudioSegment.h" michael@0: #include "MediaSegment.h" michael@0: #include "StreamBuffer.h" michael@0: #include "nsTArray.h" michael@0: #include "nsIRunnable.h" michael@0: #include "nsISupportsImpl.h" michael@0: #include "nsIDOMMediaStream.h" michael@0: michael@0: class nsIDOMWindow; michael@0: michael@0: namespace mozilla { michael@0: class MediaStreamGraph; michael@0: class MediaSegment; michael@0: }; michael@0: michael@0: class Fake_SourceMediaStream; michael@0: michael@0: static const int64_t USECS_PER_S = 1000000; michael@0: michael@0: class Fake_MediaStreamListener michael@0: { michael@0: public: michael@0: virtual ~Fake_MediaStreamListener() {} michael@0: michael@0: virtual void NotifyQueuedTrackChanges(mozilla::MediaStreamGraph* aGraph, mozilla::TrackID aID, michael@0: mozilla::TrackRate aTrackRate, michael@0: mozilla::TrackTicks aTrackOffset, michael@0: uint32_t aTrackEvents, michael@0: const mozilla::MediaSegment& aQueuedMedia) = 0; michael@0: virtual void NotifyPull(mozilla::MediaStreamGraph* aGraph, mozilla::StreamTime aDesiredTime) = 0; michael@0: michael@0: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Fake_MediaStreamListener) michael@0: }; michael@0: michael@0: class Fake_MediaStreamDirectListener : public Fake_MediaStreamListener michael@0: { michael@0: public: michael@0: virtual ~Fake_MediaStreamDirectListener() {} michael@0: michael@0: virtual void NotifyRealtimeData(mozilla::MediaStreamGraph* graph, mozilla::TrackID tid, michael@0: mozilla::TrackRate rate, michael@0: mozilla::TrackTicks offset, michael@0: uint32_t events, michael@0: const mozilla::MediaSegment& media) = 0; michael@0: }; michael@0: michael@0: // Note: only one listener supported michael@0: class Fake_MediaStream { michael@0: public: michael@0: Fake_MediaStream () : mListeners(), mMutex("Fake MediaStream") {} michael@0: virtual ~Fake_MediaStream() { Stop(); } michael@0: michael@0: void AddListener(Fake_MediaStreamListener *aListener) { michael@0: mozilla::MutexAutoLock lock(mMutex); michael@0: mListeners.insert(aListener); michael@0: } michael@0: michael@0: void RemoveListener(Fake_MediaStreamListener *aListener) { michael@0: mozilla::MutexAutoLock lock(mMutex); michael@0: mListeners.erase(aListener); michael@0: } michael@0: michael@0: virtual Fake_SourceMediaStream *AsSourceStream() { return nullptr; } michael@0: michael@0: virtual nsresult Start() { return NS_OK; } michael@0: virtual nsresult Stop() { return NS_OK; } michael@0: virtual void StopStream() {} michael@0: michael@0: virtual void Periodic() {} michael@0: michael@0: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Fake_MediaStream); michael@0: michael@0: protected: michael@0: std::set mListeners; michael@0: mozilla::Mutex mMutex; // Lock to prevent the listener list from being modified while michael@0: // executing Periodic(). michael@0: }; michael@0: michael@0: class Fake_MediaPeriodic : public nsITimerCallback { michael@0: public: michael@0: Fake_MediaPeriodic(Fake_MediaStream *aStream) : mStream(aStream), michael@0: mCount(0) {} michael@0: virtual ~Fake_MediaPeriodic() {} michael@0: void Detach() { michael@0: mStream = nullptr; michael@0: } michael@0: michael@0: int GetTimesCalled() { return mCount; } michael@0: michael@0: NS_DECL_THREADSAFE_ISUPPORTS michael@0: NS_DECL_NSITIMERCALLBACK michael@0: michael@0: protected: michael@0: Fake_MediaStream *mStream; michael@0: int mCount; michael@0: }; michael@0: michael@0: michael@0: class Fake_SourceMediaStream : public Fake_MediaStream { michael@0: public: michael@0: Fake_SourceMediaStream() : mSegmentsAdded(0), michael@0: mDesiredTime(0), michael@0: mPullEnabled(false), michael@0: mStop(false), michael@0: mPeriodic(new Fake_MediaPeriodic(this)) {} michael@0: michael@0: void AddTrack(mozilla::TrackID aID, mozilla::TrackRate aRate, mozilla::TrackTicks aStart, michael@0: mozilla::MediaSegment* aSegment) {} michael@0: void EndTrack(mozilla::TrackID aID) {} michael@0: michael@0: bool AppendToTrack(mozilla::TrackID aID, mozilla::MediaSegment* aSegment, michael@0: mozilla::MediaSegment *aRawSegment) { michael@0: return AppendToTrack(aID, aSegment); michael@0: } michael@0: michael@0: bool AppendToTrack(mozilla::TrackID aID, mozilla::MediaSegment* aSegment) { michael@0: bool nonZeroSample = false; michael@0: MOZ_ASSERT(aSegment); michael@0: if(aSegment->GetType() == mozilla::MediaSegment::AUDIO) { michael@0: //On audio segment append, we verify for validity michael@0: //of the audio samples. michael@0: mozilla::AudioSegment* audio = michael@0: static_cast(aSegment); michael@0: mozilla::AudioSegment::ChunkIterator iter(*audio); michael@0: while(!iter.IsEnded()) { michael@0: mozilla::AudioChunk& chunk = *(iter); michael@0: MOZ_ASSERT(chunk.mBuffer); michael@0: const int16_t* buf = michael@0: static_cast(chunk.mChannelData[0]); michael@0: for(int i=0; i mPeriodic; michael@0: nsCOMPtr mTimer; michael@0: }; michael@0: michael@0: michael@0: class Fake_DOMMediaStream : public nsIDOMMediaStream michael@0: { michael@0: public: michael@0: Fake_DOMMediaStream() : mMediaStream(new Fake_MediaStream()) {} michael@0: Fake_DOMMediaStream(Fake_MediaStream *stream) : michael@0: mMediaStream(stream) {} michael@0: michael@0: virtual ~Fake_DOMMediaStream() { michael@0: // Note: memory leak michael@0: mMediaStream->Stop(); michael@0: } michael@0: michael@0: NS_DECL_THREADSAFE_ISUPPORTS michael@0: michael@0: static already_AddRefed michael@0: CreateSourceStream(nsIDOMWindow* aWindow, uint32_t aHintContents) { michael@0: Fake_SourceMediaStream *source = new Fake_SourceMediaStream(); michael@0: michael@0: nsRefPtr ds = new Fake_DOMMediaStream(source); michael@0: ds->SetHintContents(aHintContents); michael@0: michael@0: return ds.forget(); michael@0: } michael@0: michael@0: virtual void Stop() {} // Really DOMLocalMediaStream michael@0: michael@0: virtual bool AddDirectListener(Fake_MediaStreamListener *aListener) { return false; } michael@0: virtual void RemoveDirectListener(Fake_MediaStreamListener *aListener) {} michael@0: michael@0: Fake_MediaStream *GetStream() { return mMediaStream; } michael@0: michael@0: // Hints to tell the SDP generator about whether this michael@0: // MediaStream probably has audio and/or video michael@0: typedef uint8_t TrackTypeHints; michael@0: enum { michael@0: HINT_CONTENTS_AUDIO = 0x01, michael@0: HINT_CONTENTS_VIDEO = 0x02 michael@0: }; michael@0: uint32_t GetHintContents() const { return mHintContents; } michael@0: void SetHintContents(uint32_t aHintContents) { mHintContents = aHintContents; } michael@0: michael@0: private: michael@0: nsRefPtr mMediaStream; michael@0: michael@0: // tells the SDP generator about whether this michael@0: // MediaStream probably has audio and/or video michael@0: uint32_t mHintContents; michael@0: }; michael@0: michael@0: class Fake_MediaStreamGraph michael@0: { michael@0: public: michael@0: virtual ~Fake_MediaStreamGraph() {} michael@0: }; michael@0: michael@0: michael@0: michael@0: class Fake_MediaStreamBase : public Fake_MediaStream { michael@0: public: michael@0: Fake_MediaStreamBase() : mPeriodic(new Fake_MediaPeriodic(this)) {} michael@0: michael@0: virtual nsresult Start(); michael@0: virtual nsresult Stop(); michael@0: michael@0: virtual int GetSegmentsAdded() { michael@0: return mPeriodic->GetTimesCalled(); michael@0: } michael@0: michael@0: private: michael@0: nsCOMPtr mTimer; michael@0: nsRefPtr mPeriodic; michael@0: }; michael@0: michael@0: michael@0: class Fake_AudioStreamSource : public Fake_MediaStreamBase { michael@0: public: michael@0: Fake_AudioStreamSource() : Fake_MediaStreamBase(), michael@0: mCount(0), michael@0: mStop(false) {} michael@0: //Signaling Agent indicates us to stop generating michael@0: //further audio. michael@0: void StopStream() { michael@0: mStop = true; michael@0: } michael@0: virtual void Periodic(); michael@0: int mCount; michael@0: bool mStop; michael@0: }; michael@0: michael@0: class Fake_VideoStreamSource : public Fake_MediaStreamBase { michael@0: public: michael@0: Fake_VideoStreamSource() : Fake_MediaStreamBase() {} michael@0: }; michael@0: michael@0: michael@0: namespace mozilla { michael@0: typedef Fake_MediaStream MediaStream; michael@0: typedef Fake_SourceMediaStream SourceMediaStream; michael@0: typedef Fake_MediaStreamListener MediaStreamListener; michael@0: typedef Fake_MediaStreamDirectListener MediaStreamDirectListener; michael@0: typedef Fake_DOMMediaStream DOMMediaStream; michael@0: typedef Fake_DOMMediaStream DOMLocalMediaStream; michael@0: } michael@0: michael@0: #endif