mirror of https://github.com/roytam1/UXP
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
857 lines
31 KiB
857 lines
31 KiB
/* -*- 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; |
|
|
|
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); |
|
}; |
|
|
|
} // namespace mozilla |
|
|
|
#endif /* NSDOMMEDIASTREAM_H_ */
|
|
|