Bug 1941046 - Part 4: Send a callback request for impression and clicks of MARS Top...
[gecko.git] / dom / media / MediaStreamTrack.h
blob7133a84f5b8e8ff40044d8bcfff8af12ad1b44d0
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/. */
6 #ifndef MEDIASTREAMTRACK_H_
7 #define MEDIASTREAMTRACK_H_
9 #include "MediaTrackConstraints.h"
10 #include "PrincipalChangeObserver.h"
11 #include "PrincipalHandle.h"
12 #include "mozilla/DOMEventTargetHelper.h"
13 #include "mozilla/dom/MediaStreamTrackBinding.h"
14 #include "mozilla/dom/MediaTrackCapabilitiesBinding.h"
15 #include "mozilla/dom/MediaTrackSettingsBinding.h"
16 #include "mozilla/media/MediaUtils.h"
17 #include "mozilla/WeakPtr.h"
18 #include "nsError.h"
19 #include "nsID.h"
20 #include "nsIPrincipal.h"
21 #include "PerformanceRecorder.h"
23 namespace mozilla {
25 class DOMMediaStream;
26 class MediaEnginePhotoCallback;
27 class MediaInputPort;
28 class MediaTrack;
29 class MediaTrackGraph;
30 class MediaTrackGraphImpl;
31 class MediaTrackListener;
32 class DirectMediaTrackListener;
33 class PeerConnectionImpl;
34 class PeerIdentity;
35 class ProcessedMediaTrack;
36 class RemoteSourceStreamInfo;
37 class SourceStreamInfo;
38 class MediaMgrError;
40 namespace dom {
42 class AudioStreamTrack;
43 class VideoStreamTrack;
44 class RTCStatsTimestampMaker;
45 enum class CallerType : uint32_t;
47 /**
48 * Common interface through which a MediaStreamTrack can communicate with its
49 * producer on the main thread.
51 * Kept alive by a strong ref in all MediaStreamTracks (original and clones)
52 * sharing this source.
54 class MediaStreamTrackSource : public nsISupports {
55 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
56 NS_DECL_CYCLE_COLLECTION_CLASS(MediaStreamTrackSource)
58 public:
59 class Sink : public SupportsWeakPtr {
60 public:
61 /**
62 * Must be constant throughout the Sink's lifetime.
64 * Return true to keep the MediaStreamTrackSource where this sink is
65 * registered alive.
66 * Return false to allow the source to stop.
68 * Typically MediaStreamTrack::Sink returns true and other Sinks
69 * (like HTMLMediaElement::StreamCaptureTrackSource) return false.
71 virtual bool KeepsSourceAlive() const = 0;
73 /**
74 * Return true to ensure that the MediaStreamTrackSource where this Sink is
75 * registered is kept turned on and active.
76 * Return false to allow the source to pause, and any underlying devices to
77 * temporarily stop.
79 * When the underlying enabled state of the sink changes,
80 * call MediaStreamTrackSource::SinkEnabledStateChanged().
82 * Typically MediaStreamTrack returns the track's enabled state and other
83 * Sinks (like HTMLMediaElement::StreamCaptureTrackSource) return false so
84 * control over device state remains with tracks and their enabled state.
86 virtual bool Enabled() const = 0;
88 /**
89 * Called when the principal of the MediaStreamTrackSource where this sink
90 * is registered has changed.
92 virtual void PrincipalChanged() = 0;
94 /**
95 * Called when the muted state of the MediaStreamTrackSource where this sink
96 * is registered has changed.
98 virtual void MutedChanged(bool aNewState) = 0;
101 * Called when the MediaStreamTrackSource where this sink is registered has
102 * stopped producing data for good, i.e., it has ended.
104 virtual void OverrideEnded() = 0;
106 protected:
107 virtual ~Sink() = default;
110 MediaStreamTrackSource(nsIPrincipal* aPrincipal, const nsString& aLabel,
111 TrackingId aTrackingId)
112 : mPrincipal(aPrincipal),
113 mLabel(aLabel),
114 mTrackingId(std::move(aTrackingId)),
115 mStopped(false) {}
118 * Use to clean up any resources that have to be cleaned before the
119 * destructor is called. It is often too late in the destructor because
120 * of garbage collection having removed the members already.
122 virtual void Destroy() {}
125 * Gets the source's MediaSourceEnum for usage by PeerConnections.
127 virtual MediaSourceEnum GetMediaSource() const = 0;
130 * Get this TrackSource's principal.
132 nsIPrincipal* GetPrincipal() const { return mPrincipal; }
135 * This is used in WebRTC. A peerIdentity constrained MediaStreamTrack cannot
136 * be sent across the network to anything other than a peer with the provided
137 * identity. If this is set, then GetPrincipal() should return an instance of
138 * NullPrincipal.
140 * A track's PeerIdentity is immutable and will not change during the track's
141 * lifetime.
143 virtual const PeerIdentity* GetPeerIdentity() const { return nullptr; }
146 * This is used in WebRTC. The timestampMaker can convert between different
147 * timestamp types used during the session.
149 virtual const RTCStatsTimestampMaker* GetTimestampMaker() const {
150 return nullptr;
154 * MediaStreamTrack::GetLabel (see spec) calls through to here.
156 void GetLabel(nsAString& aLabel) { aLabel.Assign(mLabel); }
159 * Whether this TrackSource provides video frames with an alpha channel. Only
160 * applies to video sources. Used by HTMLVideoElement.
162 virtual bool HasAlpha() const { return false; }
165 * Forwards a photo request to backends that support it. Other backends return
166 * NS_ERROR_NOT_IMPLEMENTED to indicate that a MediaTrackGraph-based fallback
167 * should be used.
169 virtual nsresult TakePhoto(MediaEnginePhotoCallback*) const {
170 return NS_ERROR_NOT_IMPLEMENTED;
173 typedef MozPromise<bool /* aIgnored */, RefPtr<MediaMgrError>, true>
174 ApplyConstraintsPromise;
177 * We provide a fallback solution to ApplyConstraints() here.
178 * Sources that support ApplyConstraints() will have to override it.
180 virtual RefPtr<ApplyConstraintsPromise> ApplyConstraints(
181 const dom::MediaTrackConstraints& aConstraints, CallerType aCallerType);
184 * Same for GetSettings (no-op).
186 virtual void GetSettings(dom::MediaTrackSettings& aResult) {};
188 virtual void GetCapabilities(dom::MediaTrackCapabilities& aResult) {};
191 * Called by the source interface when all registered sinks with
192 * KeepsSourceAlive() == true have unregistered.
194 virtual void Stop() = 0;
197 * Called by the source interface when all registered sinks with
198 * KeepsSourceAlive() == true become disabled.
200 virtual void Disable() = 0;
203 * Called by the source interface when at least one registered sink with
204 * KeepsSourceAlive() == true become enabled.
206 virtual void Enable() = 0;
209 * Called when a Sink's Enabled() state changed. Will iterate through all
210 * sinks and notify the source of the aggregated enabled state.
212 * Note that a Sink with KeepsSourceAlive() == false counts as disabled.
214 void SinkEnabledStateChanged() {
215 if (IsEnabled()) {
216 Enable();
217 } else {
218 Disable();
223 * Called by each MediaStreamTrack clone on initialization.
225 void RegisterSink(Sink* aSink) {
226 MOZ_ASSERT(NS_IsMainThread());
227 if (mStopped) {
228 return;
230 mSinks.AppendElement(aSink);
231 while (mSinks.RemoveElement(nullptr)) {
232 MOZ_ASSERT_UNREACHABLE("Sink was not explicitly removed");
237 * Called by each MediaStreamTrack clone on Stop() if supported by the
238 * source (us) or destruction.
240 void UnregisterSink(Sink* aSink) {
241 MOZ_ASSERT(NS_IsMainThread());
242 while (mSinks.RemoveElement(nullptr)) {
243 MOZ_ASSERT_UNREACHABLE("Sink was not explicitly removed");
245 if (mSinks.RemoveElement(aSink) && !IsActive()) {
246 MOZ_ASSERT(!aSink->KeepsSourceAlive() || !mStopped,
247 "When the last sink keeping the source alive is removed, "
248 "we should still be live");
249 Stop();
250 mStopped = true;
252 if (!mStopped) {
253 SinkEnabledStateChanged();
257 protected:
258 virtual ~MediaStreamTrackSource() = default;
260 bool IsActive() {
261 for (const WeakPtr<Sink>& sink : mSinks) {
262 if (sink && sink->KeepsSourceAlive()) {
263 return true;
266 return false;
269 bool IsEnabled() {
270 for (const WeakPtr<Sink>& sink : mSinks) {
271 if (sink && sink->KeepsSourceAlive() && sink->Enabled()) {
272 return true;
275 return false;
279 * Called by a sub class when the principal has changed.
280 * Notifies all sinks.
282 void PrincipalChanged() {
283 MOZ_ASSERT(NS_IsMainThread());
284 for (auto& sink : mSinks.Clone()) {
285 if (!sink) {
286 DebugOnly<bool> removed = mSinks.RemoveElement(sink);
287 MOZ_ASSERT(!removed, "Sink was not explicitly removed");
288 continue;
290 sink->PrincipalChanged();
295 * Called by a sub class when the source's muted state has changed. Note that
296 * the source is responsible for making the content black/silent during mute.
297 * Notifies all sinks.
299 void MutedChanged(bool aNewState) {
300 MOZ_ASSERT(NS_IsMainThread());
301 for (auto& sink : mSinks.Clone()) {
302 if (!sink) {
303 DebugOnly<bool> removed = mSinks.RemoveElement(sink);
304 MOZ_ASSERT(!removed, "Sink was not explicitly removed");
305 continue;
307 sink->MutedChanged(aNewState);
312 * Called by a sub class when the source has stopped producing data for good,
313 * i.e., it has ended. Notifies all sinks.
315 void OverrideEnded() {
316 MOZ_ASSERT(NS_IsMainThread());
317 for (auto& sink : mSinks.Clone()) {
318 if (!sink) {
319 DebugOnly<bool> removed = mSinks.RemoveElement(sink);
320 MOZ_ASSERT(!removed, "Sink was not explicitly removed");
321 continue;
323 sink->OverrideEnded();
327 // Principal identifying who may access the contents of this source.
328 RefPtr<nsIPrincipal> mPrincipal;
330 // Currently registered sinks.
331 nsTArray<WeakPtr<Sink>> mSinks;
333 public:
334 // The label of the track we are the source of per the MediaStreamTrack spec.
335 const nsString mLabel;
337 // Set for all video sources; an id for tracking the source of the video
338 // frames for this track.
339 const TrackingId mTrackingId;
341 protected:
342 // True if all MediaStreamTrack users have unregistered from this source and
343 // Stop() has been called.
344 bool mStopped;
348 * Base class that consumers of a MediaStreamTrack can use to get notifications
349 * about state changes in the track.
351 class MediaStreamTrackConsumer : public SupportsWeakPtr {
352 public:
354 * Called when the track's readyState transitions to "ended".
355 * Unlike the "ended" event exposed to script this is called for any reason,
356 * including MediaStreamTrack::Stop().
358 virtual void NotifyEnded(MediaStreamTrack* aTrack) {};
361 * Called when the track's enabled state changes.
363 virtual void NotifyEnabledChanged(MediaStreamTrack* aTrack, bool aEnabled) {};
366 // clang-format off
368 * DOM wrapper for MediaTrackGraph-MediaTracks.
370 * To account for cloning, a MediaStreamTrack wraps two internal (and chained)
371 * MediaTracks:
372 * 1. mInputTrack
373 * - Controlled by the producer of the data in the track. The producer
374 * decides on lifetime of the MediaTrack and the track inside it.
375 * - It can be any type of MediaTrack.
376 * - Contains one track only.
377 * 2. mTrack
378 * - A ForwardedInputTrack representing this MediaStreamTrack.
379 * - Its data is piped from mInputTrack through mPort.
380 * - Contains one track only.
381 * - When this MediaStreamTrack is enabled/disabled this is reflected in
382 * the chunks in the track in mTrack.
383 * - When this MediaStreamTrack has ended, mTrack gets destroyed.
384 * Note that mInputTrack is unaffected, such that any clones of mTrack
385 * can live on. When all clones are ended, this is signaled to the
386 * producer via our MediaStreamTrackSource. It is then likely to destroy
387 * mInputTrack.
389 * A graphical representation of how tracks are connected when cloned follows:
391 * MediaStreamTrack A
392 * mInputTrack mTrack
393 * t1 ---------> t1
395 * -----
396 * MediaStreamTrack B \ (clone of A)
397 * mInputTrack \ mTrack
398 * * -> t1
400 * (*) is a copy of A's mInputTrack
402 // clang-format on
403 class MediaStreamTrack : public DOMEventTargetHelper, public SupportsWeakPtr {
404 // PeerConnection and friends need to know our owning DOMStream and track id.
405 friend class mozilla::PeerConnectionImpl;
406 friend class mozilla::SourceStreamInfo;
407 friend class mozilla::RemoteSourceStreamInfo;
409 class MTGListener;
410 class TrackSink;
412 public:
413 MediaStreamTrack(
414 nsPIDOMWindowInner* aWindow, mozilla::MediaTrack* aInputTrack,
415 MediaStreamTrackSource* aSource,
416 MediaStreamTrackState aReadyState = MediaStreamTrackState::Live,
417 bool aMuted = false,
418 const MediaTrackConstraints& aConstraints = MediaTrackConstraints());
420 NS_DECL_ISUPPORTS_INHERITED
421 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MediaStreamTrack,
422 DOMEventTargetHelper)
424 nsPIDOMWindowInner* GetParentObject() const { return mWindow; }
425 JSObject* WrapObject(JSContext* aCx,
426 JS::Handle<JSObject*> aGivenProto) override;
428 virtual AudioStreamTrack* AsAudioStreamTrack() { return nullptr; }
429 virtual VideoStreamTrack* AsVideoStreamTrack() { return nullptr; }
431 virtual const AudioStreamTrack* AsAudioStreamTrack() const { return nullptr; }
432 virtual const VideoStreamTrack* AsVideoStreamTrack() const { return nullptr; }
434 // WebIDL
435 virtual void GetKind(nsAString& aKind) = 0;
436 void GetId(nsAString& aID) const;
437 virtual void GetLabel(nsAString& aLabel, CallerType /* aCallerType */) {
438 GetSource().GetLabel(aLabel);
440 bool Enabled() const { return mEnabled; }
441 void SetEnabled(bool aEnabled);
442 bool Muted() { return mMuted; }
443 void Stop();
444 void GetCapabilities(MediaTrackCapabilities& aResult, CallerType aCallerType);
445 void GetConstraints(dom::MediaTrackConstraints& aResult);
446 void GetSettings(dom::MediaTrackSettings& aResult, CallerType aCallerType);
448 already_AddRefed<Promise> ApplyConstraints(
449 const dom::MediaTrackConstraints& aConstraints, CallerType aCallerType,
450 ErrorResult& aRv);
451 already_AddRefed<MediaStreamTrack> Clone();
452 MediaStreamTrackState ReadyState() { return mReadyState; }
454 IMPL_EVENT_HANDLER(mute)
455 IMPL_EVENT_HANDLER(unmute)
456 IMPL_EVENT_HANDLER(ended)
459 * Convenience (and legacy) method for when ready state is "ended".
461 bool Ended() const { return mReadyState == MediaStreamTrackState::Ended; }
464 * Get this track's principal.
466 nsIPrincipal* GetPrincipal() const { return mPrincipal; }
469 * Get this track's PeerIdentity.
471 const PeerIdentity* GetPeerIdentity() const {
472 return GetSource().GetPeerIdentity();
476 * Get this track's RTCStatsTimestampMaker.
478 const RTCStatsTimestampMaker* GetTimestampMaker() const {
479 return GetSource().GetTimestampMaker();
482 ProcessedMediaTrack* GetTrack() const;
483 MediaTrackGraph* Graph() const;
484 MediaTrackGraphImpl* GraphImpl() const;
486 MediaStreamTrackSource& GetSource() const {
487 MOZ_RELEASE_ASSERT(mSource,
488 "The track source is only removed on destruction");
489 return *mSource;
492 // Webrtc allows the remote side to name tracks whatever it wants, and we
493 // need to surface this to content.
494 void AssignId(const nsAString& aID) { mID = aID; }
497 * Add a PrincipalChangeObserver to this track.
499 * Returns true if it was successfully added.
501 * Ownership of the PrincipalChangeObserver remains with the caller, and it's
502 * the caller's responsibility to remove the observer before it dies.
504 bool AddPrincipalChangeObserver(
505 PrincipalChangeObserver<MediaStreamTrack>* aObserver);
508 * Remove an added PrincipalChangeObserver from this track.
510 * Returns true if it was successfully removed.
512 bool RemovePrincipalChangeObserver(
513 PrincipalChangeObserver<MediaStreamTrack>* aObserver);
516 * Add a MediaStreamTrackConsumer to this track.
518 * Adding the same consumer multiple times is prohibited.
520 void AddConsumer(MediaStreamTrackConsumer* aConsumer);
523 * Remove an added MediaStreamTrackConsumer from this track.
525 void RemoveConsumer(MediaStreamTrackConsumer* aConsumer);
528 * Adds a MediaTrackListener to the MediaTrackGraph representation of
529 * this track.
531 virtual void AddListener(MediaTrackListener* aListener);
534 * Removes a MediaTrackListener from the MediaTrackGraph representation
535 * of this track.
537 void RemoveListener(MediaTrackListener* aListener);
540 * Attempts to add a direct track listener to this track.
541 * Callers must listen to the NotifyInstalled event to know if installing
542 * the listener succeeded (tracks originating from SourceMediaTracks) or
543 * failed (e.g., WebAudio originated tracks).
545 virtual void AddDirectListener(DirectMediaTrackListener* aListener);
546 void RemoveDirectListener(DirectMediaTrackListener* aListener);
549 * Sets up a MediaInputPort from the underlying track that this
550 * MediaStreamTrack represents, to aTrack, and returns it.
552 already_AddRefed<MediaInputPort> ForwardTrackContentsTo(
553 ProcessedMediaTrack* aTrack);
555 protected:
556 virtual ~MediaStreamTrack();
559 * Forces the ready state to a particular value, for instance when we're
560 * cloning an already ended track.
562 void SetReadyState(MediaStreamTrackState aState);
565 * Notified by the MediaTrackGraph, through our owning MediaStream on the
566 * main thread.
568 * Note that this sets the track to ended and raises the "ended" event
569 * synchronously.
571 void OverrideEnded();
574 * Called by the MTGListener when this track's PrincipalHandle changes on
575 * the MediaTrackGraph thread. When the PrincipalHandle matches the pending
576 * principal we know that the principal change has propagated to consumers.
578 void NotifyPrincipalHandleChanged(const PrincipalHandle& aNewPrincipalHandle);
581 * Called when this track's readyState transitions to "ended".
582 * Notifies all MediaStreamTrackConsumers that this track ended.
584 void NotifyEnded();
587 * Called when this track's enabled state has changed.
588 * Notifies all MediaStreamTrackConsumers.
590 void NotifyEnabledChanged();
593 * Called when mSource's principal has changed.
595 void PrincipalChanged();
598 * Called when mSource's muted state has changed.
600 void MutedChanged(bool aNewState);
603 * Sets this track's muted state without raising any events.
604 * Only really set by cloning. See MutedChanged for runtime changes.
606 void SetMuted(bool aMuted) { mMuted = aMuted; }
608 virtual void Destroy();
611 * Sets the principal and notifies PrincipalChangeObservers if it changes.
613 void SetPrincipal(nsIPrincipal* aPrincipal);
616 * Creates a new MediaStreamTrack with the same kind, input track, input
617 * track ID and source as this MediaStreamTrack.
619 virtual already_AddRefed<MediaStreamTrack> CloneInternal() = 0;
621 nsTArray<PrincipalChangeObserver<MediaStreamTrack>*>
622 mPrincipalChangeObservers;
624 nsTArray<WeakPtr<MediaStreamTrackConsumer>> mConsumers;
626 // We need this to track our parent object.
627 nsCOMPtr<nsPIDOMWindowInner> mWindow;
629 // The input MediaTrack assigned us by the data producer.
630 // Owned by the producer.
631 const RefPtr<mozilla::MediaTrack> mInputTrack;
632 // The MediaTrack representing this MediaStreamTrack in the MediaTrackGraph.
633 // Set on construction if we're live. Valid until we end. Owned by us.
634 RefPtr<ProcessedMediaTrack> mTrack;
635 // The MediaInputPort connecting mInputTrack to mTrack. Set on construction
636 // if mInputTrack is non-destroyed and we're live. Valid until we end. Owned
637 // by us.
638 RefPtr<MediaInputPort> mPort;
639 RefPtr<MediaStreamTrackSource> mSource;
640 const UniquePtr<TrackSink> mSink;
641 nsCOMPtr<nsIPrincipal> mPrincipal;
642 nsCOMPtr<nsIPrincipal> mPendingPrincipal;
643 RefPtr<MTGListener> mMTGListener;
644 // Keep tracking MediaTrackListener and DirectMediaTrackListener,
645 // so we can remove them in |Destory|.
646 nsTArray<RefPtr<MediaTrackListener>> mTrackListeners;
647 nsTArray<RefPtr<DirectMediaTrackListener>> mDirectTrackListeners;
648 nsString mID;
649 MediaStreamTrackState mReadyState;
650 bool mEnabled;
651 bool mMuted;
652 dom::MediaTrackConstraints mConstraints;
655 } // namespace dom
656 } // namespace mozilla
658 #endif /* MEDIASTREAMTRACK_H_ */