--- a/dom/media/MediaStreamGraph.cpp
+++ b/dom/media/MediaStreamGraph.cpp
@@ -1007,19 +1007,20 @@ MediaStreamGraphImpl::OpenAudioInputImpl
}
nsresult
MediaStreamGraphImpl::OpenAudioInput(int aID,
AudioDataListener *aListener)
{
// So, so, so annoying. Can't AppendMessage except on Mainthread
if (!NS_IsMainThread()) {
- NS_DispatchToMainThread(WrapRunnable(this,
- &MediaStreamGraphImpl::OpenAudioInput,
- aID, RefPtr<AudioDataListener>(aListener)));
+ RefPtr<nsIRunnable> runnable = WrapRunnable(this,
+ &MediaStreamGraphImpl::OpenAudioInput,
+ aID, RefPtr<AudioDataListener>(aListener));
+ mAbstractMainThread->Dispatch(runnable.forget());
return NS_OK;
}
class Message : public ControlMessage {
public:
Message(MediaStreamGraphImpl *aGraph, int aID,
AudioDataListener *aListener) :
ControlMessage(nullptr), mGraph(aGraph), mID(aID), mListener(aListener) {}
virtual void Run()
@@ -1077,19 +1078,20 @@ MediaStreamGraphImpl::CloseAudioInputImp
}
}
void
MediaStreamGraphImpl::CloseAudioInput(AudioDataListener *aListener)
{
// So, so, so annoying. Can't AppendMessage except on Mainthread
if (!NS_IsMainThread()) {
- NS_DispatchToMainThread(WrapRunnable(this,
- &MediaStreamGraphImpl::CloseAudioInput,
- RefPtr<AudioDataListener>(aListener)));
+ RefPtr<nsIRunnable> runnable = WrapRunnable(this,
+ &MediaStreamGraphImpl::CloseAudioInput,
+ RefPtr<AudioDataListener>(aListener));
+ mAbstractMainThread->Dispatch(runnable.forget());
return;
}
class Message : public ControlMessage {
public:
Message(MediaStreamGraphImpl *aGraph, AudioDataListener *aListener) :
ControlMessage(nullptr), mGraph(aGraph), mListener(aListener) {}
virtual void Run()
{
@@ -1698,17 +1700,17 @@ MediaStreamGraphImpl::RunInStableState(b
// A new graph graph will be created if one is needed.
// Asynchronously clean up old graph. We don't want to do this
// synchronously because it spins the event loop waiting for threads
// to shut down, and we don't want to do that in a stable state handler.
mLifecycleState = LIFECYCLE_WAITING_FOR_THREAD_SHUTDOWN;
LOG(LogLevel::Debug,
("Sending MediaStreamGraphShutDownRunnable %p", this));
nsCOMPtr<nsIRunnable> event = new MediaStreamGraphShutDownRunnable(this );
- NS_DispatchToMainThread(event.forget());
+ mAbstractMainThread->Dispatch(event.forget());
LOG(LogLevel::Debug, ("Disconnecting MediaStreamGraph %p", this));
// Find the graph in the hash table and remove it.
for (auto iter = gGraphs.Iter(); !iter.Done(); iter.Next()) {
if (iter.UserData() == this) {
iter.Remove();
break;
@@ -1781,17 +1783,17 @@ MediaStreamGraphImpl::RunInStableState(b
controlMessagesToRunDuringShutdown.AppendElements(Move(mb.mMessages));
}
mBackMessageQueue.Clear();
MOZ_ASSERT(mCurrentTaskMessageQueue.IsEmpty());
// Stop MediaStreamGraph threads. Do not clear gGraph since
// we have outstanding DOM objects that may need it.
mLifecycleState = LIFECYCLE_WAITING_FOR_THREAD_SHUTDOWN;
nsCOMPtr<nsIRunnable> event = new MediaStreamGraphShutDownRunnable(this);
- NS_DispatchToMainThread(event.forget());
+ mAbstractMainThread->Dispatch(event.forget());
}
mDetectedNotRunning = mLifecycleState > LIFECYCLE_RUNNING;
}
// Make sure we get a new current time in the next event loop task
if (!aSourceIsMSG) {
MOZ_ASSERT(mPostedRunInStableState);
@@ -1829,17 +1831,17 @@ void
MediaStreamGraphImpl::EnsureStableStateEventPosted()
{
mMonitor.AssertCurrentThreadOwns();
if (mPostedRunInStableStateEvent)
return;
mPostedRunInStableStateEvent = true;
nsCOMPtr<nsIRunnable> event = new MediaStreamGraphStableStateRunnable(this, true);
- NS_DispatchToMainThread(event.forget());
+ mAbstractMainThread->Dispatch(event.forget());
}
void
MediaStreamGraphImpl::AppendMessage(UniquePtr<ControlMessage> aMessage)
{
MOZ_ASSERT(NS_IsMainThread(), "main thread only");
MOZ_ASSERT(!aMessage->GetStream() ||
!aMessage->GetStream()->IsDestroyed(),
@@ -1876,16 +1878,21 @@ MediaStreamGraphImpl::AppendMessage(Uniq
}
return;
}
mCurrentTaskMessageQueue.AppendElement(Move(aMessage));
EnsureRunInStableState();
}
+void MediaStreamGraphImpl::Dispatch(already_AddRefed<nsIRunnable>&& aRunnable)
+{
+ mAbstractMainThread->Dispatch(std::move(aRunnable));
+}
+
MediaStream::MediaStream(AbstractThread* aMainThread)
: mTracksStartTime(0)
, mStartBlocking(GRAPH_TIME_MAX)
, mSuspendedCount(0)
, mFinished(false)
, mNotifiedFinished(false)
, mNotifiedBlocked(false)
, mHasCurrentData(false)
@@ -2558,17 +2565,17 @@ MediaStream::RunAfterPendingUpdates(alre
DispatchToMainThreadAfterStreamStateUpdate(mAbstractMainThread,
mRunnable.forget());
}
void RunDuringShutdown() override
{
// Don't run mRunnable now as it may call AppendMessage() which would
// assume that there are no remaining controlMessagesToRunDuringShutdown.
MOZ_ASSERT(NS_IsMainThread());
- NS_DispatchToCurrentThread(mRunnable);
+ mStream->GraphImpl()->Dispatch(mRunnable.forget());
}
private:
nsCOMPtr<nsIRunnable> mRunnable;
const RefPtr<AbstractThread> mAbstractMainThread;
};
graph->AppendMessage(
MakeUnique<Message>(this, runnable.forget(), mAbstractMainThread));
@@ -2678,17 +2685,17 @@ MediaStream::AddMainThreadListener(MainT
private:
~NotifyRunnable() {}
RefPtr<MediaStream> mStream;
};
nsCOMPtr<nsIRunnable> runnable = new NotifyRunnable(this);
- Unused << NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(runnable.forget())));
+ mAbstractMainThread->Dispatch(runnable.forget());
}
SourceMediaStream::SourceMediaStream(AbstractThread* aMainThread) :
MediaStream(aMainThread),
mMutex("mozilla::media::SourceMediaStream"),
mUpdateKnownTracksTime(0),
mPullEnabled(false),
mUpdateFinished(false),
@@ -3415,17 +3422,18 @@ ProcessedMediaStream::DestroyImpl()
// The stream order is only important if there are connections, in which
// case MediaInputPort::Disconnect() called SetStreamOrderDirty().
// MediaStreamGraphImpl::RemoveStreamGraphThread() will also call
// SetStreamOrderDirty(), for other reasons.
}
MediaStreamGraphImpl::MediaStreamGraphImpl(GraphDriverType aDriverRequested,
TrackRate aSampleRate,
- dom::AudioChannel aChannel)
+ dom::AudioChannel aChannel,
+ AbstractThread* aMainThread)
: MediaStreamGraph(aSampleRate)
, mPortCount(0)
, mInputWanted(false)
, mInputDeviceID(-1)
, mOutputWanted(true)
, mOutputDeviceID(-1)
, mNeedAnotherIteration(false)
, mGraphDriverAsleep(false)
@@ -3443,16 +3451,17 @@ MediaStreamGraphImpl::MediaStreamGraphIm
#ifdef MOZ_WEBRTC
, mFarendObserverRef(nullptr)
#endif
, mSelfRef(this)
#ifdef DEBUG
, mCanRunMessagesSynchronously(false)
#endif
, mAudioChannel(aChannel)
+ , mAbstractMainThread(aMainThread)
{
if (mRealtime) {
if (aDriverRequested == AUDIO_THREAD_DRIVER) {
AudioCallbackDriver* driver = new AudioCallbackDriver(this);
mDriver = driver;
} else {
mDriver = new SystemClockDriver(this);
}
@@ -3535,39 +3544,51 @@ MediaStreamGraph::GetInstance(MediaStrea
nsCOMPtr<nsIAsyncShutdownClient> barrier = MediaStreamGraphImpl::GetShutdownBarrier();
nsresult rv = barrier->
AddBlocker(gMediaStreamGraphShutdownBlocker,
NS_LITERAL_STRING(__FILE__), __LINE__,
NS_LITERAL_STRING("MediaStreamGraph shutdown"));
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
}
+ AbstractThread* mainThread;
+ if (aWindow) {
+ nsCOMPtr<nsIGlobalObject> parentObject = do_QueryInterface(aWindow);
+ mainThread = parentObject->AbstractMainThreadFor(TaskCategory::Other);
+ } else {
+ // Uncommon case, only for some old configuration of webspeech.
+ mainThread = AbstractThread::MainThread();
+ }
graph = new MediaStreamGraphImpl(aGraphDriverRequested,
CubebUtils::PreferredSampleRate(),
- aChannel);
+ aChannel,
+ mainThread);
gGraphs.Put(hashkey, graph);
LOG(LogLevel::Debug,
("Starting up MediaStreamGraph %p for channel %s and window %p",
graph, AudioChannelValues::strings[channel].value, aWindow));
}
return graph;
}
MediaStreamGraph*
-MediaStreamGraph::CreateNonRealtimeInstance(TrackRate aSampleRate)
+MediaStreamGraph::CreateNonRealtimeInstance(TrackRate aSampleRate,
+ nsPIDOMWindowInner* aWindow)
{
NS_ASSERTION(NS_IsMainThread(), "Main thread only");
+ nsCOMPtr<nsIGlobalObject> parentObject = do_QueryInterface(aWindow);
MediaStreamGraphImpl* graph =
new MediaStreamGraphImpl(OFFLINE_THREAD_DRIVER,
aSampleRate,
- AudioChannel::Normal);
+ AudioChannel::Normal,
+ parentObject->AbstractMainThreadFor(TaskCategory::Other));
LOG(LogLevel::Debug, ("Starting up Offline MediaStreamGraph %p", graph));
return graph;
}
void
MediaStreamGraph::DestroyNonRealtimeInstance(MediaStreamGraph* aGraph)
@@ -3677,17 +3698,17 @@ MediaStreamGraphImpl::CollectSizesForMem
for (MediaStream* s : AllStreams()) {
AudioNodeStream* stream = s->AsAudioNodeStream();
if (stream) {
AudioNodeSizes* usage = audioStreamSizes->AppendElement();
stream->SizeOfAudioNodesIncludingThis(MallocSizeOf, *usage);
}
}
- NS_DispatchToMainThread(runnable.forget());
+ mAbstractMainThread->Dispatch(runnable.forget());
}
void
MediaStreamGraphImpl::
FinishCollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData,
const nsTArray<AudioNodeSizes>& aAudioStreamSizes)
{
MOZ_ASSERT(NS_IsMainThread());
@@ -3801,21 +3822,21 @@ MediaStreamGraph::NotifyWhenGraphStarted
// This runs on the graph thread, so when this runs, and the current
// driver is an AudioCallbackDriver, we know the audio hardware is
// started. If not, we are going to switch soon, keep reposting this
// ControlMessage.
MediaStreamGraphImpl* graphImpl = mStream->GraphImpl();
if (graphImpl->CurrentDriver()->AsAudioCallbackDriver()) {
nsCOMPtr<nsIRunnable> event = new dom::StateChangeTask(
mStream->AsAudioNodeStream(), nullptr, AudioContextState::Running);
- NS_DispatchToMainThread(event.forget());
+ graphImpl->Dispatch(event.forget());
} else {
nsCOMPtr<nsIRunnable> event = new GraphStartedRunnable(
mStream->AsAudioNodeStream(), mStream->Graph());
- NS_DispatchToMainThread(event.forget());
+ graphImpl->Dispatch(event.forget());
}
}
void RunDuringShutdown() override
{
}
};
if (!aStream->IsDestroyed()) {
@@ -3904,17 +3925,17 @@ MediaStreamGraphImpl::AudioContextOperat
case AudioContextOperation::Close:
state = AudioContextState::Closed;
break;
default: MOZ_CRASH("Not handled.");
}
nsCOMPtr<nsIRunnable> event = new dom::StateChangeTask(
aStream->AsAudioNodeStream(), aPromise, state);
- NS_DispatchToMainThread(event.forget());
+ mAbstractMainThread->Dispatch(event.forget());
}
void
MediaStreamGraphImpl::ApplyAudioContextOperationImpl(
MediaStream* aDestinationStream, const nsTArray<MediaStream*>& aStreams,
AudioContextOperation aOperation, void* aPromise)
{
MOZ_ASSERT(CurrentDriver()->OnThread());