diff options
Diffstat (limited to 'dom/media/DOMMediaStream.h')
-rw-r--r-- | dom/media/DOMMediaStream.h | 868 |
1 files changed, 868 insertions, 0 deletions
diff --git a/dom/media/DOMMediaStream.h b/dom/media/DOMMediaStream.h new file mode 100644 index 000000000..12f3529a8 --- /dev/null +++ b/dom/media/DOMMediaStream.h @@ -0,0 +1,868 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef NSDOMMEDIASTREAM_H_ +#define NSDOMMEDIASTREAM_H_ + +#include "ImageContainer.h" + +#include "nsAutoPtr.h" +#include "nsCycleCollectionParticipant.h" +#include "nsWrapperCache.h" +#include "StreamTracks.h" +#include "nsIDOMWindow.h" +#include "nsIPrincipal.h" +#include "MediaTrackConstraints.h" +#include "mozilla/DOMEventTargetHelper.h" +#include "PrincipalChangeObserver.h" + +// X11 has a #define for CurrentTime. Unbelievable :-(. +// See dom/media/webaudio/AudioContext.h for more fun! +#ifdef CurrentTime +#undef CurrentTime +#endif + +namespace mozilla { + +class DOMHwMediaStream; +class DOMLocalMediaStream; +class DOMMediaStream; +class MediaStream; +class MediaInputPort; +class DirectMediaStreamListener; +class MediaStreamGraph; +class ProcessedMediaStream; + +enum class BlockingMode; + +namespace dom { +class AudioNode; +class HTMLCanvasElement; +class MediaStreamTrack; +class MediaStreamTrackSource; +class AudioStreamTrack; +class VideoStreamTrack; +class AudioTrack; +class VideoTrack; +class AudioTrackList; +class VideoTrackList; +class MediaTrackListListener; +} // namespace dom + +namespace layers { +class ImageContainer; +class OverlayImage; +} // namespace layers + +namespace media { +template<typename V, typename E> class Pledge; +} // namespace media + +#define NS_DOMMEDIASTREAM_IID \ +{ 0x8cb65468, 0x66c0, 0x444e, \ + { 0x89, 0x9f, 0x89, 0x1d, 0x9e, 0xd2, 0xbe, 0x7c } } + +class OnTracksAvailableCallback { +public: + virtual ~OnTracksAvailableCallback() {} + virtual void NotifyTracksAvailable(DOMMediaStream* aStream) = 0; +}; + +/** + * Interface through which a DOMMediaStream can query its producer for a + * MediaStreamTrackSource. This will be used whenever a track occurs in the + * DOMMediaStream's owned stream that has not yet been created on the main + * thread (see DOMMediaStream::CreateOwnDOMTrack). + */ +class MediaStreamTrackSourceGetter : public nsISupports +{ + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_CLASS(MediaStreamTrackSourceGetter) + +public: + MediaStreamTrackSourceGetter() + { + MOZ_COUNT_CTOR(MediaStreamTrackSourceGetter); + } + + virtual already_AddRefed<dom::MediaStreamTrackSource> + GetMediaStreamTrackSource(TrackID aInputTrackID) = 0; + +protected: + virtual ~MediaStreamTrackSourceGetter() + { + MOZ_COUNT_DTOR(MediaStreamTrackSourceGetter); + } +}; + +/** + * DOM wrapper for MediaStreams. + * + * To account for track operations such as clone(), addTrack() and + * removeTrack(), a DOMMediaStream wraps three internal (and chained) + * MediaStreams: + * 1. mInputStream + * - Controlled by the owner/source of the DOMMediaStream. + * It's a stream of the type indicated by + * - DOMMediaStream::CreateSourceStream/CreateTrackUnionStream. A source + * typically creates its DOMMediaStream, creates the MediaStreamTracks + * owned by said stream, then gets the internal input stream to which it + * feeds data for the previously created tracks. + * - When necessary it can create tracks on the internal stream only and + * their corresponding MediaStreamTracks will be asynchronously created. + * 2. mOwnedStream + * - A TrackUnionStream containing tracks owned by this stream. + * - The internal model of a MediaStreamTrack consists of its owning + * DOMMediaStream and the TrackID of the corresponding internal track in + * the owning DOMMediaStream's mOwnedStream. + * - The owned stream is different from the input stream since a cloned + * DOMMediaStream is also the owner of its (cloned) MediaStreamTracks. + * - Stopping an original track shall not stop its clone. This is + * solved by stopping it at the owned stream, while the clone's owned + * stream gets data directly from the original input stream. + * - A DOMMediaStream (original or clone) gets all tracks dynamically + * added by the source automatically forwarded by having a TRACK_ANY + * MediaInputPort set up from the owning DOMMediaStream's input stream + * to this DOMMediaStream's owned stream. + * 3. mPlaybackStream + * - A TrackUnionStream containing the tracks corresponding to the + * MediaStreamTracks currently in this DOMMediaStream (per getTracks()). + * - Similarly as for mOwnedStream, there's a TRACK_ANY MediaInputPort set + * up from the owned stream to the playback stream to allow tracks + * dynamically added by the source to be automatically forwarded to any + * audio or video sinks. + * - MediaStreamTracks added by addTrack() are set up with a MediaInputPort + * locked to their internal TrackID, from their owning DOMMediaStream's + * owned stream to this playback stream. + * + * + * A graphical representation of how tracks are connected in various cases as + * follows: + * + * addTrack()ed case: + * DOMStream A + * Input Owned Playback + * t1 ---------> t1 ------------> t1 <- MediaStreamTrack X + * (pointing to t1 in A) + * --------> t2 <- MediaStreamTrack Y + * / (pointing to t1 in B) + * DOMStream B / + * Input Owned / Playback + * t1 ---------> t1 ------------> t1 <- MediaStreamTrack Y + * (pointing to t1 in B) + * + * removeTrack()ed case: + * DOMStream A + * Input Owned Playback + * t1 ---------> t1 <- No tracks + * + * + * clone()d case: + * DOMStream A + * Input Owned Playback + * t1 ---------> t1 ------------> t1 <- MediaStreamTrack X + * \ (pointing to t1 in A) + * ----- + * DOMStream B \ + * Input \ Owned Playback + * -> t1 ------------> t1 <- MediaStreamTrack Y + * (pointing to t1 in B) + * + * + * addTrack()ed, removeTrack()ed and clone()d case: + * + * Here we have done the following: + * var A = someStreamWithTwoTracks; + * var B = someStreamWithOneTrack; + * var X = A.getTracks()[0]; + * var Y = A.getTracks()[1]; + * var Z = B.getTracks()[0]; + * A.addTrack(Z); + * A.removeTrack(X); + * B.removeTrack(Z); + * var A' = A.clone(); + * + * DOMStream A + * Input Owned Playback + * t1 ---------> t1 <- MediaStreamTrack X (removed) + * (pointing to t1 in A) + * t2 ---------> t2 ------------> t2 <- MediaStreamTrack Y + * \ (pointing to t2 in A) + * \ ------> t3 <- MediaStreamTrack Z + * \ / (pointing to t1 in B) + * DOMStream B \ / + * Input \ Owned / Playback + * t1 ---^-----> t1 --- <- MediaStreamTrack Z (removed) + * \ \ (pointing to t1 in B) + * \ \ + * DOMStream A' \ \ + * Input \ \ Owned Playback + * \ -> t1 ------------> t1 <- MediaStreamTrack Y' + * \ (pointing to t1 in A') + * ----> t2 ------------> t2 <- MediaStreamTrack Z' + * (pointing to t2 in A') + */ +class DOMMediaStream : public DOMEventTargetHelper, + public dom::PrincipalChangeObserver<dom::MediaStreamTrack> +{ + friend class DOMLocalMediaStream; + friend class dom::MediaStreamTrack; + typedef dom::MediaStreamTrack MediaStreamTrack; + typedef dom::AudioStreamTrack AudioStreamTrack; + typedef dom::VideoStreamTrack VideoStreamTrack; + typedef dom::MediaStreamTrackSource MediaStreamTrackSource; + typedef dom::AudioTrack AudioTrack; + typedef dom::VideoTrack VideoTrack; + typedef dom::AudioTrackList AudioTrackList; + typedef dom::VideoTrackList VideoTrackList; + +public: + typedef dom::MediaTrackConstraints MediaTrackConstraints; + + class TrackListener { + public: + virtual ~TrackListener() {} + + /** + * Called when the DOMMediaStream has a live track added, either by + * script (addTrack()) or the source creating one. + */ + virtual void + NotifyTrackAdded(const RefPtr<MediaStreamTrack>& aTrack) {}; + + /** + * Called when the DOMMediaStream removes a live track from playback, either + * by script (removeTrack(), track.stop()) or the source ending it. + */ + virtual void + NotifyTrackRemoved(const RefPtr<MediaStreamTrack>& aTrack) {}; + + /** + * Called when the DOMMediaStream has become active. + */ + virtual void + NotifyActive() {}; + + /** + * Called when the DOMMediaStream has become inactive. + */ + virtual void + NotifyInactive() {}; + }; + + /** + * TrackPort is a representation of a MediaStreamTrack-MediaInputPort pair + * that make up a link between the Owned stream and the Playback stream. + * + * Semantically, the track is the identifier/key and the port the value of this + * connection. + * + * The input port can be shared between several TrackPorts. This is the case + * for DOMMediaStream's mPlaybackPort which forwards all tracks in its + * mOwnedStream automatically. + * + * If the MediaStreamTrack is owned by another DOMMediaStream (called A) than + * the one owning the TrackPort (called B), the input port (locked to the + * MediaStreamTrack's TrackID) connects A's mOwnedStream to B's mPlaybackStream. + * + * A TrackPort may never leave the DOMMediaStream it was created in. Internal + * use only. + */ + class TrackPort + { + public: + NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(TrackPort) + NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(TrackPort) + + /** + * Indicates MediaInputPort ownership to the TrackPort. + * + * OWNED - Owned by the TrackPort itself. TrackPort must destroy the + * input port when it's destructed. + * EXTERNAL - Owned by another entity. It's the caller's responsibility to + * ensure the the MediaInputPort outlives the TrackPort. + */ + enum class InputPortOwnership { + OWNED = 1, + EXTERNAL + }; + + TrackPort(MediaInputPort* aInputPort, + MediaStreamTrack* aTrack, + const InputPortOwnership aOwnership); + + protected: + virtual ~TrackPort(); + + public: + void DestroyInputPort(); + + /** + * Returns the source stream of the input port. + */ + MediaStream* GetSource() const; + + /** + * Returns the track ID this track is locked to in the source stream of the + * input port. + */ + TrackID GetSourceTrackId() const; + + MediaInputPort* GetInputPort() const { return mInputPort; } + MediaStreamTrack* GetTrack() const { return mTrack; } + + /** + * Blocks aTrackId from going into mInputPort unless the port has been + * destroyed. Returns a pledge that gets resolved when the MediaStreamGraph + * has applied the block in the playback stream. + */ + already_AddRefed<media::Pledge<bool, nsresult>> + BlockSourceTrackId(TrackID aTrackId, BlockingMode aBlockingMode); + + private: + RefPtr<MediaInputPort> mInputPort; + RefPtr<MediaStreamTrack> mTrack; + + // Defines if we've been given ownership of the input port or if it's owned + // externally. The owner is responsible for destroying the port. + const InputPortOwnership mOwnership; + }; + + DOMMediaStream(nsPIDOMWindowInner* aWindow, + MediaStreamTrackSourceGetter* aTrackSourceGetter); + + NS_DECL_ISUPPORTS_INHERITED + NS_REALLY_FORWARD_NSIDOMEVENTTARGET(DOMEventTargetHelper) + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DOMMediaStream, + DOMEventTargetHelper) + NS_DECLARE_STATIC_IID_ACCESSOR(NS_DOMMEDIASTREAM_IID) + + nsPIDOMWindowInner* GetParentObject() const + { + return mWindow; + } + virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; + + // WebIDL + + static already_AddRefed<DOMMediaStream> + Constructor(const dom::GlobalObject& aGlobal, + ErrorResult& aRv); + + static already_AddRefed<DOMMediaStream> + Constructor(const dom::GlobalObject& aGlobal, + const DOMMediaStream& aStream, + ErrorResult& aRv); + + static already_AddRefed<DOMMediaStream> + Constructor(const dom::GlobalObject& aGlobal, + const dom::Sequence<OwningNonNull<MediaStreamTrack>>& aTracks, + ErrorResult& aRv); + + double CurrentTime(); + + void GetId(nsAString& aID) const; + + void GetAudioTracks(nsTArray<RefPtr<AudioStreamTrack> >& aTracks) const; + void GetVideoTracks(nsTArray<RefPtr<VideoStreamTrack> >& aTracks) const; + void GetTracks(nsTArray<RefPtr<MediaStreamTrack> >& aTracks) const; + MediaStreamTrack* GetTrackById(const nsAString& aId) const; + void AddTrack(MediaStreamTrack& aTrack); + void RemoveTrack(MediaStreamTrack& aTrack); + + /** Identical to CloneInternal(TrackForwardingOption::EXPLICIT) */ + already_AddRefed<DOMMediaStream> Clone(); + + bool Active() const; + + IMPL_EVENT_HANDLER(addtrack) + + // NON-WebIDL + + /** + * Option to provide to CloneInternal() of which tracks should be forwarded + * from the source stream (`this`) to the returned stream clone. + * + * CURRENT forwards the tracks currently in the source stream's track set. + * ALL forwards like EXPLICIT plus any and all future tracks originating + * from the same input stream as the source DOMMediaStream (`this`). + */ + enum class TrackForwardingOption { + CURRENT, + ALL + }; + already_AddRefed<DOMMediaStream> CloneInternal(TrackForwardingOption aForwarding); + + MediaStreamTrack* GetOwnedTrackById(const nsAString& aId); + + /** + * Returns true if this DOMMediaStream has aTrack in its mPlaybackStream. + */ + bool HasTrack(const MediaStreamTrack& aTrack) const; + + /** + * Returns true if this DOMMediaStream owns aTrack. + */ + bool OwnsTrack(const MediaStreamTrack& aTrack) const; + + /** + * Returns the corresponding MediaStreamTrack if it's in our mOwnedStream. + * aInputTrackID should match the track's TrackID in its input stream, + * and aTrackID the TrackID in mOwnedStream. + * + * When aTrackID is not supplied or set to TRACK_ANY, we return the first + * MediaStreamTrack that matches the given input track. Note that there may + * be multiple MediaStreamTracks matching the same input track, but that they + * in that case all share the same MediaStreamTrackSource. + */ + MediaStreamTrack* FindOwnedDOMTrack(MediaStream* aInputStream, + TrackID aInputTrackID, + TrackID aTrackID = TRACK_ANY) const; + + /** + * Returns the TrackPort connecting aTrack's input stream to mOwnedStream, + * or nullptr if aTrack is not owned by this DOMMediaStream. + */ + TrackPort* FindOwnedTrackPort(const MediaStreamTrack& aTrack) const; + + /** + * Returns the corresponding MediaStreamTrack if it's in our mPlaybackStream. + * aInputTrackID should match the track's TrackID in its owned stream. + */ + MediaStreamTrack* FindPlaybackDOMTrack(MediaStream* aInputStream, + TrackID aInputTrackID) const; + + /** + * Returns the TrackPort connecting mOwnedStream to mPlaybackStream for aTrack. + */ + TrackPort* FindPlaybackTrackPort(const MediaStreamTrack& aTrack) const; + + MediaStream* GetInputStream() const { return mInputStream; } + ProcessedMediaStream* GetOwnedStream() const { return mOwnedStream; } + ProcessedMediaStream* GetPlaybackStream() const { return mPlaybackStream; } + + /** + * Allows a video element to identify this stream as a camera stream, which + * needs special treatment. + */ + virtual MediaStream* GetCameraStream() const { return nullptr; } + + /** + * Allows users to get access to media data without going through graph + * queuing. Returns a bool to let us know if direct data will be delivered. + */ + bool AddDirectListener(DirectMediaStreamListener *aListener); + void RemoveDirectListener(DirectMediaStreamListener *aListener); + + virtual DOMLocalMediaStream* AsDOMLocalMediaStream() { return nullptr; } + virtual DOMHwMediaStream* AsDOMHwMediaStream() { return nullptr; } + + /** + * Legacy method that returns true when the playback stream has finished. + */ + bool IsFinished() const; + + /** + * Becomes inactive only when the playback stream has finished. + */ + void SetInactiveOnFinish(); + + /** + * Returns a principal indicating who may access this stream. The stream contents + * can only be accessed by principals subsuming this principal. + */ + nsIPrincipal* GetPrincipal() { return mPrincipal; } + + /** + * Returns a principal indicating who may access video data of this stream. + * The video principal will be a combination of all live video tracks. + */ + nsIPrincipal* GetVideoPrincipal() { return mVideoPrincipal; } + + // From PrincipalChangeObserver<MediaStreamTrack>. + void PrincipalChanged(MediaStreamTrack* aTrack) override; + + /** + * Add a PrincipalChangeObserver to this stream. + * + * Returns true if it was successfully added. + * + * Ownership of the PrincipalChangeObserver remains with the caller, and it's + * the caller's responsibility to remove the observer before it dies. + */ + bool AddPrincipalChangeObserver(dom::PrincipalChangeObserver<DOMMediaStream>* aObserver); + + /** + * Remove an added PrincipalChangeObserver from this stream. + * + * Returns true if it was successfully removed. + */ + bool RemovePrincipalChangeObserver(dom::PrincipalChangeObserver<DOMMediaStream>* aObserver); + + // Webrtc allows the remote side to name a stream whatever it wants, and we + // need to surface this to content. + void AssignId(const nsAString& aID) { mID = aID; } + + /** + * Create a DOMMediaStream whose underlying input stream is a SourceMediaStream. + */ + static already_AddRefed<DOMMediaStream> CreateSourceStreamAsInput(nsPIDOMWindowInner* aWindow, + MediaStreamGraph* aGraph, + MediaStreamTrackSourceGetter* aTrackSourceGetter = nullptr); + + /** + * Create a DOMMediaStream whose underlying input stream is a TrackUnionStream. + */ + static already_AddRefed<DOMMediaStream> CreateTrackUnionStreamAsInput(nsPIDOMWindowInner* aWindow, + MediaStreamGraph* aGraph, + MediaStreamTrackSourceGetter* aTrackSourceGetter = nullptr); + + /** + * Create an DOMMediaStream whose underlying input stream is an + * AudioCaptureStream. + */ + static already_AddRefed<DOMMediaStream> + CreateAudioCaptureStreamAsInput(nsPIDOMWindowInner* aWindow, + nsIPrincipal* aPrincipal, + MediaStreamGraph* aGraph); + + void SetLogicalStreamStartTime(StreamTime aTime) + { + mLogicalStreamStartTime = aTime; + } + + /** + * Adds a MediaStreamTrack to mTracks and raises "addtrack". + * + * Note that "addtrack" is raised synchronously and only has an effect if + * this MediaStream is already exposed to script. For spec compliance this is + * to be called from an async task. + */ + void AddTrackInternal(MediaStreamTrack* aTrack); + + /** + * Called for each track in our owned stream to indicate to JS that we + * are carrying that track. + * + * Pre-creates a MediaStreamTrack and returns it. + * It is up to the caller to make sure it is added through AddTrackInternal. + */ + already_AddRefed<MediaStreamTrack> CreateDOMTrack(TrackID aTrackID, + MediaSegment::Type aType, + MediaStreamTrackSource* aSource, + const MediaTrackConstraints& aConstraints = MediaTrackConstraints()); + + /** + * Creates a MediaStreamTrack cloned from aTrack, adds it to mTracks and + * returns it. + * aCloneTrackID is the TrackID the new track will get in mOwnedStream. + */ + already_AddRefed<MediaStreamTrack> CloneDOMTrack(MediaStreamTrack& aTrack, + TrackID aCloneTrackID); + + // When the initial set of tracks has been added, run + // aCallback->NotifyTracksAvailable. + // It is allowed to do anything, including run script. + // aCallback may run immediately during this call if tracks are already + // available! + // We only care about track additions, we'll fire the notification even if + // some of the tracks have been removed. + // Takes ownership of aCallback. + void OnTracksAvailable(OnTracksAvailableCallback* aCallback); + + /** + * Add an nsISupports object that this stream will keep alive as long as + * the stream itself is alive. + */ + void AddConsumerToKeepAlive(nsISupports* aConsumer) + { + mConsumersToKeepAlive.AppendElement(aConsumer); + } + + // Registers a track listener to this MediaStream, for listening to changes + // to our track set. The caller must call UnregisterTrackListener before + // being destroyed, so we don't hold on to a dead pointer. Main thread only. + void RegisterTrackListener(TrackListener* aListener); + + // Unregisters a track listener from this MediaStream. The caller must call + // UnregisterTrackListener before being destroyed, so we don't hold on to + // a dead pointer. Main thread only. + void UnregisterTrackListener(TrackListener* aListener); + +protected: + virtual ~DOMMediaStream(); + + void Destroy(); + void InitSourceStream(MediaStreamGraph* aGraph); + void InitTrackUnionStream(MediaStreamGraph* aGraph); + void InitAudioCaptureStream(nsIPrincipal* aPrincipal, MediaStreamGraph* aGraph); + + // Sets up aStream as mInputStream. A producer may append data to a + // SourceMediaStream input stream, or connect another stream to a + // TrackUnionStream input stream. + void InitInputStreamCommon(MediaStream* aStream, MediaStreamGraph* aGraph); + + // Sets up a new TrackUnionStream as mOwnedStream and connects it to + // mInputStream with a TRACK_ANY MediaInputPort if available. + // If this DOMMediaStream should have an input stream (producing data), + // it has to be initiated before the owned stream. + void InitOwnedStreamCommon(MediaStreamGraph* aGraph); + + // Sets up a new TrackUnionStream as mPlaybackStream and connects it to + // mOwnedStream with a TRACK_ANY MediaInputPort if available. + // If this DOMMediaStream should have an owned stream (producer or clone), + // it has to be initiated before the playback stream. + void InitPlaybackStreamCommon(MediaStreamGraph* aGraph); + + void CheckTracksAvailable(); + + // Called when MediaStreamGraph has finished an iteration where tracks were + // created. + void NotifyTracksCreated(); + + // Called when our playback stream has finished in the MediaStreamGraph. + void NotifyFinished(); + + // Dispatches NotifyActive() to all registered track listeners. + void NotifyActive(); + + // Dispatches NotifyInactive() to all registered track listeners. + void NotifyInactive(); + + // Dispatches NotifyTrackAdded() to all registered track listeners. + void NotifyTrackAdded(const RefPtr<MediaStreamTrack>& aTrack); + + // Dispatches NotifyTrackRemoved() to all registered track listeners. + void NotifyTrackRemoved(const RefPtr<MediaStreamTrack>& aTrack); + + // Dispatches "addtrack" or "removetrack". + nsresult DispatchTrackEvent(const nsAString& aName, + const RefPtr<MediaStreamTrack>& aTrack); + + class OwnedStreamListener; + friend class OwnedStreamListener; + + class PlaybackStreamListener; + friend class PlaybackStreamListener; + + class PlaybackTrackListener; + friend class PlaybackTrackListener; + + /** + * Block a track in our playback stream. Calls NotifyPlaybackTrackBlocked() + * after the MediaStreamGraph has applied the block and the track is no longer + * live. + */ + void BlockPlaybackTrack(TrackPort* aTrack); + + /** + * Called on main thread after MediaStreamGraph has applied a track block in + * our playback stream. + */ + void NotifyPlaybackTrackBlocked(); + + // Recomputes the current principal of this stream based on the set of tracks + // it currently contains. PrincipalChangeObservers will be notified only if + // the principal changes. + void RecomputePrincipal(); + + // StreamTime at which the currentTime attribute would return 0. + StreamTime mLogicalStreamStartTime; + + // We need this to track our parent object. + nsCOMPtr<nsPIDOMWindowInner> mWindow; + + // MediaStreams are owned by the graph, but we tell them when to die, + // and they won't die until we let them. + + // This stream contains tracks used as input by us. Cloning happens from this + // stream. Tracks may exist in these stream but not in |mOwnedStream| if they + // have been stopped. + MediaStream* mInputStream; + + // This stream contains tracks owned by us (if we were created directly from + // source, or cloned from some other stream). Tracks map to |mOwnedTracks|. + ProcessedMediaStream* mOwnedStream; + + // This stream contains tracks currently played by us, despite of owner. + // Tracks map to |mTracks|. + ProcessedMediaStream* mPlaybackStream; + + // This port connects mInputStream to mOwnedStream. All tracks forwarded. + RefPtr<MediaInputPort> mOwnedPort; + + // This port connects mOwnedStream to mPlaybackStream. All tracks not + // explicitly blocked due to removal are forwarded. + RefPtr<MediaInputPort> mPlaybackPort; + + // MediaStreamTracks corresponding to tracks in our mOwnedStream. + AutoTArray<RefPtr<TrackPort>, 2> mOwnedTracks; + + // MediaStreamTracks corresponding to tracks in our mPlaybackStream. + AutoTArray<RefPtr<TrackPort>, 2> mTracks; + + // Number of MediaStreamTracks that have been removed on main thread but are + // waiting to be removed on MediaStreamGraph thread. + size_t mTracksPendingRemoval; + + // The interface through which we can query the stream producer for + // track sources. + RefPtr<MediaStreamTrackSourceGetter> mTrackSourceGetter; + + // Listener tracking changes to mOwnedStream. We use this to notify the + // MediaStreamTracks we own about state changes. + RefPtr<OwnedStreamListener> mOwnedListener; + + // Listener tracking changes to mPlaybackStream. This drives state changes + // in this DOMMediaStream and notifications to mTrackListeners. + RefPtr<PlaybackStreamListener> mPlaybackListener; + + // Listener tracking when live MediaStreamTracks in mTracks end. + RefPtr<PlaybackTrackListener> mPlaybackTrackListener; + + nsTArray<nsAutoPtr<OnTracksAvailableCallback> > mRunOnTracksAvailable; + + // Set to true after MediaStreamGraph has created tracks for mPlaybackStream. + bool mTracksCreated; + + nsString mID; + + // Keep these alive while the stream is alive. + nsTArray<nsCOMPtr<nsISupports>> mConsumersToKeepAlive; + + bool mNotifiedOfMediaStreamGraphShutdown; + + // The track listeners subscribe to changes in this stream's track set. + nsTArray<TrackListener*> mTrackListeners; + + // True if this stream has live tracks. + bool mActive; + + // True if this stream only sets mActive to false when its playback stream + // finishes. This is a hack to maintain legacy functionality for playing a + // HTMLMediaElement::MozCaptureStream(). See bug 1302379. + bool mSetInactiveOnFinish; + +private: + void NotifyPrincipalChanged(); + // Principal identifying who may access the collected contents of this stream. + // If null, this stream can be used by anyone because it has no content yet. + nsCOMPtr<nsIPrincipal> mPrincipal; + // Video principal is used by video element as access is requested to its + // image data. + nsCOMPtr<nsIPrincipal> mVideoPrincipal; + nsTArray<dom::PrincipalChangeObserver<DOMMediaStream>*> mPrincipalChangeObservers; + CORSMode mCORSMode; +}; + +NS_DEFINE_STATIC_IID_ACCESSOR(DOMMediaStream, + NS_DOMMEDIASTREAM_IID) + +#define NS_DOMLOCALMEDIASTREAM_IID \ +{ 0xb1437260, 0xec61, 0x4dfa, \ + { 0x92, 0x54, 0x04, 0x44, 0xe2, 0xb5, 0x94, 0x9c } } + +class DOMLocalMediaStream : public DOMMediaStream +{ +public: + explicit DOMLocalMediaStream(nsPIDOMWindowInner* aWindow, + MediaStreamTrackSourceGetter* aTrackSourceGetter) + : DOMMediaStream(aWindow, aTrackSourceGetter) {} + + NS_DECL_ISUPPORTS_INHERITED + NS_DECLARE_STATIC_IID_ACCESSOR(NS_DOMLOCALMEDIASTREAM_IID) + + virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; + + void Stop(); + + /** + * Create an nsDOMLocalMediaStream whose underlying stream is a SourceMediaStream. + */ + static already_AddRefed<DOMLocalMediaStream> + CreateSourceStreamAsInput(nsPIDOMWindowInner* aWindow, + MediaStreamGraph* aGraph, + MediaStreamTrackSourceGetter* aTrackSourceGetter = nullptr); + + /** + * Create an nsDOMLocalMediaStream whose underlying stream is a TrackUnionStream. + */ + static already_AddRefed<DOMLocalMediaStream> + CreateTrackUnionStreamAsInput(nsPIDOMWindowInner* aWindow, + MediaStreamGraph* aGraph, + MediaStreamTrackSourceGetter* aTrackSourceGetter = nullptr); + +protected: + virtual ~DOMLocalMediaStream(); + + void StopImpl(); +}; + +NS_DEFINE_STATIC_IID_ACCESSOR(DOMLocalMediaStream, + NS_DOMLOCALMEDIASTREAM_IID) + +class DOMAudioNodeMediaStream : public DOMMediaStream +{ + typedef dom::AudioNode AudioNode; +public: + DOMAudioNodeMediaStream(nsPIDOMWindowInner* aWindow, AudioNode* aNode); + + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DOMAudioNodeMediaStream, DOMMediaStream) + + /** + * Create a DOMAudioNodeMediaStream whose underlying stream is a TrackUnionStream. + */ + static already_AddRefed<DOMAudioNodeMediaStream> + CreateTrackUnionStreamAsInput(nsPIDOMWindowInner* aWindow, + AudioNode* aNode, + MediaStreamGraph* aGraph); + +protected: + ~DOMAudioNodeMediaStream(); + +private: + // If this object wraps a stream owned by an AudioNode, we need to ensure that + // the node isn't cycle-collected too early. + RefPtr<AudioNode> mStreamNode; +}; + +class DOMHwMediaStream : public DOMLocalMediaStream +{ + typedef mozilla::gfx::IntSize IntSize; + typedef layers::OverlayImage OverlayImage; +#ifdef MOZ_WIDGET_GONK + typedef layers::OverlayImage::Data Data; +#endif + +public: + explicit DOMHwMediaStream(nsPIDOMWindowInner* aWindow); + + static already_AddRefed<DOMHwMediaStream> CreateHwStream(nsPIDOMWindowInner* aWindow, + OverlayImage* aImage = nullptr); + virtual DOMHwMediaStream* AsDOMHwMediaStream() override { return this; } + int32_t RequestOverlayId(); + void SetOverlayId(int32_t aOverlayId); + void SetImageSize(uint32_t width, uint32_t height); + void SetOverlayImage(OverlayImage* aImage); + +protected: + ~DOMHwMediaStream(); + +private: + void Init(MediaStream* aStream, OverlayImage* aImage); + +#ifdef MOZ_WIDGET_GONK + const int DEFAULT_IMAGE_ID = 0x01; + const int DEFAULT_IMAGE_WIDTH = 400; + const int DEFAULT_IMAGE_HEIGHT = 300; + RefPtr<OverlayImage> mOverlayImage; + PrincipalHandle mPrincipalHandle; +#endif +}; + +} // namespace mozilla + +#endif /* NSDOMMEDIASTREAM_H_ */ |