summaryrefslogtreecommitdiffstats
path: root/dom/media/DOMMediaStream.h
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/DOMMediaStream.h')
-rw-r--r--dom/media/DOMMediaStream.h868
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_ */