|
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 |
|
6 #ifndef MOZILLA_MEDIASTREAMGRAPHIMPL_H_ |
|
7 #define MOZILLA_MEDIASTREAMGRAPHIMPL_H_ |
|
8 |
|
9 #include "MediaStreamGraph.h" |
|
10 |
|
11 #include "mozilla/Monitor.h" |
|
12 #include "mozilla/TimeStamp.h" |
|
13 #include "nsIMemoryReporter.h" |
|
14 #include "nsIThread.h" |
|
15 #include "nsIRunnable.h" |
|
16 #include "Latency.h" |
|
17 #include "mozilla/WeakPtr.h" |
|
18 |
|
19 namespace mozilla { |
|
20 |
|
21 template <typename T> |
|
22 class LinkedList; |
|
23 |
|
24 class AudioMixer; |
|
25 |
|
26 /** |
|
27 * Assume we can run an iteration of the MediaStreamGraph loop in this much time |
|
28 * or less. |
|
29 * We try to run the control loop at this rate. |
|
30 */ |
|
31 static const int MEDIA_GRAPH_TARGET_PERIOD_MS = 10; |
|
32 |
|
33 /** |
|
34 * Assume that we might miss our scheduled wakeup of the MediaStreamGraph by |
|
35 * this much. |
|
36 */ |
|
37 static const int SCHEDULE_SAFETY_MARGIN_MS = 10; |
|
38 |
|
39 /** |
|
40 * Try have this much audio buffered in streams and queued to the hardware. |
|
41 * The maximum delay to the end of the next control loop |
|
42 * is 2*MEDIA_GRAPH_TARGET_PERIOD_MS + SCHEDULE_SAFETY_MARGIN_MS. |
|
43 * There is no point in buffering more audio than this in a stream at any |
|
44 * given time (until we add processing). |
|
45 * This is not optimal yet. |
|
46 */ |
|
47 static const int AUDIO_TARGET_MS = 2*MEDIA_GRAPH_TARGET_PERIOD_MS + |
|
48 SCHEDULE_SAFETY_MARGIN_MS; |
|
49 |
|
50 /** |
|
51 * Try have this much video buffered. Video frames are set |
|
52 * near the end of the iteration of the control loop. The maximum delay |
|
53 * to the setting of the next video frame is 2*MEDIA_GRAPH_TARGET_PERIOD_MS + |
|
54 * SCHEDULE_SAFETY_MARGIN_MS. This is not optimal yet. |
|
55 */ |
|
56 static const int VIDEO_TARGET_MS = 2*MEDIA_GRAPH_TARGET_PERIOD_MS + |
|
57 SCHEDULE_SAFETY_MARGIN_MS; |
|
58 |
|
59 /** |
|
60 * A per-stream update message passed from the media graph thread to the |
|
61 * main thread. |
|
62 */ |
|
63 struct StreamUpdate { |
|
64 int64_t mGraphUpdateIndex; |
|
65 nsRefPtr<MediaStream> mStream; |
|
66 StreamTime mNextMainThreadCurrentTime; |
|
67 bool mNextMainThreadFinished; |
|
68 }; |
|
69 |
|
70 /** |
|
71 * This represents a message passed from the main thread to the graph thread. |
|
72 * A ControlMessage always has a weak reference a particular affected stream. |
|
73 */ |
|
74 class ControlMessage { |
|
75 public: |
|
76 explicit ControlMessage(MediaStream* aStream) : mStream(aStream) |
|
77 { |
|
78 MOZ_COUNT_CTOR(ControlMessage); |
|
79 } |
|
80 // All these run on the graph thread |
|
81 virtual ~ControlMessage() |
|
82 { |
|
83 MOZ_COUNT_DTOR(ControlMessage); |
|
84 } |
|
85 // Do the action of this message on the MediaStreamGraph thread. Any actions |
|
86 // affecting graph processing should take effect at mStateComputedTime. |
|
87 // All stream data for times < mStateComputedTime has already been |
|
88 // computed. |
|
89 virtual void Run() = 0; |
|
90 // When we're shutting down the application, most messages are ignored but |
|
91 // some cleanup messages should still be processed (on the main thread). |
|
92 // This must not add new control messages to the graph. |
|
93 virtual void RunDuringShutdown() {} |
|
94 MediaStream* GetStream() { return mStream; } |
|
95 |
|
96 protected: |
|
97 // We do not hold a reference to mStream. The graph will be holding |
|
98 // a reference to the stream until the Destroy message is processed. The |
|
99 // last message referencing a stream is the Destroy message for that stream. |
|
100 MediaStream* mStream; |
|
101 }; |
|
102 |
|
103 /** |
|
104 * The implementation of a media stream graph. This class is private to this |
|
105 * file. It's not in the anonymous namespace because MediaStream needs to |
|
106 * be able to friend it. |
|
107 * |
|
108 * Currently we have one global instance per process, and one per each |
|
109 * OfflineAudioContext object. |
|
110 */ |
|
111 class MediaStreamGraphImpl : public MediaStreamGraph, |
|
112 public nsIMemoryReporter { |
|
113 public: |
|
114 NS_DECL_ISUPPORTS |
|
115 NS_DECL_NSIMEMORYREPORTER |
|
116 |
|
117 /** |
|
118 * Set aRealtime to true in order to create a MediaStreamGraph which provides |
|
119 * support for real-time audio and video. Set it to false in order to create |
|
120 * a non-realtime instance which just churns through its inputs and produces |
|
121 * output. Those objects currently only support audio, and are used to |
|
122 * implement OfflineAudioContext. They do not support MediaStream inputs. |
|
123 */ |
|
124 explicit MediaStreamGraphImpl(bool aRealtime, TrackRate aSampleRate); |
|
125 |
|
126 /** |
|
127 * Unregisters memory reporting and deletes this instance. This should be |
|
128 * called instead of calling the destructor directly. |
|
129 */ |
|
130 void Destroy(); |
|
131 |
|
132 // Main thread only. |
|
133 /** |
|
134 * This runs every time we need to sync state from the media graph thread |
|
135 * to the main thread while the main thread is not in the middle |
|
136 * of a script. It runs during a "stable state" (per HTML5) or during |
|
137 * an event posted to the main thread. |
|
138 */ |
|
139 void RunInStableState(); |
|
140 /** |
|
141 * Ensure a runnable to run RunInStableState is posted to the appshell to |
|
142 * run at the next stable state (per HTML5). |
|
143 * See EnsureStableStateEventPosted. |
|
144 */ |
|
145 void EnsureRunInStableState(); |
|
146 /** |
|
147 * Called to apply a StreamUpdate to its stream. |
|
148 */ |
|
149 void ApplyStreamUpdate(StreamUpdate* aUpdate); |
|
150 /** |
|
151 * Append a ControlMessage to the message queue. This queue is drained |
|
152 * during RunInStableState; the messages will run on the graph thread. |
|
153 */ |
|
154 void AppendMessage(ControlMessage* aMessage); |
|
155 /** |
|
156 * Make this MediaStreamGraph enter forced-shutdown state. This state |
|
157 * will be noticed by the media graph thread, which will shut down all streams |
|
158 * and other state controlled by the media graph thread. |
|
159 * This is called during application shutdown. |
|
160 */ |
|
161 void ForceShutDown(); |
|
162 /** |
|
163 * Shutdown() this MediaStreamGraph's threads and return when they've shut down. |
|
164 */ |
|
165 void ShutdownThreads(); |
|
166 |
|
167 /** |
|
168 * Called before the thread runs. |
|
169 */ |
|
170 void Init(); |
|
171 // The following methods run on the graph thread (or possibly the main thread if |
|
172 // mLifecycleState > LIFECYCLE_RUNNING) |
|
173 /** |
|
174 * Runs main control loop on the graph thread. Normally a single invocation |
|
175 * of this runs for the entire lifetime of the graph thread. |
|
176 */ |
|
177 void RunThread(); |
|
178 /** |
|
179 * Call this to indicate that another iteration of the control loop is |
|
180 * required on its regular schedule. The monitor must not be held. |
|
181 */ |
|
182 void EnsureNextIteration(); |
|
183 /** |
|
184 * As above, but with the monitor already held. |
|
185 */ |
|
186 void EnsureNextIterationLocked(MonitorAutoLock& aLock); |
|
187 /** |
|
188 * Call this to indicate that another iteration of the control loop is |
|
189 * required immediately. The monitor must already be held. |
|
190 */ |
|
191 void EnsureImmediateWakeUpLocked(MonitorAutoLock& aLock); |
|
192 /** |
|
193 * Ensure there is an event posted to the main thread to run RunInStableState. |
|
194 * mMonitor must be held. |
|
195 * See EnsureRunInStableState |
|
196 */ |
|
197 void EnsureStableStateEventPosted(); |
|
198 /** |
|
199 * Generate messages to the main thread to update it for all state changes. |
|
200 * mMonitor must be held. |
|
201 */ |
|
202 void PrepareUpdatesToMainThreadState(bool aFinalUpdate); |
|
203 /** |
|
204 * Returns false if there is any stream that has finished but not yet finished |
|
205 * playing out. |
|
206 */ |
|
207 bool AllFinishedStreamsNotified(); |
|
208 /** |
|
209 * If we are rendering in non-realtime mode, we don't want to send messages to |
|
210 * the main thread at each iteration for performance reasons. We instead |
|
211 * notify the main thread at the same rate |
|
212 */ |
|
213 bool ShouldUpdateMainThread(); |
|
214 // The following methods are the various stages of RunThread processing. |
|
215 /** |
|
216 * Compute a new current time for the graph and advance all on-graph-thread |
|
217 * state to the new current time. |
|
218 */ |
|
219 void UpdateCurrentTime(); |
|
220 /** |
|
221 * Update the consumption state of aStream to reflect whether its data |
|
222 * is needed or not. |
|
223 */ |
|
224 void UpdateConsumptionState(SourceMediaStream* aStream); |
|
225 /** |
|
226 * Extract any state updates pending in aStream, and apply them. |
|
227 */ |
|
228 void ExtractPendingInput(SourceMediaStream* aStream, |
|
229 GraphTime aDesiredUpToTime, |
|
230 bool* aEnsureNextIteration); |
|
231 /** |
|
232 * Update "have enough data" flags in aStream. |
|
233 */ |
|
234 void UpdateBufferSufficiencyState(SourceMediaStream* aStream); |
|
235 /* |
|
236 * If aStream hasn't already been ordered, push it onto aStack and order |
|
237 * its children. |
|
238 */ |
|
239 void UpdateStreamOrderForStream(mozilla::LinkedList<MediaStream>* aStack, |
|
240 already_AddRefed<MediaStream> aStream); |
|
241 /** |
|
242 * Mark aStream and all its inputs (recursively) as consumed. |
|
243 */ |
|
244 static void MarkConsumed(MediaStream* aStream); |
|
245 /** |
|
246 * Sort mStreams so that every stream not in a cycle is after any streams |
|
247 * it depends on, and every stream in a cycle is marked as being in a cycle. |
|
248 * Also sets mIsConsumed on every stream. |
|
249 */ |
|
250 void UpdateStreamOrder(); |
|
251 /** |
|
252 * Compute the blocking states of streams from mStateComputedTime |
|
253 * until the desired future time aEndBlockingDecisions. |
|
254 * Updates mStateComputedTime and sets MediaStream::mBlocked |
|
255 * for all streams. |
|
256 */ |
|
257 void RecomputeBlocking(GraphTime aEndBlockingDecisions); |
|
258 // The following methods are used to help RecomputeBlocking. |
|
259 /** |
|
260 * If aStream isn't already in aStreams, add it and recursively call |
|
261 * AddBlockingRelatedStreamsToSet on all the streams whose blocking |
|
262 * status could depend on or affect the state of aStream. |
|
263 */ |
|
264 void AddBlockingRelatedStreamsToSet(nsTArray<MediaStream*>* aStreams, |
|
265 MediaStream* aStream); |
|
266 /** |
|
267 * Mark a stream blocked at time aTime. If this results in decisions that need |
|
268 * to be revisited at some point in the future, *aEnd will be reduced to the |
|
269 * first time in the future to recompute those decisions. |
|
270 */ |
|
271 void MarkStreamBlocking(MediaStream* aStream); |
|
272 /** |
|
273 * Recompute blocking for the streams in aStreams for the interval starting at aTime. |
|
274 * If this results in decisions that need to be revisited at some point |
|
275 * in the future, *aEnd will be reduced to the first time in the future to |
|
276 * recompute those decisions. |
|
277 */ |
|
278 void RecomputeBlockingAt(const nsTArray<MediaStream*>& aStreams, |
|
279 GraphTime aTime, GraphTime aEndBlockingDecisions, |
|
280 GraphTime* aEnd); |
|
281 /** |
|
282 * Produce data for all streams >= aStreamIndex for the given time interval. |
|
283 * Advances block by block, each iteration producing data for all streams |
|
284 * for a single block. |
|
285 * This is called whenever we have an AudioNodeStream in the graph. |
|
286 */ |
|
287 void ProduceDataForStreamsBlockByBlock(uint32_t aStreamIndex, |
|
288 TrackRate aSampleRate, |
|
289 GraphTime aFrom, |
|
290 GraphTime aTo); |
|
291 /** |
|
292 * Returns true if aStream will underrun at aTime for its own playback. |
|
293 * aEndBlockingDecisions is when we plan to stop making blocking decisions. |
|
294 * *aEnd will be reduced to the first time in the future to recompute these |
|
295 * decisions. |
|
296 */ |
|
297 bool WillUnderrun(MediaStream* aStream, GraphTime aTime, |
|
298 GraphTime aEndBlockingDecisions, GraphTime* aEnd); |
|
299 /** |
|
300 * Given a graph time aTime, convert it to a stream time taking into |
|
301 * account the time during which aStream is scheduled to be blocked. |
|
302 */ |
|
303 StreamTime GraphTimeToStreamTime(MediaStream* aStream, GraphTime aTime); |
|
304 /** |
|
305 * Given a graph time aTime, convert it to a stream time taking into |
|
306 * account the time during which aStream is scheduled to be blocked, and |
|
307 * when we don't know whether it's blocked or not, we assume it's not blocked. |
|
308 */ |
|
309 StreamTime GraphTimeToStreamTimeOptimistic(MediaStream* aStream, GraphTime aTime); |
|
310 enum { |
|
311 INCLUDE_TRAILING_BLOCKED_INTERVAL = 0x01 |
|
312 }; |
|
313 /** |
|
314 * Given a stream time aTime, convert it to a graph time taking into |
|
315 * account the time during which aStream is scheduled to be blocked. |
|
316 * aTime must be <= mStateComputedTime since blocking decisions |
|
317 * are only known up to that point. |
|
318 * If aTime is exactly at the start of a blocked interval, then the blocked |
|
319 * interval is included in the time returned if and only if |
|
320 * aFlags includes INCLUDE_TRAILING_BLOCKED_INTERVAL. |
|
321 */ |
|
322 GraphTime StreamTimeToGraphTime(MediaStream* aStream, StreamTime aTime, |
|
323 uint32_t aFlags = 0); |
|
324 /** |
|
325 * Get the current audio position of the stream's audio output. |
|
326 */ |
|
327 GraphTime GetAudioPosition(MediaStream* aStream); |
|
328 /** |
|
329 * Call NotifyHaveCurrentData on aStream's listeners. |
|
330 */ |
|
331 void NotifyHasCurrentData(MediaStream* aStream); |
|
332 /** |
|
333 * If aStream needs an audio stream but doesn't have one, create it. |
|
334 * If aStream doesn't need an audio stream but has one, destroy it. |
|
335 */ |
|
336 void CreateOrDestroyAudioStreams(GraphTime aAudioOutputStartTime, |
|
337 MediaStream* aStream); |
|
338 /** |
|
339 * Queue audio (mix of stream audio and silence for blocked intervals) |
|
340 * to the audio output stream. Returns the number of frames played. |
|
341 */ |
|
342 TrackTicks PlayAudio(MediaStream* aStream, GraphTime aFrom, GraphTime aTo); |
|
343 /** |
|
344 * Set the correct current video frame for stream aStream. |
|
345 */ |
|
346 void PlayVideo(MediaStream* aStream); |
|
347 /** |
|
348 * No more data will be forthcoming for aStream. The stream will end |
|
349 * at the current buffer end point. The StreamBuffer's tracks must be |
|
350 * explicitly set to finished by the caller. |
|
351 */ |
|
352 void FinishStream(MediaStream* aStream); |
|
353 /** |
|
354 * Compute how much stream data we would like to buffer for aStream. |
|
355 */ |
|
356 StreamTime GetDesiredBufferEnd(MediaStream* aStream); |
|
357 /** |
|
358 * Returns true when there are no active streams. |
|
359 */ |
|
360 bool IsEmpty() { return mStreams.IsEmpty() && mPortCount == 0; } |
|
361 |
|
362 // For use by control messages, on graph thread only. |
|
363 /** |
|
364 * Identify which graph update index we are currently processing. |
|
365 */ |
|
366 int64_t GetProcessingGraphUpdateIndex() { return mProcessingGraphUpdateIndex; } |
|
367 /** |
|
368 * Add aStream to the graph and initializes its graph-specific state. |
|
369 */ |
|
370 void AddStream(MediaStream* aStream); |
|
371 /** |
|
372 * Remove aStream from the graph. Ensures that pending messages about the |
|
373 * stream back to the main thread are flushed. |
|
374 */ |
|
375 void RemoveStream(MediaStream* aStream); |
|
376 /** |
|
377 * Remove aPort from the graph and release it. |
|
378 */ |
|
379 void DestroyPort(MediaInputPort* aPort); |
|
380 /** |
|
381 * Mark the media stream order as dirty. |
|
382 */ |
|
383 void SetStreamOrderDirty() |
|
384 { |
|
385 mStreamOrderDirty = true; |
|
386 } |
|
387 /** |
|
388 * Pause all AudioStreams being written to by MediaStreams |
|
389 */ |
|
390 void PauseAllAudioOutputs(); |
|
391 /** |
|
392 * Resume all AudioStreams being written to by MediaStreams |
|
393 */ |
|
394 void ResumeAllAudioOutputs(); |
|
395 |
|
396 TrackRate AudioSampleRate() { return mSampleRate; } |
|
397 |
|
398 // Data members |
|
399 |
|
400 /** |
|
401 * Media graph thread. |
|
402 * Readonly after initialization on the main thread. |
|
403 */ |
|
404 nsCOMPtr<nsIThread> mThread; |
|
405 |
|
406 // The following state is managed on the graph thread only, unless |
|
407 // mLifecycleState > LIFECYCLE_RUNNING in which case the graph thread |
|
408 // is not running and this state can be used from the main thread. |
|
409 |
|
410 nsTArray<nsRefPtr<MediaStream> > mStreams; |
|
411 /** |
|
412 * mOldStreams is used as temporary storage for streams when computing the |
|
413 * order in which we compute them. |
|
414 */ |
|
415 nsTArray<nsRefPtr<MediaStream> > mOldStreams; |
|
416 /** |
|
417 * The current graph time for the current iteration of the RunThread control |
|
418 * loop. |
|
419 */ |
|
420 GraphTime mCurrentTime; |
|
421 /** |
|
422 * Blocking decisions and all stream contents have been computed up to this |
|
423 * time. The next batch of updates from the main thread will be processed |
|
424 * at this time. Always >= mCurrentTime. |
|
425 */ |
|
426 GraphTime mStateComputedTime; |
|
427 /** |
|
428 * This is only used for logging. |
|
429 */ |
|
430 TimeStamp mInitialTimeStamp; |
|
431 /** |
|
432 * The real timestamp of the latest run of UpdateCurrentTime. |
|
433 */ |
|
434 TimeStamp mCurrentTimeStamp; |
|
435 /** |
|
436 * Date of the last time we updated the main thread with the graph state. |
|
437 */ |
|
438 TimeStamp mLastMainThreadUpdate; |
|
439 /** |
|
440 * Which update batch we are currently processing. |
|
441 */ |
|
442 int64_t mProcessingGraphUpdateIndex; |
|
443 /** |
|
444 * Number of active MediaInputPorts |
|
445 */ |
|
446 int32_t mPortCount; |
|
447 |
|
448 // mMonitor guards the data below. |
|
449 // MediaStreamGraph normally does its work without holding mMonitor, so it is |
|
450 // not safe to just grab mMonitor from some thread and start monkeying with |
|
451 // the graph. Instead, communicate with the graph thread using provided |
|
452 // mechanisms such as the ControlMessage queue. |
|
453 Monitor mMonitor; |
|
454 |
|
455 // Data guarded by mMonitor (must always be accessed with mMonitor held, |
|
456 // regardless of the value of mLifecycleState. |
|
457 |
|
458 /** |
|
459 * State to copy to main thread |
|
460 */ |
|
461 nsTArray<StreamUpdate> mStreamUpdates; |
|
462 /** |
|
463 * Runnables to run after the next update to main thread state. |
|
464 */ |
|
465 nsTArray<nsCOMPtr<nsIRunnable> > mUpdateRunnables; |
|
466 struct MessageBlock { |
|
467 int64_t mGraphUpdateIndex; |
|
468 nsTArray<nsAutoPtr<ControlMessage> > mMessages; |
|
469 }; |
|
470 /** |
|
471 * A list of batches of messages to process. Each batch is processed |
|
472 * as an atomic unit. |
|
473 */ |
|
474 nsTArray<MessageBlock> mMessageQueue; |
|
475 /** |
|
476 * This enum specifies where this graph is in its lifecycle. This is used |
|
477 * to control shutdown. |
|
478 * Shutdown is tricky because it can happen in two different ways: |
|
479 * 1) Shutdown due to inactivity. RunThread() detects that it has no |
|
480 * pending messages and no streams, and exits. The next RunInStableState() |
|
481 * checks if there are new pending messages from the main thread (true only |
|
482 * if new stream creation raced with shutdown); if there are, it revives |
|
483 * RunThread(), otherwise it commits to shutting down the graph. New stream |
|
484 * creation after this point will create a new graph. An async event is |
|
485 * dispatched to Shutdown() the graph's threads and then delete the graph |
|
486 * object. |
|
487 * 2) Forced shutdown at application shutdown, or completion of a |
|
488 * non-realtime graph. A flag is set, RunThread() detects the flag and |
|
489 * exits, the next RunInStableState() detects the flag, and dispatches the |
|
490 * async event to Shutdown() the graph's threads. However the graph object |
|
491 * is not deleted. New messages for the graph are processed synchronously on |
|
492 * the main thread if necessary. When the last stream is destroyed, the |
|
493 * graph object is deleted. |
|
494 */ |
|
495 enum LifecycleState { |
|
496 // The graph thread hasn't started yet. |
|
497 LIFECYCLE_THREAD_NOT_STARTED, |
|
498 // RunThread() is running normally. |
|
499 LIFECYCLE_RUNNING, |
|
500 // In the following states, the graph thread is not running so |
|
501 // all "graph thread only" state in this class can be used safely |
|
502 // on the main thread. |
|
503 // RunThread() has exited and we're waiting for the next |
|
504 // RunInStableState(), at which point we can clean up the main-thread |
|
505 // side of the graph. |
|
506 LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP, |
|
507 // RunInStableState() posted a ShutdownRunnable, and we're waiting for it |
|
508 // to shut down the graph thread(s). |
|
509 LIFECYCLE_WAITING_FOR_THREAD_SHUTDOWN, |
|
510 // Graph threads have shut down but we're waiting for remaining streams |
|
511 // to be destroyed. Only happens during application shutdown and on |
|
512 // completed non-realtime graphs, since normally we'd only shut down a |
|
513 // realtime graph when it has no streams. |
|
514 LIFECYCLE_WAITING_FOR_STREAM_DESTRUCTION |
|
515 }; |
|
516 LifecycleState mLifecycleState; |
|
517 /** |
|
518 * This enum specifies the wait state of the graph thread. |
|
519 */ |
|
520 enum WaitState { |
|
521 // RunThread() is running normally |
|
522 WAITSTATE_RUNNING, |
|
523 // RunThread() is paused waiting for its next iteration, which will |
|
524 // happen soon |
|
525 WAITSTATE_WAITING_FOR_NEXT_ITERATION, |
|
526 // RunThread() is paused indefinitely waiting for something to change |
|
527 WAITSTATE_WAITING_INDEFINITELY, |
|
528 // Something has signaled RunThread() to wake up immediately, |
|
529 // but it hasn't done so yet |
|
530 WAITSTATE_WAKING_UP |
|
531 }; |
|
532 WaitState mWaitState; |
|
533 /** |
|
534 * The graph should stop processing at or after this time. |
|
535 */ |
|
536 GraphTime mEndTime; |
|
537 |
|
538 /** |
|
539 * Sample rate at which this graph runs. For real time graphs, this is |
|
540 * the rate of the audio mixer. For offline graphs, this is the rate specified |
|
541 * at construction. |
|
542 */ |
|
543 TrackRate mSampleRate; |
|
544 /** |
|
545 * True when another iteration of the control loop is required. |
|
546 */ |
|
547 bool mNeedAnotherIteration; |
|
548 /** |
|
549 * True when we need to do a forced shutdown during application shutdown. |
|
550 */ |
|
551 bool mForceShutDown; |
|
552 /** |
|
553 * True when we have posted an event to the main thread to run |
|
554 * RunInStableState() and the event hasn't run yet. |
|
555 */ |
|
556 bool mPostedRunInStableStateEvent; |
|
557 |
|
558 // Main thread only |
|
559 |
|
560 /** |
|
561 * Messages posted by the current event loop task. These are forwarded to |
|
562 * the media graph thread during RunInStableState. We can't forward them |
|
563 * immediately because we want all messages between stable states to be |
|
564 * processed as an atomic batch. |
|
565 */ |
|
566 nsTArray<nsAutoPtr<ControlMessage> > mCurrentTaskMessageQueue; |
|
567 /** |
|
568 * True when RunInStableState has determined that mLifecycleState is > |
|
569 * LIFECYCLE_RUNNING. Since only the main thread can reset mLifecycleState to |
|
570 * LIFECYCLE_RUNNING, this can be relied on to not change unexpectedly. |
|
571 */ |
|
572 bool mDetectedNotRunning; |
|
573 /** |
|
574 * True when a stable state runner has been posted to the appshell to run |
|
575 * RunInStableState at the next stable state. |
|
576 */ |
|
577 bool mPostedRunInStableState; |
|
578 /** |
|
579 * True when processing real-time audio/video. False when processing non-realtime |
|
580 * audio. |
|
581 */ |
|
582 bool mRealtime; |
|
583 /** |
|
584 * True when a non-realtime MediaStreamGraph has started to process input. This |
|
585 * value is only accessed on the main thread. |
|
586 */ |
|
587 bool mNonRealtimeProcessing; |
|
588 /** |
|
589 * True when a change has happened which requires us to recompute the stream |
|
590 * blocking order. |
|
591 */ |
|
592 bool mStreamOrderDirty; |
|
593 /** |
|
594 * Hold a ref to the Latency logger |
|
595 */ |
|
596 nsRefPtr<AsyncLatencyLogger> mLatencyLog; |
|
597 /** |
|
598 * If this is not null, all the audio output for the MSG will be mixed down. |
|
599 */ |
|
600 nsAutoPtr<AudioMixer> mMixer; |
|
601 |
|
602 private: |
|
603 virtual ~MediaStreamGraphImpl(); |
|
604 |
|
605 MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf) |
|
606 |
|
607 /** |
|
608 * Used to signal that a memory report has been requested. |
|
609 */ |
|
610 Monitor mMemoryReportMonitor; |
|
611 /** |
|
612 * This class uses manual memory management, and all pointers to it are raw |
|
613 * pointers. However, in order for it to implement nsIMemoryReporter, it needs |
|
614 * to implement nsISupports and so be ref-counted. So it maintains a single |
|
615 * nsRefPtr to itself, giving it a ref-count of 1 during its entire lifetime, |
|
616 * and Destroy() nulls this self-reference in order to trigger self-deletion. |
|
617 */ |
|
618 nsRefPtr<MediaStreamGraphImpl> mSelfRef; |
|
619 /** |
|
620 * Used to pass memory report information across threads. |
|
621 */ |
|
622 nsTArray<AudioNodeSizes> mAudioStreamSizes; |
|
623 /** |
|
624 * Indicates that the MSG thread should gather data for a memory report. |
|
625 */ |
|
626 bool mNeedsMemoryReport; |
|
627 |
|
628 #ifdef DEBUG |
|
629 /** |
|
630 * Used to assert when AppendMessage() runs ControlMessages synchronously. |
|
631 */ |
|
632 bool mCanRunMessagesSynchronously; |
|
633 #endif |
|
634 |
|
635 }; |
|
636 |
|
637 } |
|
638 |
|
639 #endif /* MEDIASTREAMGRAPHIMPL_H_ */ |