diff --git a/dom/media/MediaStreamGraph.cpp b/dom/media/MediaStreamGraph.cpp index 2816d94f3e63..b406e94a38c7 100644 --- a/dom/media/MediaStreamGraph.cpp +++ b/dom/media/MediaStreamGraph.cpp @@ -1000,7 +1000,21 @@ MediaStreamGraphImpl::AllFinishedStreamsNotified() } void -MediaStreamGraphImpl::UpdateGraph(GraphTime aEndBlockingDecisions) +MediaStreamGraphImpl::RunMessageAfterProcessing(nsAutoPtr aMessage) +{ + MOZ_ASSERT(CurrentDriver()->OnThread()); + + if (mFrontMessageQueue.IsEmpty()) { + mFrontMessageQueue.AppendElement(); + } + + // Only one block is used for messages from the graph thread. + MOZ_ASSERT(mFrontMessageQueue.Length() == 1); + mFrontMessageQueue[0].mMessages.AppendElement(Move(aMessage)); +} + +void +MediaStreamGraphImpl::RunMessagesInQueue() { // Calculate independent action times for each batch of messages (each // batch corresponding to an event loop task). This isolates the performance @@ -1013,7 +1027,11 @@ MediaStreamGraphImpl::UpdateGraph(GraphTime aEndBlockingDecisions) } } mFrontMessageQueue.Clear(); +} +void +MediaStreamGraphImpl::UpdateGraph(GraphTime aEndBlockingDecisions) +{ MOZ_ASSERT(aEndBlockingDecisions >= mProcessedTime); // The next state computed time can be the same as the previous: it // means the driver would be have been blocking indefinitly, but the graph has @@ -1204,6 +1222,9 @@ MediaStreamGraphImpl::OneIteration(GraphTime aStateEnd) { MaybeProduceMemoryReport(); + // Process graph message from the main thread for this iteration. + RunMessagesInQueue(); + GraphTime stateEnd = std::min(aStateEnd, mEndTime); UpdateGraph(stateEnd); @@ -1216,6 +1237,10 @@ MediaStreamGraphImpl::OneIteration(GraphTime aStateEnd) UpdateCurrentTimeForStreams(oldProcessedTime); + // Process graph messages queued from RunMessageAfterProcessing() on this + // thread during the iteration. + RunMessagesInQueue(); + return UpdateMainThreadState(); } diff --git a/dom/media/MediaStreamGraphImpl.h b/dom/media/MediaStreamGraphImpl.h index a27857c54b86..c5e850ca6b3c 100644 --- a/dom/media/MediaStreamGraphImpl.h +++ b/dom/media/MediaStreamGraphImpl.h @@ -38,8 +38,11 @@ struct StreamUpdate }; /** - * This represents a message passed from the main thread to the graph thread. - * A ControlMessage always has a weak reference a particular affected stream. + * This represents a message run on the graph thread to modify stream or graph + * state. These are passed from main thread to graph thread through + * AppendMessage(), or scheduled on the graph thread with + * RunMessageAfterProcessing(). A ControlMessage + * always has a weak reference to a particular affected stream. */ class ControlMessage { @@ -58,6 +61,8 @@ public: // All stream data for times < mProcessedTime has already been // computed. virtual void Run() = 0; + // RunDuringShutdown() is only relevant to messages generated on the main + // thread (for AppendMessage()). // When we're shutting down the application, most messages are ignored but // some cleanup messages should still be processed (on the main thread). // This must not add new control messages to the graph. @@ -218,8 +223,12 @@ public: */ void UpdateCurrentTimeForStreams(GraphTime aPrevCurrentTime); /** - * Process graph message for this iteration, update stream processing order, - * and recompute stream blocking until aEndBlockingDecisions. + * Process graph messages in mFrontMessageQueue. + */ + void RunMessagesInQueue(); + /** + * Update stream processing order and recompute stream blocking until + * aEndBlockingDecisions. */ void UpdateGraph(GraphTime aEndBlockingDecisions); @@ -242,6 +251,14 @@ public: GraphTime aDesiredUpToTime, bool* aEnsureNextIteration); + /** + * For use during ProcessedMediaStream::ProcessInput() or + * MediaStreamListener callbacks, when graph state cannot be changed. + * Schedules |aMessage| to run after processing, at a time when graph state + * can be changed. Graph thread. + */ + void RunMessageAfterProcessing(nsAutoPtr aMessage); + /** * Called when a suspend/resume/close operation has been completed, on the * graph thread.