Line data Source code
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_MEDIASTREAMLISTENER_h_
8 : #define MOZILLA_MEDIASTREAMLISTENER_h_
9 :
10 : #include "StreamTracks.h"
11 :
12 : #include "MediaStreamGraph.h"
13 :
14 : namespace mozilla {
15 :
16 : class AudioSegment;
17 : class MediaStream;
18 : class MediaStreamGraph;
19 : class MediaStreamVideoSink;
20 : class VideoSegment;
21 :
22 : /**
23 : * This is a base class for media graph thread listener callbacks.
24 : * Override methods to be notified of audio or video data or changes in stream
25 : * state.
26 : *
27 : * This can be used by stream recorders or network connections that receive
28 : * stream input. It could also be used for debugging.
29 : *
30 : * All notification methods are called from the media graph thread. Overriders
31 : * of these methods are responsible for all synchronization. Beware!
32 : * These methods are called without the media graph monitor held, so
33 : * reentry into media graph methods is possible, although very much discouraged!
34 : * You should do something non-blocking and non-reentrant (e.g. dispatch an
35 : * event to some thread) and return.
36 : * The listener is not allowed to add/remove any listeners from the stream.
37 : *
38 : * When a listener is first attached, we guarantee to send a NotifyBlockingChanged
39 : * callback to notify of the initial blocking state. Also, if a listener is
40 : * attached to a stream that has already finished, we'll call NotifyFinished.
41 : */
42 0 : class MediaStreamListener {
43 : protected:
44 : // Protected destructor, to discourage deletion outside of Release():
45 0 : virtual ~MediaStreamListener() {}
46 :
47 : public:
48 0 : NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaStreamListener)
49 :
50 : /**
51 : * When a SourceMediaStream has pulling enabled, and the MediaStreamGraph
52 : * control loop is ready to pull, this gets called. A NotifyPull implementation
53 : * is allowed to call the SourceMediaStream methods that alter track
54 : * data. It is not allowed to make other MediaStream API calls, including
55 : * calls to add or remove MediaStreamListeners. It is not allowed to block
56 : * for any length of time.
57 : * aDesiredTime is the stream time we would like to get data up to. Data
58 : * beyond this point will not be played until NotifyPull runs again, so there's
59 : * not much point in providing it. Note that if the stream is blocked for
60 : * some reason, then data before aDesiredTime may not be played immediately.
61 : */
62 0 : virtual void NotifyPull(MediaStreamGraph* aGraph, StreamTime aDesiredTime) {}
63 :
64 : enum Blocking {
65 : BLOCKED,
66 : UNBLOCKED
67 : };
68 : /**
69 : * Notify that the blocking status of the stream changed. The initial state
70 : * is assumed to be BLOCKED.
71 : */
72 0 : virtual void NotifyBlockingChanged(MediaStreamGraph* aGraph, Blocking aBlocked) {}
73 :
74 : /**
75 : * Notify that the stream has data in each track
76 : * for the stream's current time. Once this state becomes true, it will
77 : * always be true since we block stream time from progressing to times where
78 : * there isn't data in each track.
79 : */
80 0 : virtual void NotifyHasCurrentData(MediaStreamGraph* aGraph) {}
81 :
82 : /**
83 : * Notify that the stream output is advancing. aCurrentTime is the graph's
84 : * current time. MediaStream::GraphTimeToStreamTime can be used to get the
85 : * stream time.
86 : */
87 0 : virtual void NotifyOutput(MediaStreamGraph* aGraph, GraphTime aCurrentTime) {}
88 :
89 : /**
90 : * Notify that an event has occurred on the Stream
91 : */
92 0 : virtual void NotifyEvent(MediaStreamGraph* aGraph, MediaStreamGraphEvent aEvent) {}
93 :
94 : /**
95 : * Notify that changes to one of the stream tracks have been queued.
96 : * aTrackEvents can be any combination of TRACK_EVENT_CREATED and
97 : * TRACK_EVENT_ENDED. aQueuedMedia is the data being added to the track
98 : * at aTrackOffset (relative to the start of the stream).
99 : * aInputStream and aInputTrackID will be set if the changes originated
100 : * from an input stream's track. In practice they will only be used for
101 : * ProcessedMediaStreams.
102 : */
103 0 : virtual void NotifyQueuedTrackChanges(MediaStreamGraph* aGraph, TrackID aID,
104 : StreamTime aTrackOffset,
105 : TrackEventCommand aTrackEvents,
106 : const MediaSegment& aQueuedMedia,
107 : MediaStream* aInputStream = nullptr,
108 0 : TrackID aInputTrackID = TRACK_INVALID) {}
109 :
110 : /**
111 : * Notify queued audio data. Only audio data need to be queued. The video data
112 : * will be notified by MediaStreamVideoSink::SetCurrentFrame.
113 : */
114 0 : virtual void NotifyQueuedAudioData(MediaStreamGraph* aGraph, TrackID aID,
115 : StreamTime aTrackOffset,
116 : const AudioSegment& aQueuedMedia,
117 : MediaStream* aInputStream = nullptr,
118 0 : TrackID aInputTrackID = TRACK_INVALID) {}
119 :
120 : /**
121 : * Notify that all new tracks this iteration have been created.
122 : * This is to ensure that tracks added atomically to MediaStreamGraph
123 : * are also notified of atomically to MediaStreamListeners.
124 : */
125 0 : virtual void NotifyFinishedTrackCreation(MediaStreamGraph* aGraph) {}
126 : };
127 :
128 : /**
129 : * This is a base class for media graph thread listener callbacks locked to
130 : * specific tracks. Override methods to be notified of audio or video data or
131 : * changes in track state.
132 : *
133 : * All notification methods are called from the media graph thread. Overriders
134 : * of these methods are responsible for all synchronization. Beware!
135 : * These methods are called without the media graph monitor held, so
136 : * reentry into media graph methods is possible, although very much discouraged!
137 : * You should do something non-blocking and non-reentrant (e.g. dispatch an
138 : * event to some thread) and return.
139 : * The listener is not allowed to add/remove any listeners from the parent
140 : * stream.
141 : *
142 : * If a listener is attached to a track that has already ended, we guarantee
143 : * to call NotifyEnded.
144 : */
145 0 : class MediaStreamTrackListener
146 : {
147 0 : NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaStreamTrackListener)
148 :
149 : public:
150 0 : virtual void NotifyQueuedChanges(MediaStreamGraph* aGraph,
151 : StreamTime aTrackOffset,
152 0 : const MediaSegment& aQueuedMedia) {}
153 :
154 0 : virtual void NotifyPrincipalHandleChanged(MediaStreamGraph* aGraph,
155 0 : const PrincipalHandle& aNewPrincipalHandle) {}
156 :
157 0 : virtual void NotifyEnded() {}
158 :
159 0 : virtual void NotifyRemoved() {}
160 :
161 : protected:
162 0 : virtual ~MediaStreamTrackListener() {}
163 : };
164 :
165 :
166 : /**
167 : * This is a base class for media graph thread listener direct callbacks
168 : * from within AppendToTrack(). Note that your regular listener will
169 : * still get NotifyQueuedTrackChanges() callbacks from the MSG thread, so
170 : * you must be careful to ignore them if AddDirectListener was successful.
171 : */
172 0 : class DirectMediaStreamListener : public MediaStreamListener
173 : {
174 : public:
175 0 : virtual ~DirectMediaStreamListener() {}
176 :
177 : /*
178 : * This will be called on any DirectMediaStreamListener added to a
179 : * a SourceMediaStream when AppendToTrack() is called. The MediaSegment
180 : * will be the RawSegment (unresampled) if available in AppendToTrack().
181 : * Note that NotifyQueuedTrackChanges() calls will also still occur.
182 : */
183 0 : virtual void NotifyRealtimeData(MediaStreamGraph* aGraph, TrackID aID,
184 : StreamTime aTrackOffset,
185 : uint32_t aTrackEvents,
186 0 : const MediaSegment& aMedia) {}
187 : };
188 :
189 : /**
190 : * This is a base class for media graph thread listener direct callbacks from
191 : * within AppendToTrack(). It is bound to a certain track and can only be
192 : * installed on audio tracks. Once added to a track on any stream in the graph,
193 : * the graph will try to install it at that track's source of media data.
194 : *
195 : * This works for TrackUnionStreams, which will forward the listener to the
196 : * track's input track if it exists, or wait for it to be created before
197 : * forwarding if it doesn't.
198 : * Once it reaches a SourceMediaStream, it can be successfully installed.
199 : * Other types of streams will fail installation since they are not supported.
200 : *
201 : * Note that this listener and others for the same track will still get
202 : * NotifyQueuedChanges() callbacks from the MSG tread, so you must be careful
203 : * to ignore them if this listener was successfully installed.
204 : */
205 0 : class DirectMediaStreamTrackListener : public MediaStreamTrackListener
206 : {
207 : friend class SourceMediaStream;
208 : friend class TrackUnionStream;
209 :
210 : public:
211 : /*
212 : * This will be called on any DirectMediaStreamTrackListener added to a
213 : * SourceMediaStream when AppendToTrack() is called for the listener's bound
214 : * track, using the thread of the AppendToTrack() caller. The MediaSegment
215 : * will be the RawSegment (unresampled) if available in AppendToTrack().
216 : * If the track is enabled at the source but has been disabled in one of the
217 : * streams in between the source and where it was originally added, aMedia
218 : * will be a disabled version of the one passed to AppendToTrack() as well.
219 : * Note that NotifyQueuedTrackChanges() calls will also still occur.
220 : */
221 0 : virtual void NotifyRealtimeTrackData(MediaStreamGraph* aGraph,
222 : StreamTime aTrackOffset,
223 0 : const MediaSegment& aMedia) {}
224 :
225 : /**
226 : * When a direct listener is processed for installation by the
227 : * MediaStreamGraph it will be notified with whether the installation was
228 : * successful or not. The results of this installation are the following:
229 : * TRACK_NOT_FOUND_AT_SOURCE
230 : * We found the source stream of media data for this track, but the track
231 : * didn't exist. This should only happen if you try to install the listener
232 : * directly to a SourceMediaStream that doesn't contain the given TrackID.
233 : * STREAM_NOT_SUPPORTED
234 : * While looking for the data source of this track, we found a MediaStream
235 : * that is not a SourceMediaStream or a TrackUnionStream.
236 : * ALREADY_EXIST
237 : * This DirectMediaStreamTrackListener already exists in the
238 : * SourceMediaStream.
239 : * SUCCESS
240 : * Installation was successful and this listener will start receiving
241 : * NotifyRealtimeData on the next AppendToTrack().
242 : */
243 : enum class InstallationResult {
244 : TRACK_NOT_FOUND_AT_SOURCE,
245 : TRACK_TYPE_NOT_SUPPORTED,
246 : STREAM_NOT_SUPPORTED,
247 : ALREADY_EXISTS,
248 : SUCCESS
249 : };
250 0 : virtual void NotifyDirectListenerInstalled(InstallationResult aResult) {}
251 0 : virtual void NotifyDirectListenerUninstalled() {}
252 :
253 0 : virtual MediaStreamVideoSink* AsMediaStreamVideoSink() { return nullptr; }
254 :
255 : protected:
256 0 : virtual ~DirectMediaStreamTrackListener() {}
257 :
258 : void MirrorAndDisableSegment(AudioSegment& aFrom, AudioSegment& aTo);
259 : void MirrorAndDisableSegment(VideoSegment& aFrom,
260 : VideoSegment& aTo,
261 : DisabledTrackMode aMode);
262 : void NotifyRealtimeTrackDataAndApplyTrackDisabling(MediaStreamGraph* aGraph,
263 : StreamTime aTrackOffset,
264 : MediaSegment& aMedia);
265 :
266 : void IncreaseDisabled(DisabledTrackMode aMode);
267 : void DecreaseDisabled(DisabledTrackMode aMode);
268 :
269 : // Matches the number of disabled streams to which this listener is attached.
270 : // The number of streams are those between the stream the listener was added
271 : // and the SourceMediaStream that is the input of the data.
272 : Atomic<int32_t> mDisabledFreezeCount;
273 : Atomic<int32_t> mDisabledBlackCount;
274 :
275 : nsAutoPtr<MediaSegment> mMedia;
276 : };
277 :
278 : } // namespace mozilla
279 :
280 : #endif // MOZILLA_MEDIASTREAMLISTENER_h_
|