123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482 |
- /* -*- 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 MEDIASTREAMTRACK_H_
- #define MEDIASTREAMTRACK_H_
- #include "mozilla/DOMEventTargetHelper.h"
- #include "nsError.h"
- #include "nsID.h"
- #include "nsIPrincipal.h"
- #include "StreamTracks.h"
- #include "MediaTrackConstraints.h"
- #include "mozilla/CORSMode.h"
- #include "PrincipalChangeObserver.h"
- #include "mozilla/dom/MediaStreamTrackBinding.h"
- #include "mozilla/dom/MediaTrackSettingsBinding.h"
- #include "mozilla/media/MediaUtils.h"
- namespace mozilla {
- class DOMMediaStream;
- class MediaEnginePhotoCallback;
- class MediaInputPort;
- class MediaStream;
- class MediaStreamGraph;
- class MediaStreamGraphImpl;
- class MediaStreamTrackListener;
- class DirectMediaStreamTrackListener;
- class PeerConnectionImpl;
- class PeerConnectionMedia;
- class PeerIdentity;
- class ProcessedMediaStream;
- class RemoteSourceStreamInfo;
- class SourceStreamInfo;
- namespace dom {
- class AudioStreamTrack;
- class VideoStreamTrack;
- class MediaStreamError;
- /**
- * Common interface through which a MediaStreamTrack can communicate with its
- * producer on the main thread.
- *
- * Kept alive by a strong ref in all MediaStreamTracks (original and clones)
- * sharing this source.
- */
- class MediaStreamTrackSource : public nsISupports
- {
- NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_CLASS(MediaStreamTrackSource)
- public:
- class Sink
- {
- public:
- virtual void PrincipalChanged() = 0;
- };
- MediaStreamTrackSource(nsIPrincipal* aPrincipal,
- const nsString& aLabel)
- : mPrincipal(aPrincipal),
- mLabel(aLabel),
- mStopped(false)
- {
- MOZ_COUNT_CTOR(MediaStreamTrackSource);
- }
- /**
- * Use to clean up any resources that have to be cleaned before the
- * destructor is called. It is often too late in the destructor because
- * of garbage collection having removed the members already.
- */
- virtual void Destroy() {}
- /**
- * Gets the source's MediaSourceEnum for usage by PeerConnections.
- */
- virtual MediaSourceEnum GetMediaSource() const = 0;
- /**
- * Get this TrackSource's principal.
- */
- nsIPrincipal* GetPrincipal() const { return mPrincipal; }
- /**
- * Get the source's current CORSMode. If not applicable CORS_NONE is returned.
- * The sink will be notified of changes to our CORSMode through
- * PrincipalChanged().
- */
- virtual CORSMode GetCORSMode() const { return CORS_NONE; }
- /**
- * This is used in WebRTC. A peerIdentity constrained MediaStreamTrack cannot
- * be sent across the network to anything other than a peer with the provided
- * identity. If this is set, then GetPrincipal() should return an instance of
- * nsNullPrincipal.
- *
- * A track's PeerIdentity is immutable and will not change during the track's
- * lifetime.
- */
- virtual const PeerIdentity* GetPeerIdentity() const { return nullptr; }
- /**
- * MediaStreamTrack::GetLabel (see spec) calls through to here.
- */
- void GetLabel(nsAString& aLabel) { aLabel.Assign(mLabel); }
- /**
- * Forwards a photo request to backends that support it. Other backends return
- * NS_ERROR_NOT_IMPLEMENTED to indicate that a MediaStreamGraph-based fallback
- * should be used.
- */
- virtual nsresult TakePhoto(MediaEnginePhotoCallback*) const { return NS_ERROR_NOT_IMPLEMENTED; }
- typedef media::Pledge<bool, dom::MediaStreamError*> PledgeVoid;
- /**
- * We provide a fallback solution to ApplyConstraints() here.
- * Sources that support ApplyConstraints() will have to override it.
- */
- virtual already_AddRefed<PledgeVoid>
- ApplyConstraints(nsPIDOMWindowInner* aWindow,
- const dom::MediaTrackConstraints& aConstraints);
- /**
- * Same for GetSettings (no-op).
- */
- virtual void
- GetSettings(dom::MediaTrackSettings& aResult) {};
- /**
- * Called by the source interface when all registered sinks have unregistered.
- */
- virtual void Stop() = 0;
- /**
- * Called by each MediaStreamTrack clone on initialization.
- */
- void RegisterSink(Sink* aSink)
- {
- MOZ_ASSERT(NS_IsMainThread());
- if (mStopped) {
- return;
- }
- mSinks.AppendElement(aSink);
- }
- /**
- * Called by each MediaStreamTrack clone on Stop() if supported by the
- * source (us) or destruction.
- */
- void UnregisterSink(Sink* aSink)
- {
- MOZ_ASSERT(NS_IsMainThread());
- if (mSinks.RemoveElement(aSink) && mSinks.IsEmpty()) {
- MOZ_ASSERT(!mStopped);
- Stop();
- mStopped = true;
- }
- }
- protected:
- virtual ~MediaStreamTrackSource()
- {
- MOZ_COUNT_DTOR(MediaStreamTrackSource);
- }
- /**
- * Called by a sub class when the principal has changed.
- * Notifies all sinks.
- */
- void PrincipalChanged()
- {
- for (Sink* sink : mSinks) {
- sink->PrincipalChanged();
- }
- }
- // Principal identifying who may access the contents of this source.
- nsCOMPtr<nsIPrincipal> mPrincipal;
- // Currently registered sinks.
- nsTArray<Sink*> mSinks;
- // The label of the track we are the source of per the MediaStreamTrack spec.
- const nsString mLabel;
- // True if all MediaStreamTrack users have unregistered from this source and
- // Stop() has been called.
- bool mStopped;
- };
- /**
- * Basic implementation of MediaStreamTrackSource that doesn't forward Stop().
- */
- class BasicTrackSource : public MediaStreamTrackSource
- {
- public:
- explicit BasicTrackSource(nsIPrincipal* aPrincipal,
- const MediaSourceEnum aMediaSource =
- MediaSourceEnum::Other)
- : MediaStreamTrackSource(aPrincipal, nsString())
- , mMediaSource(aMediaSource)
- {}
- MediaSourceEnum GetMediaSource() const override { return mMediaSource; }
- void Stop() override {}
- protected:
- ~BasicTrackSource() {}
- const MediaSourceEnum mMediaSource;
- };
- /**
- * Base class that consumers of a MediaStreamTrack can use to get notifications
- * about state changes in the track.
- */
- class MediaStreamTrackConsumer : public nsISupports
- {
- public:
- NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_CLASS(MediaStreamTrackConsumer)
- /**
- * Called when the track's readyState transitions to "ended".
- * Unlike the "ended" event exposed to script this is called for any reason,
- * including MediaStreamTrack::Stop().
- */
- virtual void NotifyEnded(MediaStreamTrack* aTrack) {};
- protected:
- virtual ~MediaStreamTrackConsumer() {}
- };
- /**
- * Class representing a track in a DOMMediaStream.
- */
- class MediaStreamTrack : public DOMEventTargetHelper,
- public MediaStreamTrackSource::Sink
- {
- // DOMMediaStream owns MediaStreamTrack instances, and requires access to
- // some internal state, e.g., GetInputStream(), GetOwnedStream().
- friend class mozilla::DOMMediaStream;
- // PeerConnection and friends need to know our owning DOMStream and track id.
- friend class mozilla::PeerConnectionImpl;
- friend class mozilla::PeerConnectionMedia;
- friend class mozilla::SourceStreamInfo;
- friend class mozilla::RemoteSourceStreamInfo;
- class PrincipalHandleListener;
- public:
- /**
- * aTrackID is the MediaStreamGraph track ID for the track in the
- * MediaStream owned by aStream.
- */
- MediaStreamTrack(DOMMediaStream* aStream, TrackID aTrackID,
- TrackID aInputTrackID,
- MediaStreamTrackSource* aSource,
- const MediaTrackConstraints& aConstraints = MediaTrackConstraints());
- NS_DECL_ISUPPORTS_INHERITED
- NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MediaStreamTrack,
- DOMEventTargetHelper)
- nsPIDOMWindowInner* GetParentObject() const;
- virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override = 0;
- virtual AudioStreamTrack* AsAudioStreamTrack() { return nullptr; }
- virtual VideoStreamTrack* AsVideoStreamTrack() { return nullptr; }
- virtual const AudioStreamTrack* AsAudioStreamTrack() const { return nullptr; }
- virtual const VideoStreamTrack* AsVideoStreamTrack() const { return nullptr; }
- // WebIDL
- virtual void GetKind(nsAString& aKind) = 0;
- void GetId(nsAString& aID) const;
- void GetLabel(nsAString& aLabel) { GetSource().GetLabel(aLabel); }
- bool Enabled() { return mEnabled; }
- void SetEnabled(bool aEnabled);
- void Stop();
- void GetConstraints(dom::MediaTrackConstraints& aResult);
- void GetSettings(dom::MediaTrackSettings& aResult);
- already_AddRefed<Promise>
- ApplyConstraints(const dom::MediaTrackConstraints& aConstraints, ErrorResult &aRv);
- already_AddRefed<MediaStreamTrack> Clone();
- MediaStreamTrackState ReadyState() { return mReadyState; }
- IMPL_EVENT_HANDLER(ended)
- /**
- * Convenience (and legacy) method for when ready state is "ended".
- */
- bool Ended() const { return mReadyState == MediaStreamTrackState::Ended; }
- /**
- * Forces the ready state to a particular value, for instance when we're
- * cloning an already ended track.
- */
- void SetReadyState(MediaStreamTrackState aState);
- /**
- * Notified by the MediaStreamGraph, through our owning MediaStream on the
- * main thread.
- *
- * Note that this sets the track to ended and raises the "ended" event
- * synchronously.
- */
- void OverrideEnded();
- /**
- * Get this track's principal.
- */
- nsIPrincipal* GetPrincipal() const { return mPrincipal; }
- /**
- * Called by the PrincipalHandleListener when this track's PrincipalHandle changes on
- * the MediaStreamGraph thread. When the PrincipalHandle matches the pending
- * principal we know that the principal change has propagated to consumers.
- */
- void NotifyPrincipalHandleChanged(const PrincipalHandle& aPrincipalHandle);
- /**
- * Called when this track's readyState transitions to "ended".
- * Notifies all MediaStreamTrackConsumers that this track ended.
- */
- void NotifyEnded();
- /**
- * Get this track's CORS mode.
- */
- CORSMode GetCORSMode() const { return GetSource().GetCORSMode(); }
- /**
- * Get this track's PeerIdentity.
- */
- const PeerIdentity* GetPeerIdentity() const { return GetSource().GetPeerIdentity(); }
- MediaStreamGraph* Graph();
- MediaStreamGraphImpl* GraphImpl();
- MediaStreamTrackSource& GetSource() const
- {
- MOZ_RELEASE_ASSERT(mSource, "The track source is only removed on destruction");
- return *mSource;
- }
- // Webrtc allows the remote side to name tracks whatever it wants, and we
- // need to surface this to content.
- void AssignId(const nsAString& aID) { mID = aID; }
- // Implementation of MediaStreamTrackSource::Sink
- void PrincipalChanged() override;
- /**
- * Add a PrincipalChangeObserver to this track.
- *
- * 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(PrincipalChangeObserver<MediaStreamTrack>* aObserver);
- /**
- * Remove an added PrincipalChangeObserver from this track.
- *
- * Returns true if it was successfully removed.
- */
- bool RemovePrincipalChangeObserver(PrincipalChangeObserver<MediaStreamTrack>* aObserver);
- /**
- * Add a MediaStreamTrackConsumer to this track.
- *
- * Adding the same consumer multiple times is prohibited.
- */
- void AddConsumer(MediaStreamTrackConsumer* aConsumer);
- /**
- * Remove an added MediaStreamTrackConsumer from this track.
- */
- void RemoveConsumer(MediaStreamTrackConsumer* aConsumer);
- /**
- * Adds a MediaStreamTrackListener to the MediaStreamGraph representation of
- * this track.
- */
- void AddListener(MediaStreamTrackListener* aListener);
- /**
- * Removes a MediaStreamTrackListener from the MediaStreamGraph representation
- * of this track.
- */
- void RemoveListener(MediaStreamTrackListener* aListener);
- /**
- * Attempts to add a direct track listener to this track.
- * Callers must listen to the NotifyInstalled event to know if installing
- * the listener succeeded (tracks originating from SourceMediaStreams) or
- * failed (e.g., WebAudio originated tracks).
- */
- void AddDirectListener(DirectMediaStreamTrackListener *aListener);
- void RemoveDirectListener(DirectMediaStreamTrackListener *aListener);
- /**
- * Sets up a MediaInputPort from the underlying track that this
- * MediaStreamTrack represents, to aStream, and returns it.
- */
- already_AddRefed<MediaInputPort> ForwardTrackContentsTo(ProcessedMediaStream* aStream,
- TrackID aDestinationTrackID = TRACK_ANY);
- /**
- * Returns true if this track is connected to aPort and forwarded to aPort's
- * output stream.
- */
- bool IsForwardedThrough(MediaInputPort* aPort);
- void SetMediaStreamSizeListener(DirectMediaStreamTrackListener* aListener);
- protected:
- virtual ~MediaStreamTrack();
- void Destroy();
- // Returns the original DOMMediaStream's underlying input stream.
- MediaStream* GetInputStream();
- // Returns the owning DOMMediaStream's underlying owned stream.
- ProcessedMediaStream* GetOwnedStream();
- // Returns the original DOMMediaStream. If this track is a clone,
- // the original track's owning DOMMediaStream is returned.
- DOMMediaStream* GetInputDOMStream();
- /**
- * Sets the principal and notifies PrincipalChangeObservers if it changes.
- */
- void SetPrincipal(nsIPrincipal* aPrincipal);
- /**
- * Creates a new MediaStreamTrack with the same type, input track ID and
- * source as this MediaStreamTrack.
- * aTrackID is the TrackID the new track will have in its owned stream.
- */
- virtual already_AddRefed<MediaStreamTrack> CloneInternal(DOMMediaStream* aOwningStream,
- TrackID aTrackID) = 0;
- nsTArray<PrincipalChangeObserver<MediaStreamTrack>*> mPrincipalChangeObservers;
- nsTArray<RefPtr<MediaStreamTrackConsumer>> mConsumers;
- RefPtr<DOMMediaStream> mOwningStream;
- TrackID mTrackID;
- TrackID mInputTrackID;
- RefPtr<MediaStreamTrackSource> mSource;
- RefPtr<MediaStreamTrack> mOriginalTrack;
- nsCOMPtr<nsIPrincipal> mPrincipal;
- nsCOMPtr<nsIPrincipal> mPendingPrincipal;
- RefPtr<PrincipalHandleListener> mPrincipalHandleListener;
- // Keep tracking MediaStreamTrackListener and DirectMediaStreamTrackListener,
- // so we can remove them in |Destory|.
- nsTArray<RefPtr<MediaStreamTrackListener>> mTrackListeners;
- nsTArray<RefPtr<DirectMediaStreamTrackListener>> mDirectTrackListeners;
- nsString mID;
- MediaStreamTrackState mReadyState;
- bool mEnabled;
- dom::MediaTrackConstraints mConstraints;
- };
- } // namespace dom
- } // namespace mozilla
- #endif /* MEDIASTREAMTRACK_H_ */
|