1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/media/MediaStreamGraphImpl.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,639 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.7 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef MOZILLA_MEDIASTREAMGRAPHIMPL_H_ 1.10 +#define MOZILLA_MEDIASTREAMGRAPHIMPL_H_ 1.11 + 1.12 +#include "MediaStreamGraph.h" 1.13 + 1.14 +#include "mozilla/Monitor.h" 1.15 +#include "mozilla/TimeStamp.h" 1.16 +#include "nsIMemoryReporter.h" 1.17 +#include "nsIThread.h" 1.18 +#include "nsIRunnable.h" 1.19 +#include "Latency.h" 1.20 +#include "mozilla/WeakPtr.h" 1.21 + 1.22 +namespace mozilla { 1.23 + 1.24 +template <typename T> 1.25 +class LinkedList; 1.26 + 1.27 +class AudioMixer; 1.28 + 1.29 +/** 1.30 + * Assume we can run an iteration of the MediaStreamGraph loop in this much time 1.31 + * or less. 1.32 + * We try to run the control loop at this rate. 1.33 + */ 1.34 +static const int MEDIA_GRAPH_TARGET_PERIOD_MS = 10; 1.35 + 1.36 +/** 1.37 + * Assume that we might miss our scheduled wakeup of the MediaStreamGraph by 1.38 + * this much. 1.39 + */ 1.40 +static const int SCHEDULE_SAFETY_MARGIN_MS = 10; 1.41 + 1.42 +/** 1.43 + * Try have this much audio buffered in streams and queued to the hardware. 1.44 + * The maximum delay to the end of the next control loop 1.45 + * is 2*MEDIA_GRAPH_TARGET_PERIOD_MS + SCHEDULE_SAFETY_MARGIN_MS. 1.46 + * There is no point in buffering more audio than this in a stream at any 1.47 + * given time (until we add processing). 1.48 + * This is not optimal yet. 1.49 + */ 1.50 +static const int AUDIO_TARGET_MS = 2*MEDIA_GRAPH_TARGET_PERIOD_MS + 1.51 + SCHEDULE_SAFETY_MARGIN_MS; 1.52 + 1.53 +/** 1.54 + * Try have this much video buffered. Video frames are set 1.55 + * near the end of the iteration of the control loop. The maximum delay 1.56 + * to the setting of the next video frame is 2*MEDIA_GRAPH_TARGET_PERIOD_MS + 1.57 + * SCHEDULE_SAFETY_MARGIN_MS. This is not optimal yet. 1.58 + */ 1.59 +static const int VIDEO_TARGET_MS = 2*MEDIA_GRAPH_TARGET_PERIOD_MS + 1.60 + SCHEDULE_SAFETY_MARGIN_MS; 1.61 + 1.62 +/** 1.63 + * A per-stream update message passed from the media graph thread to the 1.64 + * main thread. 1.65 + */ 1.66 +struct StreamUpdate { 1.67 + int64_t mGraphUpdateIndex; 1.68 + nsRefPtr<MediaStream> mStream; 1.69 + StreamTime mNextMainThreadCurrentTime; 1.70 + bool mNextMainThreadFinished; 1.71 +}; 1.72 + 1.73 +/** 1.74 + * This represents a message passed from the main thread to the graph thread. 1.75 + * A ControlMessage always has a weak reference a particular affected stream. 1.76 + */ 1.77 +class ControlMessage { 1.78 +public: 1.79 + explicit ControlMessage(MediaStream* aStream) : mStream(aStream) 1.80 + { 1.81 + MOZ_COUNT_CTOR(ControlMessage); 1.82 + } 1.83 + // All these run on the graph thread 1.84 + virtual ~ControlMessage() 1.85 + { 1.86 + MOZ_COUNT_DTOR(ControlMessage); 1.87 + } 1.88 + // Do the action of this message on the MediaStreamGraph thread. Any actions 1.89 + // affecting graph processing should take effect at mStateComputedTime. 1.90 + // All stream data for times < mStateComputedTime has already been 1.91 + // computed. 1.92 + virtual void Run() = 0; 1.93 + // When we're shutting down the application, most messages are ignored but 1.94 + // some cleanup messages should still be processed (on the main thread). 1.95 + // This must not add new control messages to the graph. 1.96 + virtual void RunDuringShutdown() {} 1.97 + MediaStream* GetStream() { return mStream; } 1.98 + 1.99 +protected: 1.100 + // We do not hold a reference to mStream. The graph will be holding 1.101 + // a reference to the stream until the Destroy message is processed. The 1.102 + // last message referencing a stream is the Destroy message for that stream. 1.103 + MediaStream* mStream; 1.104 +}; 1.105 + 1.106 +/** 1.107 + * The implementation of a media stream graph. This class is private to this 1.108 + * file. It's not in the anonymous namespace because MediaStream needs to 1.109 + * be able to friend it. 1.110 + * 1.111 + * Currently we have one global instance per process, and one per each 1.112 + * OfflineAudioContext object. 1.113 + */ 1.114 +class MediaStreamGraphImpl : public MediaStreamGraph, 1.115 + public nsIMemoryReporter { 1.116 +public: 1.117 + NS_DECL_ISUPPORTS 1.118 + NS_DECL_NSIMEMORYREPORTER 1.119 + 1.120 + /** 1.121 + * Set aRealtime to true in order to create a MediaStreamGraph which provides 1.122 + * support for real-time audio and video. Set it to false in order to create 1.123 + * a non-realtime instance which just churns through its inputs and produces 1.124 + * output. Those objects currently only support audio, and are used to 1.125 + * implement OfflineAudioContext. They do not support MediaStream inputs. 1.126 + */ 1.127 + explicit MediaStreamGraphImpl(bool aRealtime, TrackRate aSampleRate); 1.128 + 1.129 + /** 1.130 + * Unregisters memory reporting and deletes this instance. This should be 1.131 + * called instead of calling the destructor directly. 1.132 + */ 1.133 + void Destroy(); 1.134 + 1.135 + // Main thread only. 1.136 + /** 1.137 + * This runs every time we need to sync state from the media graph thread 1.138 + * to the main thread while the main thread is not in the middle 1.139 + * of a script. It runs during a "stable state" (per HTML5) or during 1.140 + * an event posted to the main thread. 1.141 + */ 1.142 + void RunInStableState(); 1.143 + /** 1.144 + * Ensure a runnable to run RunInStableState is posted to the appshell to 1.145 + * run at the next stable state (per HTML5). 1.146 + * See EnsureStableStateEventPosted. 1.147 + */ 1.148 + void EnsureRunInStableState(); 1.149 + /** 1.150 + * Called to apply a StreamUpdate to its stream. 1.151 + */ 1.152 + void ApplyStreamUpdate(StreamUpdate* aUpdate); 1.153 + /** 1.154 + * Append a ControlMessage to the message queue. This queue is drained 1.155 + * during RunInStableState; the messages will run on the graph thread. 1.156 + */ 1.157 + void AppendMessage(ControlMessage* aMessage); 1.158 + /** 1.159 + * Make this MediaStreamGraph enter forced-shutdown state. This state 1.160 + * will be noticed by the media graph thread, which will shut down all streams 1.161 + * and other state controlled by the media graph thread. 1.162 + * This is called during application shutdown. 1.163 + */ 1.164 + void ForceShutDown(); 1.165 + /** 1.166 + * Shutdown() this MediaStreamGraph's threads and return when they've shut down. 1.167 + */ 1.168 + void ShutdownThreads(); 1.169 + 1.170 + /** 1.171 + * Called before the thread runs. 1.172 + */ 1.173 + void Init(); 1.174 + // The following methods run on the graph thread (or possibly the main thread if 1.175 + // mLifecycleState > LIFECYCLE_RUNNING) 1.176 + /** 1.177 + * Runs main control loop on the graph thread. Normally a single invocation 1.178 + * of this runs for the entire lifetime of the graph thread. 1.179 + */ 1.180 + void RunThread(); 1.181 + /** 1.182 + * Call this to indicate that another iteration of the control loop is 1.183 + * required on its regular schedule. The monitor must not be held. 1.184 + */ 1.185 + void EnsureNextIteration(); 1.186 + /** 1.187 + * As above, but with the monitor already held. 1.188 + */ 1.189 + void EnsureNextIterationLocked(MonitorAutoLock& aLock); 1.190 + /** 1.191 + * Call this to indicate that another iteration of the control loop is 1.192 + * required immediately. The monitor must already be held. 1.193 + */ 1.194 + void EnsureImmediateWakeUpLocked(MonitorAutoLock& aLock); 1.195 + /** 1.196 + * Ensure there is an event posted to the main thread to run RunInStableState. 1.197 + * mMonitor must be held. 1.198 + * See EnsureRunInStableState 1.199 + */ 1.200 + void EnsureStableStateEventPosted(); 1.201 + /** 1.202 + * Generate messages to the main thread to update it for all state changes. 1.203 + * mMonitor must be held. 1.204 + */ 1.205 + void PrepareUpdatesToMainThreadState(bool aFinalUpdate); 1.206 + /** 1.207 + * Returns false if there is any stream that has finished but not yet finished 1.208 + * playing out. 1.209 + */ 1.210 + bool AllFinishedStreamsNotified(); 1.211 + /** 1.212 + * If we are rendering in non-realtime mode, we don't want to send messages to 1.213 + * the main thread at each iteration for performance reasons. We instead 1.214 + * notify the main thread at the same rate 1.215 + */ 1.216 + bool ShouldUpdateMainThread(); 1.217 + // The following methods are the various stages of RunThread processing. 1.218 + /** 1.219 + * Compute a new current time for the graph and advance all on-graph-thread 1.220 + * state to the new current time. 1.221 + */ 1.222 + void UpdateCurrentTime(); 1.223 + /** 1.224 + * Update the consumption state of aStream to reflect whether its data 1.225 + * is needed or not. 1.226 + */ 1.227 + void UpdateConsumptionState(SourceMediaStream* aStream); 1.228 + /** 1.229 + * Extract any state updates pending in aStream, and apply them. 1.230 + */ 1.231 + void ExtractPendingInput(SourceMediaStream* aStream, 1.232 + GraphTime aDesiredUpToTime, 1.233 + bool* aEnsureNextIteration); 1.234 + /** 1.235 + * Update "have enough data" flags in aStream. 1.236 + */ 1.237 + void UpdateBufferSufficiencyState(SourceMediaStream* aStream); 1.238 + /* 1.239 + * If aStream hasn't already been ordered, push it onto aStack and order 1.240 + * its children. 1.241 + */ 1.242 + void UpdateStreamOrderForStream(mozilla::LinkedList<MediaStream>* aStack, 1.243 + already_AddRefed<MediaStream> aStream); 1.244 + /** 1.245 + * Mark aStream and all its inputs (recursively) as consumed. 1.246 + */ 1.247 + static void MarkConsumed(MediaStream* aStream); 1.248 + /** 1.249 + * Sort mStreams so that every stream not in a cycle is after any streams 1.250 + * it depends on, and every stream in a cycle is marked as being in a cycle. 1.251 + * Also sets mIsConsumed on every stream. 1.252 + */ 1.253 + void UpdateStreamOrder(); 1.254 + /** 1.255 + * Compute the blocking states of streams from mStateComputedTime 1.256 + * until the desired future time aEndBlockingDecisions. 1.257 + * Updates mStateComputedTime and sets MediaStream::mBlocked 1.258 + * for all streams. 1.259 + */ 1.260 + void RecomputeBlocking(GraphTime aEndBlockingDecisions); 1.261 + // The following methods are used to help RecomputeBlocking. 1.262 + /** 1.263 + * If aStream isn't already in aStreams, add it and recursively call 1.264 + * AddBlockingRelatedStreamsToSet on all the streams whose blocking 1.265 + * status could depend on or affect the state of aStream. 1.266 + */ 1.267 + void AddBlockingRelatedStreamsToSet(nsTArray<MediaStream*>* aStreams, 1.268 + MediaStream* aStream); 1.269 + /** 1.270 + * Mark a stream blocked at time aTime. If this results in decisions that need 1.271 + * to be revisited at some point in the future, *aEnd will be reduced to the 1.272 + * first time in the future to recompute those decisions. 1.273 + */ 1.274 + void MarkStreamBlocking(MediaStream* aStream); 1.275 + /** 1.276 + * Recompute blocking for the streams in aStreams for the interval starting at aTime. 1.277 + * If this results in decisions that need to be revisited at some point 1.278 + * in the future, *aEnd will be reduced to the first time in the future to 1.279 + * recompute those decisions. 1.280 + */ 1.281 + void RecomputeBlockingAt(const nsTArray<MediaStream*>& aStreams, 1.282 + GraphTime aTime, GraphTime aEndBlockingDecisions, 1.283 + GraphTime* aEnd); 1.284 + /** 1.285 + * Produce data for all streams >= aStreamIndex for the given time interval. 1.286 + * Advances block by block, each iteration producing data for all streams 1.287 + * for a single block. 1.288 + * This is called whenever we have an AudioNodeStream in the graph. 1.289 + */ 1.290 + void ProduceDataForStreamsBlockByBlock(uint32_t aStreamIndex, 1.291 + TrackRate aSampleRate, 1.292 + GraphTime aFrom, 1.293 + GraphTime aTo); 1.294 + /** 1.295 + * Returns true if aStream will underrun at aTime for its own playback. 1.296 + * aEndBlockingDecisions is when we plan to stop making blocking decisions. 1.297 + * *aEnd will be reduced to the first time in the future to recompute these 1.298 + * decisions. 1.299 + */ 1.300 + bool WillUnderrun(MediaStream* aStream, GraphTime aTime, 1.301 + GraphTime aEndBlockingDecisions, GraphTime* aEnd); 1.302 + /** 1.303 + * Given a graph time aTime, convert it to a stream time taking into 1.304 + * account the time during which aStream is scheduled to be blocked. 1.305 + */ 1.306 + StreamTime GraphTimeToStreamTime(MediaStream* aStream, GraphTime aTime); 1.307 + /** 1.308 + * Given a graph time aTime, convert it to a stream time taking into 1.309 + * account the time during which aStream is scheduled to be blocked, and 1.310 + * when we don't know whether it's blocked or not, we assume it's not blocked. 1.311 + */ 1.312 + StreamTime GraphTimeToStreamTimeOptimistic(MediaStream* aStream, GraphTime aTime); 1.313 + enum { 1.314 + INCLUDE_TRAILING_BLOCKED_INTERVAL = 0x01 1.315 + }; 1.316 + /** 1.317 + * Given a stream time aTime, convert it to a graph time taking into 1.318 + * account the time during which aStream is scheduled to be blocked. 1.319 + * aTime must be <= mStateComputedTime since blocking decisions 1.320 + * are only known up to that point. 1.321 + * If aTime is exactly at the start of a blocked interval, then the blocked 1.322 + * interval is included in the time returned if and only if 1.323 + * aFlags includes INCLUDE_TRAILING_BLOCKED_INTERVAL. 1.324 + */ 1.325 + GraphTime StreamTimeToGraphTime(MediaStream* aStream, StreamTime aTime, 1.326 + uint32_t aFlags = 0); 1.327 + /** 1.328 + * Get the current audio position of the stream's audio output. 1.329 + */ 1.330 + GraphTime GetAudioPosition(MediaStream* aStream); 1.331 + /** 1.332 + * Call NotifyHaveCurrentData on aStream's listeners. 1.333 + */ 1.334 + void NotifyHasCurrentData(MediaStream* aStream); 1.335 + /** 1.336 + * If aStream needs an audio stream but doesn't have one, create it. 1.337 + * If aStream doesn't need an audio stream but has one, destroy it. 1.338 + */ 1.339 + void CreateOrDestroyAudioStreams(GraphTime aAudioOutputStartTime, 1.340 + MediaStream* aStream); 1.341 + /** 1.342 + * Queue audio (mix of stream audio and silence for blocked intervals) 1.343 + * to the audio output stream. Returns the number of frames played. 1.344 + */ 1.345 + TrackTicks PlayAudio(MediaStream* aStream, GraphTime aFrom, GraphTime aTo); 1.346 + /** 1.347 + * Set the correct current video frame for stream aStream. 1.348 + */ 1.349 + void PlayVideo(MediaStream* aStream); 1.350 + /** 1.351 + * No more data will be forthcoming for aStream. The stream will end 1.352 + * at the current buffer end point. The StreamBuffer's tracks must be 1.353 + * explicitly set to finished by the caller. 1.354 + */ 1.355 + void FinishStream(MediaStream* aStream); 1.356 + /** 1.357 + * Compute how much stream data we would like to buffer for aStream. 1.358 + */ 1.359 + StreamTime GetDesiredBufferEnd(MediaStream* aStream); 1.360 + /** 1.361 + * Returns true when there are no active streams. 1.362 + */ 1.363 + bool IsEmpty() { return mStreams.IsEmpty() && mPortCount == 0; } 1.364 + 1.365 + // For use by control messages, on graph thread only. 1.366 + /** 1.367 + * Identify which graph update index we are currently processing. 1.368 + */ 1.369 + int64_t GetProcessingGraphUpdateIndex() { return mProcessingGraphUpdateIndex; } 1.370 + /** 1.371 + * Add aStream to the graph and initializes its graph-specific state. 1.372 + */ 1.373 + void AddStream(MediaStream* aStream); 1.374 + /** 1.375 + * Remove aStream from the graph. Ensures that pending messages about the 1.376 + * stream back to the main thread are flushed. 1.377 + */ 1.378 + void RemoveStream(MediaStream* aStream); 1.379 + /** 1.380 + * Remove aPort from the graph and release it. 1.381 + */ 1.382 + void DestroyPort(MediaInputPort* aPort); 1.383 + /** 1.384 + * Mark the media stream order as dirty. 1.385 + */ 1.386 + void SetStreamOrderDirty() 1.387 + { 1.388 + mStreamOrderDirty = true; 1.389 + } 1.390 + /** 1.391 + * Pause all AudioStreams being written to by MediaStreams 1.392 + */ 1.393 + void PauseAllAudioOutputs(); 1.394 + /** 1.395 + * Resume all AudioStreams being written to by MediaStreams 1.396 + */ 1.397 + void ResumeAllAudioOutputs(); 1.398 + 1.399 + TrackRate AudioSampleRate() { return mSampleRate; } 1.400 + 1.401 + // Data members 1.402 + 1.403 + /** 1.404 + * Media graph thread. 1.405 + * Readonly after initialization on the main thread. 1.406 + */ 1.407 + nsCOMPtr<nsIThread> mThread; 1.408 + 1.409 + // The following state is managed on the graph thread only, unless 1.410 + // mLifecycleState > LIFECYCLE_RUNNING in which case the graph thread 1.411 + // is not running and this state can be used from the main thread. 1.412 + 1.413 + nsTArray<nsRefPtr<MediaStream> > mStreams; 1.414 + /** 1.415 + * mOldStreams is used as temporary storage for streams when computing the 1.416 + * order in which we compute them. 1.417 + */ 1.418 + nsTArray<nsRefPtr<MediaStream> > mOldStreams; 1.419 + /** 1.420 + * The current graph time for the current iteration of the RunThread control 1.421 + * loop. 1.422 + */ 1.423 + GraphTime mCurrentTime; 1.424 + /** 1.425 + * Blocking decisions and all stream contents have been computed up to this 1.426 + * time. The next batch of updates from the main thread will be processed 1.427 + * at this time. Always >= mCurrentTime. 1.428 + */ 1.429 + GraphTime mStateComputedTime; 1.430 + /** 1.431 + * This is only used for logging. 1.432 + */ 1.433 + TimeStamp mInitialTimeStamp; 1.434 + /** 1.435 + * The real timestamp of the latest run of UpdateCurrentTime. 1.436 + */ 1.437 + TimeStamp mCurrentTimeStamp; 1.438 + /** 1.439 + * Date of the last time we updated the main thread with the graph state. 1.440 + */ 1.441 + TimeStamp mLastMainThreadUpdate; 1.442 + /** 1.443 + * Which update batch we are currently processing. 1.444 + */ 1.445 + int64_t mProcessingGraphUpdateIndex; 1.446 + /** 1.447 + * Number of active MediaInputPorts 1.448 + */ 1.449 + int32_t mPortCount; 1.450 + 1.451 + // mMonitor guards the data below. 1.452 + // MediaStreamGraph normally does its work without holding mMonitor, so it is 1.453 + // not safe to just grab mMonitor from some thread and start monkeying with 1.454 + // the graph. Instead, communicate with the graph thread using provided 1.455 + // mechanisms such as the ControlMessage queue. 1.456 + Monitor mMonitor; 1.457 + 1.458 + // Data guarded by mMonitor (must always be accessed with mMonitor held, 1.459 + // regardless of the value of mLifecycleState. 1.460 + 1.461 + /** 1.462 + * State to copy to main thread 1.463 + */ 1.464 + nsTArray<StreamUpdate> mStreamUpdates; 1.465 + /** 1.466 + * Runnables to run after the next update to main thread state. 1.467 + */ 1.468 + nsTArray<nsCOMPtr<nsIRunnable> > mUpdateRunnables; 1.469 + struct MessageBlock { 1.470 + int64_t mGraphUpdateIndex; 1.471 + nsTArray<nsAutoPtr<ControlMessage> > mMessages; 1.472 + }; 1.473 + /** 1.474 + * A list of batches of messages to process. Each batch is processed 1.475 + * as an atomic unit. 1.476 + */ 1.477 + nsTArray<MessageBlock> mMessageQueue; 1.478 + /** 1.479 + * This enum specifies where this graph is in its lifecycle. This is used 1.480 + * to control shutdown. 1.481 + * Shutdown is tricky because it can happen in two different ways: 1.482 + * 1) Shutdown due to inactivity. RunThread() detects that it has no 1.483 + * pending messages and no streams, and exits. The next RunInStableState() 1.484 + * checks if there are new pending messages from the main thread (true only 1.485 + * if new stream creation raced with shutdown); if there are, it revives 1.486 + * RunThread(), otherwise it commits to shutting down the graph. New stream 1.487 + * creation after this point will create a new graph. An async event is 1.488 + * dispatched to Shutdown() the graph's threads and then delete the graph 1.489 + * object. 1.490 + * 2) Forced shutdown at application shutdown, or completion of a 1.491 + * non-realtime graph. A flag is set, RunThread() detects the flag and 1.492 + * exits, the next RunInStableState() detects the flag, and dispatches the 1.493 + * async event to Shutdown() the graph's threads. However the graph object 1.494 + * is not deleted. New messages for the graph are processed synchronously on 1.495 + * the main thread if necessary. When the last stream is destroyed, the 1.496 + * graph object is deleted. 1.497 + */ 1.498 + enum LifecycleState { 1.499 + // The graph thread hasn't started yet. 1.500 + LIFECYCLE_THREAD_NOT_STARTED, 1.501 + // RunThread() is running normally. 1.502 + LIFECYCLE_RUNNING, 1.503 + // In the following states, the graph thread is not running so 1.504 + // all "graph thread only" state in this class can be used safely 1.505 + // on the main thread. 1.506 + // RunThread() has exited and we're waiting for the next 1.507 + // RunInStableState(), at which point we can clean up the main-thread 1.508 + // side of the graph. 1.509 + LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP, 1.510 + // RunInStableState() posted a ShutdownRunnable, and we're waiting for it 1.511 + // to shut down the graph thread(s). 1.512 + LIFECYCLE_WAITING_FOR_THREAD_SHUTDOWN, 1.513 + // Graph threads have shut down but we're waiting for remaining streams 1.514 + // to be destroyed. Only happens during application shutdown and on 1.515 + // completed non-realtime graphs, since normally we'd only shut down a 1.516 + // realtime graph when it has no streams. 1.517 + LIFECYCLE_WAITING_FOR_STREAM_DESTRUCTION 1.518 + }; 1.519 + LifecycleState mLifecycleState; 1.520 + /** 1.521 + * This enum specifies the wait state of the graph thread. 1.522 + */ 1.523 + enum WaitState { 1.524 + // RunThread() is running normally 1.525 + WAITSTATE_RUNNING, 1.526 + // RunThread() is paused waiting for its next iteration, which will 1.527 + // happen soon 1.528 + WAITSTATE_WAITING_FOR_NEXT_ITERATION, 1.529 + // RunThread() is paused indefinitely waiting for something to change 1.530 + WAITSTATE_WAITING_INDEFINITELY, 1.531 + // Something has signaled RunThread() to wake up immediately, 1.532 + // but it hasn't done so yet 1.533 + WAITSTATE_WAKING_UP 1.534 + }; 1.535 + WaitState mWaitState; 1.536 + /** 1.537 + * The graph should stop processing at or after this time. 1.538 + */ 1.539 + GraphTime mEndTime; 1.540 + 1.541 + /** 1.542 + * Sample rate at which this graph runs. For real time graphs, this is 1.543 + * the rate of the audio mixer. For offline graphs, this is the rate specified 1.544 + * at construction. 1.545 + */ 1.546 + TrackRate mSampleRate; 1.547 + /** 1.548 + * True when another iteration of the control loop is required. 1.549 + */ 1.550 + bool mNeedAnotherIteration; 1.551 + /** 1.552 + * True when we need to do a forced shutdown during application shutdown. 1.553 + */ 1.554 + bool mForceShutDown; 1.555 + /** 1.556 + * True when we have posted an event to the main thread to run 1.557 + * RunInStableState() and the event hasn't run yet. 1.558 + */ 1.559 + bool mPostedRunInStableStateEvent; 1.560 + 1.561 + // Main thread only 1.562 + 1.563 + /** 1.564 + * Messages posted by the current event loop task. These are forwarded to 1.565 + * the media graph thread during RunInStableState. We can't forward them 1.566 + * immediately because we want all messages between stable states to be 1.567 + * processed as an atomic batch. 1.568 + */ 1.569 + nsTArray<nsAutoPtr<ControlMessage> > mCurrentTaskMessageQueue; 1.570 + /** 1.571 + * True when RunInStableState has determined that mLifecycleState is > 1.572 + * LIFECYCLE_RUNNING. Since only the main thread can reset mLifecycleState to 1.573 + * LIFECYCLE_RUNNING, this can be relied on to not change unexpectedly. 1.574 + */ 1.575 + bool mDetectedNotRunning; 1.576 + /** 1.577 + * True when a stable state runner has been posted to the appshell to run 1.578 + * RunInStableState at the next stable state. 1.579 + */ 1.580 + bool mPostedRunInStableState; 1.581 + /** 1.582 + * True when processing real-time audio/video. False when processing non-realtime 1.583 + * audio. 1.584 + */ 1.585 + bool mRealtime; 1.586 + /** 1.587 + * True when a non-realtime MediaStreamGraph has started to process input. This 1.588 + * value is only accessed on the main thread. 1.589 + */ 1.590 + bool mNonRealtimeProcessing; 1.591 + /** 1.592 + * True when a change has happened which requires us to recompute the stream 1.593 + * blocking order. 1.594 + */ 1.595 + bool mStreamOrderDirty; 1.596 + /** 1.597 + * Hold a ref to the Latency logger 1.598 + */ 1.599 + nsRefPtr<AsyncLatencyLogger> mLatencyLog; 1.600 + /** 1.601 + * If this is not null, all the audio output for the MSG will be mixed down. 1.602 + */ 1.603 + nsAutoPtr<AudioMixer> mMixer; 1.604 + 1.605 +private: 1.606 + virtual ~MediaStreamGraphImpl(); 1.607 + 1.608 + MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf) 1.609 + 1.610 + /** 1.611 + * Used to signal that a memory report has been requested. 1.612 + */ 1.613 + Monitor mMemoryReportMonitor; 1.614 + /** 1.615 + * This class uses manual memory management, and all pointers to it are raw 1.616 + * pointers. However, in order for it to implement nsIMemoryReporter, it needs 1.617 + * to implement nsISupports and so be ref-counted. So it maintains a single 1.618 + * nsRefPtr to itself, giving it a ref-count of 1 during its entire lifetime, 1.619 + * and Destroy() nulls this self-reference in order to trigger self-deletion. 1.620 + */ 1.621 + nsRefPtr<MediaStreamGraphImpl> mSelfRef; 1.622 + /** 1.623 + * Used to pass memory report information across threads. 1.624 + */ 1.625 + nsTArray<AudioNodeSizes> mAudioStreamSizes; 1.626 + /** 1.627 + * Indicates that the MSG thread should gather data for a memory report. 1.628 + */ 1.629 + bool mNeedsMemoryReport; 1.630 + 1.631 +#ifdef DEBUG 1.632 + /** 1.633 + * Used to assert when AppendMessage() runs ControlMessages synchronously. 1.634 + */ 1.635 + bool mCanRunMessagesSynchronously; 1.636 +#endif 1.637 + 1.638 +}; 1.639 + 1.640 +} 1.641 + 1.642 +#endif /* MEDIASTREAMGRAPHIMPL_H_ */