MediaTrackListener.h (7681B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef MOZILLA_MEDIATRACKLISTENER_h_ 8 #define MOZILLA_MEDIATRACKLISTENER_h_ 9 10 #include "MediaTrackGraph.h" 11 #include "PrincipalHandle.h" 12 13 namespace mozilla { 14 15 class AudioSegment; 16 class MediaTrackGraph; 17 class MediaStreamVideoSink; 18 class VideoSegment; 19 20 /** 21 * This is a base class for media graph thread listener callbacks locked to 22 * specific tracks. Override methods to be notified of audio or video data or 23 * changes in track state. 24 * 25 * All notification methods are called from the media graph thread. Overriders 26 * of these methods are responsible for all synchronization. Beware! 27 * These methods are called without the media graph monitor held, so 28 * reentry into media graph methods is possible, although very much discouraged! 29 * You should do something non-blocking and non-reentrant (e.g. dispatch an 30 * event to some thread) and return. 31 * The listener is not allowed to add/remove any listeners from the parent 32 * track. 33 * 34 * If a listener is attached to a track that has already ended, we guarantee 35 * to call NotifyEnded. 36 */ 37 class MediaTrackListener { 38 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaTrackListener) 39 40 public: 41 /** 42 * When a SourceMediaTrack has pulling enabled, and the MediaTrackGraph 43 * control loop is ready to pull, this gets called for each track in the 44 * SourceMediaTrack that is lacking data for the current iteration. 45 * A NotifyPull implementation is allowed to call the SourceMediaTrack 46 * methods that alter track data. 47 * 48 * It is not allowed to make other MediaTrack API calls, including 49 * calls to add or remove MediaTrackListeners. It is not allowed to 50 * block for any length of time. 51 * 52 * aEndOfAppendedData is the duration of the data that has already been 53 * appended to this track, in track time. 54 * 55 * aDesiredTime is the track time we should append data up to. Data 56 * beyond this point will not be played until NotifyPull runs again, so 57 * there's not much point in providing it. Note that if the track is blocked 58 * for some reason, then data before aDesiredTime may not be played 59 * immediately. 60 */ 61 virtual void NotifyPull(MediaTrackGraph* aGraph, TrackTime aEndOfAppendedData, 62 TrackTime aDesiredTime) {} 63 64 virtual void NotifyQueuedChanges(MediaTrackGraph* aGraph, 65 TrackTime aTrackOffset, 66 const MediaSegment& aQueuedMedia) {} 67 68 virtual void NotifyPrincipalHandleChanged( 69 MediaTrackGraph* aGraph, const PrincipalHandle& aNewPrincipalHandle) {} 70 71 /** 72 * Notify that the enabled state for the track this listener is attached to 73 * has changed. 74 * 75 * The enabled state here is referring to whether audio should be audible 76 * (enabled) or silent (not enabled); or whether video should be displayed as 77 * is (enabled), or black (not enabled). 78 */ 79 virtual void NotifyEnabledStateChanged(MediaTrackGraph* aGraph, 80 bool aEnabled) {} 81 82 /** 83 * Notify that the track output is advancing. aCurrentTrackTime is the number 84 * of samples that has been played out for this track in track time. 85 */ 86 virtual void NotifyOutput(MediaTrackGraph* aGraph, 87 TrackTime aCurrentTrackTime) {} 88 89 /** 90 * Notify that this track has been ended and all data has been played out. 91 */ 92 virtual void NotifyEnded(MediaTrackGraph* aGraph) {} 93 94 /** 95 * Notify that this track listener has been removed from the graph, either 96 * after shutdown or through MediaTrack::RemoveListener(). 97 */ 98 virtual void NotifyRemoved(MediaTrackGraph* aGraph) {} 99 100 protected: 101 virtual ~MediaTrackListener() = default; 102 }; 103 104 /** 105 * This is a base class for media graph thread listener direct callbacks from 106 * within AppendToTrack(). It is bound to a certain track and can only be 107 * installed on audio tracks. Once added to a track on any track in the graph, 108 * the graph will try to install it at that track's source of media data. 109 * 110 * This works for ForwardedInputTracks, which will forward the listener to the 111 * track's input track if it exists, or wait for it to be created before 112 * forwarding if it doesn't. 113 * Once it reaches a SourceMediaTrack, it can be successfully installed. 114 * Other types of tracks will fail installation since they are not supported. 115 * 116 * Note that this listener and others for the same track will still get 117 * NotifyQueuedChanges() callbacks from the MTG tread, so you must be careful 118 * to ignore them if this listener was successfully installed. 119 */ 120 class DirectMediaTrackListener : public MediaTrackListener { 121 friend class SourceMediaTrack; 122 friend class ForwardedInputTrack; 123 124 public: 125 /* 126 * This will be called on any DirectMediaTrackListener added to a 127 * SourceMediaTrack when AppendToTrack() is called for the listener's bound 128 * track, using the thread of the AppendToTrack() caller. The MediaSegment 129 * will be the RawSegment (unresampled) if available in AppendToTrack(). 130 * If the track is enabled at the source but has been disabled in one of the 131 * tracks in between the source and where it was originally added, aMedia 132 * will be a disabled version of the one passed to AppendToTrack() as well. 133 * Note that NotifyQueuedTrackChanges() calls will also still occur. 134 */ 135 virtual void NotifyRealtimeTrackData(MediaTrackGraph* aGraph, 136 TrackTime aTrackOffset, 137 const MediaSegment& aMedia) {} 138 139 /** 140 * When a direct listener is processed for installation by the 141 * MediaTrackGraph it will be notified with whether the installation was 142 * successful or not. The results of this installation are the following: 143 * TRACK_NOT_SUPPORTED 144 * While looking for the data source of this track, we found a MediaTrack 145 * that is not a SourceMediaTrack or a ForwardedInputTrack. 146 * ALREADY_EXISTS 147 * This DirectMediaTrackListener already exists in the 148 * SourceMediaTrack. 149 * SUCCESS 150 * Installation was successful and this listener will start receiving 151 * NotifyRealtimeData on the next AppendData(). 152 */ 153 enum class InstallationResult { 154 TRACK_NOT_SUPPORTED, 155 ALREADY_EXISTS, 156 SUCCESS 157 }; 158 virtual void NotifyDirectListenerInstalled(InstallationResult aResult) {} 159 virtual void NotifyDirectListenerUninstalled() {} 160 161 protected: 162 virtual ~DirectMediaTrackListener() = default; 163 164 void MirrorAndDisableSegment(AudioSegment& aFrom, AudioSegment& aTo); 165 void MirrorAndDisableSegment(VideoSegment& aFrom, VideoSegment& aTo, 166 DisabledTrackMode aMode); 167 void NotifyRealtimeTrackDataAndApplyTrackDisabling(MediaTrackGraph* aGraph, 168 TrackTime aTrackOffset, 169 MediaSegment& aMedia); 170 171 void IncreaseDisabled(DisabledTrackMode aMode); 172 void DecreaseDisabled(DisabledTrackMode aMode); 173 174 // Matches the number of disabled tracks to which this listener is attached. 175 // The number of tracks are those between the track where the listener was 176 // added and the SourceMediaTrack that is the source of the data reaching 177 // this listener. 178 Atomic<int32_t> mDisabledFreezeCount; 179 Atomic<int32_t> mDisabledBlackCount; 180 }; 181 182 } // namespace mozilla 183 184 #endif // MOZILLA_MEDIATRACKLISTENER_h_