MediaStreamTrack.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  4. * You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #ifndef MEDIASTREAMTRACK_H_
  6. #define MEDIASTREAMTRACK_H_
  7. #include "mozilla/DOMEventTargetHelper.h"
  8. #include "nsError.h"
  9. #include "nsID.h"
  10. #include "nsIPrincipal.h"
  11. #include "StreamTracks.h"
  12. #include "MediaTrackConstraints.h"
  13. #include "mozilla/CORSMode.h"
  14. #include "PrincipalChangeObserver.h"
  15. #include "mozilla/dom/MediaStreamTrackBinding.h"
  16. #include "mozilla/dom/MediaTrackSettingsBinding.h"
  17. #include "mozilla/media/MediaUtils.h"
  18. namespace mozilla {
  19. class DOMMediaStream;
  20. class MediaEnginePhotoCallback;
  21. class MediaInputPort;
  22. class MediaStream;
  23. class MediaStreamGraph;
  24. class MediaStreamGraphImpl;
  25. class MediaStreamTrackListener;
  26. class DirectMediaStreamTrackListener;
  27. class PeerConnectionImpl;
  28. class PeerConnectionMedia;
  29. class PeerIdentity;
  30. class ProcessedMediaStream;
  31. class RemoteSourceStreamInfo;
  32. class SourceStreamInfo;
  33. namespace dom {
  34. class AudioStreamTrack;
  35. class VideoStreamTrack;
  36. class MediaStreamError;
  37. /**
  38. * Common interface through which a MediaStreamTrack can communicate with its
  39. * producer on the main thread.
  40. *
  41. * Kept alive by a strong ref in all MediaStreamTracks (original and clones)
  42. * sharing this source.
  43. */
  44. class MediaStreamTrackSource : public nsISupports
  45. {
  46. NS_DECL_CYCLE_COLLECTING_ISUPPORTS
  47. NS_DECL_CYCLE_COLLECTION_CLASS(MediaStreamTrackSource)
  48. public:
  49. class Sink
  50. {
  51. public:
  52. virtual void PrincipalChanged() = 0;
  53. };
  54. MediaStreamTrackSource(nsIPrincipal* aPrincipal,
  55. const nsString& aLabel)
  56. : mPrincipal(aPrincipal),
  57. mLabel(aLabel),
  58. mStopped(false)
  59. {
  60. MOZ_COUNT_CTOR(MediaStreamTrackSource);
  61. }
  62. /**
  63. * Use to clean up any resources that have to be cleaned before the
  64. * destructor is called. It is often too late in the destructor because
  65. * of garbage collection having removed the members already.
  66. */
  67. virtual void Destroy() {}
  68. /**
  69. * Gets the source's MediaSourceEnum for usage by PeerConnections.
  70. */
  71. virtual MediaSourceEnum GetMediaSource() const = 0;
  72. /**
  73. * Get this TrackSource's principal.
  74. */
  75. nsIPrincipal* GetPrincipal() const { return mPrincipal; }
  76. /**
  77. * Get the source's current CORSMode. If not applicable CORS_NONE is returned.
  78. * The sink will be notified of changes to our CORSMode through
  79. * PrincipalChanged().
  80. */
  81. virtual CORSMode GetCORSMode() const { return CORS_NONE; }
  82. /**
  83. * This is used in WebRTC. A peerIdentity constrained MediaStreamTrack cannot
  84. * be sent across the network to anything other than a peer with the provided
  85. * identity. If this is set, then GetPrincipal() should return an instance of
  86. * nsNullPrincipal.
  87. *
  88. * A track's PeerIdentity is immutable and will not change during the track's
  89. * lifetime.
  90. */
  91. virtual const PeerIdentity* GetPeerIdentity() const { return nullptr; }
  92. /**
  93. * MediaStreamTrack::GetLabel (see spec) calls through to here.
  94. */
  95. void GetLabel(nsAString& aLabel) { aLabel.Assign(mLabel); }
  96. /**
  97. * Forwards a photo request to backends that support it. Other backends return
  98. * NS_ERROR_NOT_IMPLEMENTED to indicate that a MediaStreamGraph-based fallback
  99. * should be used.
  100. */
  101. virtual nsresult TakePhoto(MediaEnginePhotoCallback*) const { return NS_ERROR_NOT_IMPLEMENTED; }
  102. typedef media::Pledge<bool, dom::MediaStreamError*> PledgeVoid;
  103. /**
  104. * We provide a fallback solution to ApplyConstraints() here.
  105. * Sources that support ApplyConstraints() will have to override it.
  106. */
  107. virtual already_AddRefed<PledgeVoid>
  108. ApplyConstraints(nsPIDOMWindowInner* aWindow,
  109. const dom::MediaTrackConstraints& aConstraints);
  110. /**
  111. * Same for GetSettings (no-op).
  112. */
  113. virtual void
  114. GetSettings(dom::MediaTrackSettings& aResult) {};
  115. /**
  116. * Called by the source interface when all registered sinks have unregistered.
  117. */
  118. virtual void Stop() = 0;
  119. /**
  120. * Called by each MediaStreamTrack clone on initialization.
  121. */
  122. void RegisterSink(Sink* aSink)
  123. {
  124. MOZ_ASSERT(NS_IsMainThread());
  125. if (mStopped) {
  126. return;
  127. }
  128. mSinks.AppendElement(aSink);
  129. }
  130. /**
  131. * Called by each MediaStreamTrack clone on Stop() if supported by the
  132. * source (us) or destruction.
  133. */
  134. void UnregisterSink(Sink* aSink)
  135. {
  136. MOZ_ASSERT(NS_IsMainThread());
  137. if (mSinks.RemoveElement(aSink) && mSinks.IsEmpty()) {
  138. MOZ_ASSERT(!mStopped);
  139. Stop();
  140. mStopped = true;
  141. }
  142. }
  143. protected:
  144. virtual ~MediaStreamTrackSource()
  145. {
  146. MOZ_COUNT_DTOR(MediaStreamTrackSource);
  147. }
  148. /**
  149. * Called by a sub class when the principal has changed.
  150. * Notifies all sinks.
  151. */
  152. void PrincipalChanged()
  153. {
  154. for (Sink* sink : mSinks) {
  155. sink->PrincipalChanged();
  156. }
  157. }
  158. // Principal identifying who may access the contents of this source.
  159. nsCOMPtr<nsIPrincipal> mPrincipal;
  160. // Currently registered sinks.
  161. nsTArray<Sink*> mSinks;
  162. // The label of the track we are the source of per the MediaStreamTrack spec.
  163. const nsString mLabel;
  164. // True if all MediaStreamTrack users have unregistered from this source and
  165. // Stop() has been called.
  166. bool mStopped;
  167. };
  168. /**
  169. * Basic implementation of MediaStreamTrackSource that doesn't forward Stop().
  170. */
  171. class BasicTrackSource : public MediaStreamTrackSource
  172. {
  173. public:
  174. explicit BasicTrackSource(nsIPrincipal* aPrincipal,
  175. const MediaSourceEnum aMediaSource =
  176. MediaSourceEnum::Other)
  177. : MediaStreamTrackSource(aPrincipal, nsString())
  178. , mMediaSource(aMediaSource)
  179. {}
  180. MediaSourceEnum GetMediaSource() const override { return mMediaSource; }
  181. void Stop() override {}
  182. protected:
  183. ~BasicTrackSource() {}
  184. const MediaSourceEnum mMediaSource;
  185. };
  186. /**
  187. * Base class that consumers of a MediaStreamTrack can use to get notifications
  188. * about state changes in the track.
  189. */
  190. class MediaStreamTrackConsumer : public nsISupports
  191. {
  192. public:
  193. NS_DECL_CYCLE_COLLECTING_ISUPPORTS
  194. NS_DECL_CYCLE_COLLECTION_CLASS(MediaStreamTrackConsumer)
  195. /**
  196. * Called when the track's readyState transitions to "ended".
  197. * Unlike the "ended" event exposed to script this is called for any reason,
  198. * including MediaStreamTrack::Stop().
  199. */
  200. virtual void NotifyEnded(MediaStreamTrack* aTrack) {};
  201. protected:
  202. virtual ~MediaStreamTrackConsumer() {}
  203. };
  204. /**
  205. * Class representing a track in a DOMMediaStream.
  206. */
  207. class MediaStreamTrack : public DOMEventTargetHelper,
  208. public MediaStreamTrackSource::Sink
  209. {
  210. // DOMMediaStream owns MediaStreamTrack instances, and requires access to
  211. // some internal state, e.g., GetInputStream(), GetOwnedStream().
  212. friend class mozilla::DOMMediaStream;
  213. // PeerConnection and friends need to know our owning DOMStream and track id.
  214. friend class mozilla::PeerConnectionImpl;
  215. friend class mozilla::PeerConnectionMedia;
  216. friend class mozilla::SourceStreamInfo;
  217. friend class mozilla::RemoteSourceStreamInfo;
  218. class PrincipalHandleListener;
  219. public:
  220. /**
  221. * aTrackID is the MediaStreamGraph track ID for the track in the
  222. * MediaStream owned by aStream.
  223. */
  224. MediaStreamTrack(DOMMediaStream* aStream, TrackID aTrackID,
  225. TrackID aInputTrackID,
  226. MediaStreamTrackSource* aSource,
  227. const MediaTrackConstraints& aConstraints = MediaTrackConstraints());
  228. NS_DECL_ISUPPORTS_INHERITED
  229. NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MediaStreamTrack,
  230. DOMEventTargetHelper)
  231. nsPIDOMWindowInner* GetParentObject() const;
  232. virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override = 0;
  233. virtual AudioStreamTrack* AsAudioStreamTrack() { return nullptr; }
  234. virtual VideoStreamTrack* AsVideoStreamTrack() { return nullptr; }
  235. virtual const AudioStreamTrack* AsAudioStreamTrack() const { return nullptr; }
  236. virtual const VideoStreamTrack* AsVideoStreamTrack() const { return nullptr; }
  237. // WebIDL
  238. virtual void GetKind(nsAString& aKind) = 0;
  239. void GetId(nsAString& aID) const;
  240. void GetLabel(nsAString& aLabel) { GetSource().GetLabel(aLabel); }
  241. bool Enabled() { return mEnabled; }
  242. void SetEnabled(bool aEnabled);
  243. void Stop();
  244. void GetConstraints(dom::MediaTrackConstraints& aResult);
  245. void GetSettings(dom::MediaTrackSettings& aResult);
  246. already_AddRefed<Promise>
  247. ApplyConstraints(const dom::MediaTrackConstraints& aConstraints, ErrorResult &aRv);
  248. already_AddRefed<MediaStreamTrack> Clone();
  249. MediaStreamTrackState ReadyState() { return mReadyState; }
  250. IMPL_EVENT_HANDLER(ended)
  251. /**
  252. * Convenience (and legacy) method for when ready state is "ended".
  253. */
  254. bool Ended() const { return mReadyState == MediaStreamTrackState::Ended; }
  255. /**
  256. * Forces the ready state to a particular value, for instance when we're
  257. * cloning an already ended track.
  258. */
  259. void SetReadyState(MediaStreamTrackState aState);
  260. /**
  261. * Notified by the MediaStreamGraph, through our owning MediaStream on the
  262. * main thread.
  263. *
  264. * Note that this sets the track to ended and raises the "ended" event
  265. * synchronously.
  266. */
  267. void OverrideEnded();
  268. /**
  269. * Get this track's principal.
  270. */
  271. nsIPrincipal* GetPrincipal() const { return mPrincipal; }
  272. /**
  273. * Called by the PrincipalHandleListener when this track's PrincipalHandle changes on
  274. * the MediaStreamGraph thread. When the PrincipalHandle matches the pending
  275. * principal we know that the principal change has propagated to consumers.
  276. */
  277. void NotifyPrincipalHandleChanged(const PrincipalHandle& aPrincipalHandle);
  278. /**
  279. * Called when this track's readyState transitions to "ended".
  280. * Notifies all MediaStreamTrackConsumers that this track ended.
  281. */
  282. void NotifyEnded();
  283. /**
  284. * Get this track's CORS mode.
  285. */
  286. CORSMode GetCORSMode() const { return GetSource().GetCORSMode(); }
  287. /**
  288. * Get this track's PeerIdentity.
  289. */
  290. const PeerIdentity* GetPeerIdentity() const { return GetSource().GetPeerIdentity(); }
  291. MediaStreamGraph* Graph();
  292. MediaStreamGraphImpl* GraphImpl();
  293. MediaStreamTrackSource& GetSource() const
  294. {
  295. MOZ_RELEASE_ASSERT(mSource, "The track source is only removed on destruction");
  296. return *mSource;
  297. }
  298. // Webrtc allows the remote side to name tracks whatever it wants, and we
  299. // need to surface this to content.
  300. void AssignId(const nsAString& aID) { mID = aID; }
  301. // Implementation of MediaStreamTrackSource::Sink
  302. void PrincipalChanged() override;
  303. /**
  304. * Add a PrincipalChangeObserver to this track.
  305. *
  306. * Returns true if it was successfully added.
  307. *
  308. * Ownership of the PrincipalChangeObserver remains with the caller, and it's
  309. * the caller's responsibility to remove the observer before it dies.
  310. */
  311. bool AddPrincipalChangeObserver(PrincipalChangeObserver<MediaStreamTrack>* aObserver);
  312. /**
  313. * Remove an added PrincipalChangeObserver from this track.
  314. *
  315. * Returns true if it was successfully removed.
  316. */
  317. bool RemovePrincipalChangeObserver(PrincipalChangeObserver<MediaStreamTrack>* aObserver);
  318. /**
  319. * Add a MediaStreamTrackConsumer to this track.
  320. *
  321. * Adding the same consumer multiple times is prohibited.
  322. */
  323. void AddConsumer(MediaStreamTrackConsumer* aConsumer);
  324. /**
  325. * Remove an added MediaStreamTrackConsumer from this track.
  326. */
  327. void RemoveConsumer(MediaStreamTrackConsumer* aConsumer);
  328. /**
  329. * Adds a MediaStreamTrackListener to the MediaStreamGraph representation of
  330. * this track.
  331. */
  332. void AddListener(MediaStreamTrackListener* aListener);
  333. /**
  334. * Removes a MediaStreamTrackListener from the MediaStreamGraph representation
  335. * of this track.
  336. */
  337. void RemoveListener(MediaStreamTrackListener* aListener);
  338. /**
  339. * Attempts to add a direct track listener to this track.
  340. * Callers must listen to the NotifyInstalled event to know if installing
  341. * the listener succeeded (tracks originating from SourceMediaStreams) or
  342. * failed (e.g., WebAudio originated tracks).
  343. */
  344. void AddDirectListener(DirectMediaStreamTrackListener *aListener);
  345. void RemoveDirectListener(DirectMediaStreamTrackListener *aListener);
  346. /**
  347. * Sets up a MediaInputPort from the underlying track that this
  348. * MediaStreamTrack represents, to aStream, and returns it.
  349. */
  350. already_AddRefed<MediaInputPort> ForwardTrackContentsTo(ProcessedMediaStream* aStream,
  351. TrackID aDestinationTrackID = TRACK_ANY);
  352. /**
  353. * Returns true if this track is connected to aPort and forwarded to aPort's
  354. * output stream.
  355. */
  356. bool IsForwardedThrough(MediaInputPort* aPort);
  357. void SetMediaStreamSizeListener(DirectMediaStreamTrackListener* aListener);
  358. protected:
  359. virtual ~MediaStreamTrack();
  360. void Destroy();
  361. // Returns the original DOMMediaStream's underlying input stream.
  362. MediaStream* GetInputStream();
  363. // Returns the owning DOMMediaStream's underlying owned stream.
  364. ProcessedMediaStream* GetOwnedStream();
  365. // Returns the original DOMMediaStream. If this track is a clone,
  366. // the original track's owning DOMMediaStream is returned.
  367. DOMMediaStream* GetInputDOMStream();
  368. /**
  369. * Sets the principal and notifies PrincipalChangeObservers if it changes.
  370. */
  371. void SetPrincipal(nsIPrincipal* aPrincipal);
  372. /**
  373. * Creates a new MediaStreamTrack with the same type, input track ID and
  374. * source as this MediaStreamTrack.
  375. * aTrackID is the TrackID the new track will have in its owned stream.
  376. */
  377. virtual already_AddRefed<MediaStreamTrack> CloneInternal(DOMMediaStream* aOwningStream,
  378. TrackID aTrackID) = 0;
  379. nsTArray<PrincipalChangeObserver<MediaStreamTrack>*> mPrincipalChangeObservers;
  380. nsTArray<RefPtr<MediaStreamTrackConsumer>> mConsumers;
  381. RefPtr<DOMMediaStream> mOwningStream;
  382. TrackID mTrackID;
  383. TrackID mInputTrackID;
  384. RefPtr<MediaStreamTrackSource> mSource;
  385. RefPtr<MediaStreamTrack> mOriginalTrack;
  386. nsCOMPtr<nsIPrincipal> mPrincipal;
  387. nsCOMPtr<nsIPrincipal> mPendingPrincipal;
  388. RefPtr<PrincipalHandleListener> mPrincipalHandleListener;
  389. // Keep tracking MediaStreamTrackListener and DirectMediaStreamTrackListener,
  390. // so we can remove them in |Destory|.
  391. nsTArray<RefPtr<MediaStreamTrackListener>> mTrackListeners;
  392. nsTArray<RefPtr<DirectMediaStreamTrackListener>> mDirectTrackListeners;
  393. nsString mID;
  394. MediaStreamTrackState mReadyState;
  395. bool mEnabled;
  396. dom::MediaTrackConstraints mConstraints;
  397. };
  398. } // namespace dom
  399. } // namespace mozilla
  400. #endif /* MEDIASTREAMTRACK_H_ */