summaryrefslogtreecommitdiffstats
path: root/dom/media/MediaTrackListener.h
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/MediaTrackListener.h')
-rw-r--r--dom/media/MediaTrackListener.h184
1 files changed, 184 insertions, 0 deletions
diff --git a/dom/media/MediaTrackListener.h b/dom/media/MediaTrackListener.h
new file mode 100644
index 0000000000..162482f7ef
--- /dev/null
+++ b/dom/media/MediaTrackListener.h
@@ -0,0 +1,184 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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 MOZILLA_MEDIATRACKLISTENER_h_
+#define MOZILLA_MEDIATRACKLISTENER_h_
+
+#include "MediaTrackGraph.h"
+#include "PrincipalHandle.h"
+
+namespace mozilla {
+
+class AudioSegment;
+class MediaTrackGraph;
+class MediaStreamVideoSink;
+class VideoSegment;
+
+/**
+ * This is a base class for media graph thread listener callbacks locked to
+ * specific tracks. Override methods to be notified of audio or video data or
+ * changes in track state.
+ *
+ * All notification methods are called from the media graph thread. Overriders
+ * of these methods are responsible for all synchronization. Beware!
+ * These methods are called without the media graph monitor held, so
+ * reentry into media graph methods is possible, although very much discouraged!
+ * You should do something non-blocking and non-reentrant (e.g. dispatch an
+ * event to some thread) and return.
+ * The listener is not allowed to add/remove any listeners from the parent
+ * track.
+ *
+ * If a listener is attached to a track that has already ended, we guarantee
+ * to call NotifyEnded.
+ */
+class MediaTrackListener {
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaTrackListener)
+
+ public:
+ /**
+ * When a SourceMediaTrack has pulling enabled, and the MediaTrackGraph
+ * control loop is ready to pull, this gets called for each track in the
+ * SourceMediaTrack that is lacking data for the current iteration.
+ * A NotifyPull implementation is allowed to call the SourceMediaTrack
+ * methods that alter track data.
+ *
+ * It is not allowed to make other MediaTrack API calls, including
+ * calls to add or remove MediaTrackListeners. It is not allowed to
+ * block for any length of time.
+ *
+ * aEndOfAppendedData is the duration of the data that has already been
+ * appended to this track, in track time.
+ *
+ * aDesiredTime is the track time we should append data up to. Data
+ * beyond this point will not be played until NotifyPull runs again, so
+ * there's not much point in providing it. Note that if the track is blocked
+ * for some reason, then data before aDesiredTime may not be played
+ * immediately.
+ */
+ virtual void NotifyPull(MediaTrackGraph* aGraph, TrackTime aEndOfAppendedData,
+ TrackTime aDesiredTime) {}
+
+ virtual void NotifyQueuedChanges(MediaTrackGraph* aGraph,
+ TrackTime aTrackOffset,
+ const MediaSegment& aQueuedMedia) {}
+
+ virtual void NotifyPrincipalHandleChanged(
+ MediaTrackGraph* aGraph, const PrincipalHandle& aNewPrincipalHandle) {}
+
+ /**
+ * Notify that the enabled state for the track this listener is attached to
+ * has changed.
+ *
+ * The enabled state here is referring to whether audio should be audible
+ * (enabled) or silent (not enabled); or whether video should be displayed as
+ * is (enabled), or black (not enabled).
+ */
+ virtual void NotifyEnabledStateChanged(MediaTrackGraph* aGraph,
+ bool aEnabled) {}
+
+ /**
+ * Notify that the track output is advancing. aCurrentTrackTime is the number
+ * of samples that has been played out for this track in track time.
+ */
+ virtual void NotifyOutput(MediaTrackGraph* aGraph,
+ TrackTime aCurrentTrackTime) {}
+
+ /**
+ * Notify that this track has been ended and all data has been played out.
+ */
+ virtual void NotifyEnded(MediaTrackGraph* aGraph) {}
+
+ /**
+ * Notify that this track listener has been removed from the graph, either
+ * after shutdown or through MediaTrack::RemoveListener().
+ */
+ virtual void NotifyRemoved(MediaTrackGraph* aGraph) {}
+
+ protected:
+ virtual ~MediaTrackListener() = default;
+};
+
+/**
+ * This is a base class for media graph thread listener direct callbacks from
+ * within AppendToTrack(). It is bound to a certain track and can only be
+ * installed on audio tracks. Once added to a track on any track in the graph,
+ * the graph will try to install it at that track's source of media data.
+ *
+ * This works for ForwardedInputTracks, which will forward the listener to the
+ * track's input track if it exists, or wait for it to be created before
+ * forwarding if it doesn't.
+ * Once it reaches a SourceMediaTrack, it can be successfully installed.
+ * Other types of tracks will fail installation since they are not supported.
+ *
+ * Note that this listener and others for the same track will still get
+ * NotifyQueuedChanges() callbacks from the MTG tread, so you must be careful
+ * to ignore them if this listener was successfully installed.
+ */
+class DirectMediaTrackListener : public MediaTrackListener {
+ friend class SourceMediaTrack;
+ friend class ForwardedInputTrack;
+
+ public:
+ /*
+ * This will be called on any DirectMediaTrackListener added to a
+ * SourceMediaTrack when AppendToTrack() is called for the listener's bound
+ * track, using the thread of the AppendToTrack() caller. The MediaSegment
+ * will be the RawSegment (unresampled) if available in AppendToTrack().
+ * If the track is enabled at the source but has been disabled in one of the
+ * tracks in between the source and where it was originally added, aMedia
+ * will be a disabled version of the one passed to AppendToTrack() as well.
+ * Note that NotifyQueuedTrackChanges() calls will also still occur.
+ */
+ virtual void NotifyRealtimeTrackData(MediaTrackGraph* aGraph,
+ TrackTime aTrackOffset,
+ const MediaSegment& aMedia) {}
+
+ /**
+ * When a direct listener is processed for installation by the
+ * MediaTrackGraph it will be notified with whether the installation was
+ * successful or not. The results of this installation are the following:
+ * TRACK_NOT_SUPPORTED
+ * While looking for the data source of this track, we found a MediaTrack
+ * that is not a SourceMediaTrack or a ForwardedInputTrack.
+ * ALREADY_EXISTS
+ * This DirectMediaTrackListener already exists in the
+ * SourceMediaTrack.
+ * SUCCESS
+ * Installation was successful and this listener will start receiving
+ * NotifyRealtimeData on the next AppendData().
+ */
+ enum class InstallationResult {
+ TRACK_NOT_SUPPORTED,
+ ALREADY_EXISTS,
+ SUCCESS
+ };
+ virtual void NotifyDirectListenerInstalled(InstallationResult aResult) {}
+ virtual void NotifyDirectListenerUninstalled() {}
+
+ protected:
+ virtual ~DirectMediaTrackListener() = default;
+
+ void MirrorAndDisableSegment(AudioSegment& aFrom, AudioSegment& aTo);
+ void MirrorAndDisableSegment(VideoSegment& aFrom, VideoSegment& aTo,
+ DisabledTrackMode aMode);
+ void NotifyRealtimeTrackDataAndApplyTrackDisabling(MediaTrackGraph* aGraph,
+ TrackTime aTrackOffset,
+ MediaSegment& aMedia);
+
+ void IncreaseDisabled(DisabledTrackMode aMode);
+ void DecreaseDisabled(DisabledTrackMode aMode);
+
+ // Matches the number of disabled tracks to which this listener is attached.
+ // The number of tracks are those between the track where the listener was
+ // added and the SourceMediaTrack that is the source of the data reaching
+ // this listener.
+ Atomic<int32_t> mDisabledFreezeCount;
+ Atomic<int32_t> mDisabledBlackCount;
+};
+
+} // namespace mozilla
+
+#endif // MOZILLA_MEDIATRACKLISTENER_h_