michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ 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 NSDOMMEDIASTREAM_H_ michael@0: #define NSDOMMEDIASTREAM_H_ michael@0: michael@0: #include "nsIDOMMediaStream.h" michael@0: #include "nsCycleCollectionParticipant.h" michael@0: #include "nsWrapperCache.h" michael@0: #include "StreamBuffer.h" michael@0: #include "nsIDOMWindow.h" michael@0: michael@0: class nsXPCClassInfo; michael@0: class nsIPrincipal; michael@0: michael@0: // GetCurrentTime is defined in winbase.h as zero argument macro forwarding to michael@0: // GetTickCount() and conflicts with NS_DECL_NSIDOMMEDIASTREAM, containing michael@0: // currentTime getter. michael@0: #ifdef GetCurrentTime michael@0: #undef GetCurrentTime michael@0: #endif michael@0: // X11 has a #define for CurrentTime. Unbelievable :-(. michael@0: // See content/media/webaudio/AudioContext.h for more fun! michael@0: #ifdef CurrentTime michael@0: #undef CurrentTime michael@0: #endif michael@0: michael@0: namespace mozilla { michael@0: michael@0: class MediaStream; michael@0: michael@0: namespace dom { michael@0: class AudioNode; michael@0: class MediaStreamTrack; michael@0: class AudioStreamTrack; michael@0: class VideoStreamTrack; michael@0: } michael@0: michael@0: class MediaStreamDirectListener; michael@0: michael@0: /** michael@0: * DOM wrapper for MediaStreams. michael@0: */ michael@0: class DOMMediaStream : public nsIDOMMediaStream, michael@0: public nsWrapperCache michael@0: { michael@0: friend class DOMLocalMediaStream; michael@0: typedef dom::MediaStreamTrack MediaStreamTrack; michael@0: typedef dom::AudioStreamTrack AudioStreamTrack; michael@0: typedef dom::VideoStreamTrack VideoStreamTrack; michael@0: michael@0: public: michael@0: typedef uint8_t TrackTypeHints; michael@0: michael@0: DOMMediaStream(); michael@0: virtual ~DOMMediaStream(); michael@0: michael@0: NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMMediaStream) michael@0: NS_DECL_CYCLE_COLLECTING_ISUPPORTS michael@0: michael@0: nsIDOMWindow* GetParentObject() const michael@0: { michael@0: return mWindow; michael@0: } michael@0: virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE; michael@0: michael@0: // WebIDL michael@0: double CurrentTime(); michael@0: michael@0: void GetAudioTracks(nsTArray >& aTracks); michael@0: void GetVideoTracks(nsTArray >& aTracks); michael@0: michael@0: MediaStream* GetStream() const { return mStream; } michael@0: michael@0: /** michael@0: * Overridden in DOMLocalMediaStreams to allow getUserMedia to pass michael@0: * data directly to RTCPeerConnection without going through graph queuing. michael@0: * Returns a bool to let us know if direct data will be delivered. michael@0: */ michael@0: virtual bool AddDirectListener(MediaStreamDirectListener *aListener) { return false; } michael@0: virtual void RemoveDirectListener(MediaStreamDirectListener *aListener) {} michael@0: michael@0: /** michael@0: * Overridden in DOMLocalMediaStreams to allow getUserMedia to disable michael@0: * media at the SourceMediaStream. michael@0: */ michael@0: virtual void SetTrackEnabled(TrackID aTrackID, bool aEnabled); michael@0: michael@0: bool IsFinished(); michael@0: /** michael@0: * Returns a principal indicating who may access this stream. The stream contents michael@0: * can only be accessed by principals subsuming this principal. michael@0: */ michael@0: nsIPrincipal* GetPrincipal() { return mPrincipal; } michael@0: michael@0: /** michael@0: * Indicate that data will be contributed to this stream from origin aPrincipal. michael@0: * If aPrincipal is null, this is ignored. Otherwise, from now on the contents michael@0: * of this stream can only be accessed by principals that subsume aPrincipal. michael@0: * Returns true if the stream's principal changed. michael@0: */ michael@0: bool CombineWithPrincipal(nsIPrincipal* aPrincipal); michael@0: michael@0: /** michael@0: * Called when this stream's MediaStreamGraph has been shut down. Normally michael@0: * MSGs are only shut down when all streams have been removed, so this michael@0: * will only be called during a forced shutdown due to application exit. michael@0: */ michael@0: void NotifyMediaStreamGraphShutdown(); michael@0: /** michael@0: * Called when the main-thread state of the MediaStream changed. michael@0: */ michael@0: void NotifyStreamStateChanged(); michael@0: michael@0: // Indicate what track types we eventually expect to add to this stream michael@0: enum { michael@0: HINT_CONTENTS_AUDIO = 1 << 0, michael@0: HINT_CONTENTS_VIDEO = 1 << 1 michael@0: }; michael@0: TrackTypeHints GetHintContents() const { return mHintContents; } michael@0: void SetHintContents(TrackTypeHints aHintContents) { mHintContents = aHintContents; } michael@0: michael@0: /** michael@0: * Create an nsDOMMediaStream whose underlying stream is a SourceMediaStream. michael@0: */ michael@0: static already_AddRefed michael@0: CreateSourceStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents); michael@0: michael@0: /** michael@0: * Create an nsDOMMediaStream whose underlying stream is a TrackUnionStream. michael@0: */ michael@0: static already_AddRefed michael@0: CreateTrackUnionStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents = 0); michael@0: michael@0: void SetLogicalStreamStartTime(StreamTime aTime) michael@0: { michael@0: mLogicalStreamStartTime = aTime; michael@0: } michael@0: michael@0: // Notifications from StreamListener. michael@0: // CreateDOMTrack should only be called when it's safe to run script. michael@0: MediaStreamTrack* CreateDOMTrack(TrackID aTrackID, MediaSegment::Type aType); michael@0: MediaStreamTrack* GetDOMTrackFor(TrackID aTrackID); michael@0: michael@0: class OnTracksAvailableCallback { michael@0: public: michael@0: OnTracksAvailableCallback(uint8_t aExpectedTracks = 0) michael@0: : mExpectedTracks(aExpectedTracks) {} michael@0: virtual ~OnTracksAvailableCallback() {} michael@0: virtual void NotifyTracksAvailable(DOMMediaStream* aStream) = 0; michael@0: TrackTypeHints GetExpectedTracks() { return mExpectedTracks; } michael@0: void SetExpectedTracks(TrackTypeHints aExpectedTracks) { mExpectedTracks = aExpectedTracks; } michael@0: private: michael@0: TrackTypeHints mExpectedTracks; michael@0: }; michael@0: // When one track of the appropriate type has been added for each bit set michael@0: // in aCallback->GetExpectedTracks(), run aCallback->NotifyTracksAvailable. michael@0: // It is allowed to do anything, including run script. michael@0: // aCallback may run immediately during this call if tracks are already michael@0: // available! michael@0: // We only care about track additions, we'll fire the notification even if michael@0: // some of the tracks have been removed. michael@0: // Takes ownership of aCallback. michael@0: // If GetExpectedTracks() returns 0, the callback will be fired as soon as there are any tracks. michael@0: void OnTracksAvailable(OnTracksAvailableCallback* aCallback); michael@0: michael@0: /** michael@0: * Add an nsISupports object that this stream will keep alive as long as michael@0: * the stream is not finished. michael@0: */ michael@0: void AddConsumerToKeepAlive(nsISupports* aConsumer) michael@0: { michael@0: if (!IsFinished() && !mNotifiedOfMediaStreamGraphShutdown) { michael@0: mConsumersToKeepAlive.AppendElement(aConsumer); michael@0: } michael@0: } michael@0: michael@0: protected: michael@0: void Destroy(); michael@0: void InitSourceStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents); michael@0: void InitTrackUnionStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents); michael@0: void InitStreamCommon(MediaStream* aStream); michael@0: michael@0: void CheckTracksAvailable(); michael@0: michael@0: class StreamListener; michael@0: friend class StreamListener; michael@0: michael@0: // StreamTime at which the currentTime attribute would return 0. michael@0: StreamTime mLogicalStreamStartTime; michael@0: michael@0: // We need this to track our parent object. michael@0: nsCOMPtr mWindow; michael@0: michael@0: // MediaStream is owned by the graph, but we tell it when to die, and it won't michael@0: // die until we let it. michael@0: MediaStream* mStream; michael@0: // Principal identifying who may access the contents of this stream. michael@0: // If null, this stream can be used by anyone because it has no content yet. michael@0: nsCOMPtr mPrincipal; michael@0: michael@0: nsAutoTArray,2> mTracks; michael@0: nsRefPtr mListener; michael@0: michael@0: nsTArray > mRunOnTracksAvailable; michael@0: michael@0: // Keep these alive until the stream finishes michael@0: nsTArray > mConsumersToKeepAlive; michael@0: michael@0: // Indicate what track types we eventually expect to add to this stream michael@0: uint8_t mHintContents; michael@0: // Indicate what track types have been added to this stream michael@0: uint8_t mTrackTypesAvailable; michael@0: bool mNotifiedOfMediaStreamGraphShutdown; michael@0: }; michael@0: michael@0: class DOMLocalMediaStream : public DOMMediaStream, michael@0: public nsIDOMLocalMediaStream michael@0: { michael@0: public: michael@0: DOMLocalMediaStream() {} michael@0: virtual ~DOMLocalMediaStream(); michael@0: michael@0: NS_DECL_ISUPPORTS_INHERITED michael@0: michael@0: virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE; michael@0: michael@0: virtual void Stop(); michael@0: michael@0: /** michael@0: * Create an nsDOMLocalMediaStream whose underlying stream is a SourceMediaStream. michael@0: */ michael@0: static already_AddRefed michael@0: CreateSourceStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents); michael@0: michael@0: /** michael@0: * Create an nsDOMLocalMediaStream whose underlying stream is a TrackUnionStream. michael@0: */ michael@0: static already_AddRefed michael@0: CreateTrackUnionStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents = 0); michael@0: }; michael@0: michael@0: class DOMAudioNodeMediaStream : public DOMMediaStream michael@0: { michael@0: typedef dom::AudioNode AudioNode; michael@0: public: michael@0: DOMAudioNodeMediaStream(AudioNode* aNode); michael@0: michael@0: NS_DECL_ISUPPORTS_INHERITED michael@0: NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DOMAudioNodeMediaStream, DOMMediaStream) michael@0: michael@0: /** michael@0: * Create a DOMAudioNodeMediaStream whose underlying stream is a TrackUnionStream. michael@0: */ michael@0: static already_AddRefed michael@0: CreateTrackUnionStream(nsIDOMWindow* aWindow, michael@0: AudioNode* aNode, michael@0: TrackTypeHints aHintContents = 0); michael@0: michael@0: private: michael@0: // If this object wraps a stream owned by an AudioNode, we need to ensure that michael@0: // the node isn't cycle-collected too early. michael@0: nsRefPtr mStreamNode; michael@0: }; michael@0: michael@0: } michael@0: michael@0: #endif /* NSDOMMEDIASTREAM_H_ */