author | Paul Adenot <paul@paul.cx> |
Thu, 29 Jun 2017 11:31:17 -0700 | |
changeset 366889 | e0c4f2ca44b4292881a56fab6bf584bf7d966299 |
parent 366888 | 5de53323f3ad17102b9428fc3c06066055cabc73 |
child 366890 | 5c2fea87df168bdcbfe807ffedfb6d7c1ea4cb4e |
push id | 32109 |
push user | cbook@mozilla.com |
push date | Fri, 30 Jun 2017 11:00:05 +0000 |
treeherder | mozilla-central@d536973fe668 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | pehrsons |
bugs | 1341555 |
milestone | 56.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- 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,22 @@ MediaStreamGraphImpl::AppendMessage(Uniq } return; } mCurrentTaskMessageQueue.AppendElement(Move(aMessage)); EnsureRunInStableState(); } +void +MediaStreamGraphImpl::Dispatch(already_AddRefed<nsIRunnable>&& aRunnable) +{ + mAbstractMainThread->Dispatch(Move(aRunnable)); +} + MediaStream::MediaStream(AbstractThread* aMainThread) : mTracksStartTime(0) , mStartBlocking(GRAPH_TIME_MAX) , mSuspendedCount(0) , mFinished(false) , mNotifiedFinished(false) , mNotifiedBlocked(false) , mHasCurrentData(false) @@ -2558,17 +2566,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 +2686,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 +3423,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 +3452,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 +3545,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 +3699,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 +3823,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 +3926,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());
--- a/dom/media/MediaStreamGraph.h +++ b/dom/media/MediaStreamGraph.h @@ -17,16 +17,17 @@ #include "mozilla/dom/AudioChannelBinding.h" #include "nsAutoPtr.h" #include "nsAutoRef.h" #include "nsIRunnable.h" #include "nsTArray.h" #include <speex/speex_resampler.h> class nsIRunnable; +class nsIGlobalObject; class nsPIDOMWindowInner; template <> class nsAutoRefTraits<SpeexResamplerState> : public nsPointerRefTraits<SpeexResamplerState> { public: static void Release(SpeexResamplerState* aState) { speex_resampler_destroy(aState); } }; @@ -1271,17 +1272,18 @@ public: OFFLINE_THREAD_DRIVER }; static const uint32_t AUDIO_CALLBACK_DRIVER_SHUTDOWN_TIMEOUT = 20*1000; // Main thread only static MediaStreamGraph* GetInstance(GraphDriverType aGraphDriverRequested, dom::AudioChannel aChannel, nsPIDOMWindowInner* aWindow); - static MediaStreamGraph* CreateNonRealtimeInstance(TrackRate aSampleRate); + static MediaStreamGraph* CreateNonRealtimeInstance(TrackRate aSampleRate, + nsPIDOMWindowInner* aWindowId); // Idempotent static void DestroyNonRealtimeInstance(MediaStreamGraph* aGraph); virtual nsresult OpenAudioInput(int aID, AudioDataListener *aListener) { return NS_ERROR_FAILURE; } virtual void CloseAudioInput(AudioDataListener *aListener) {}
--- a/dom/media/MediaStreamGraphImpl.h +++ b/dom/media/MediaStreamGraphImpl.h @@ -111,17 +111,18 @@ public: * to create a MediaStreamGraph which provides support for real-time audio * and/or video. Set it to OFFLINE_THREAD_DRIVER in order to create a * non-realtime instance which just churns through its inputs and produces * output. Those objects currently only support audio, and are used to * implement OfflineAudioContext. They do not support MediaStream inputs. */ explicit MediaStreamGraphImpl(GraphDriverType aGraphDriverRequested, TrackRate aSampleRate, - dom::AudioChannel aChannel); + dom::AudioChannel aChannel, + AbstractThread* aWindow); /** * Unregisters memory reporting and deletes this instance. This should be * called instead of calling the destructor directly. */ void Destroy(); // Main thread only. @@ -144,16 +145,22 @@ public: */ void ApplyStreamUpdate(StreamUpdate* aUpdate); /** * Append a ControlMessage to the message queue. This queue is drained * during RunInStableState; the messages will run on the graph thread. */ void AppendMessage(UniquePtr<ControlMessage> aMessage); + /** + * Dispatches a runnable from any thread to the correct main thread for this + * MediaStreamGraph. + */ + void Dispatch(already_AddRefed<nsIRunnable>&& aRunnable); + // Shutdown helpers. static already_AddRefed<nsIAsyncShutdownClient> GetShutdownBarrier() { nsCOMPtr<nsIAsyncShutdownService> svc = services::GetAsyncShutdown(); MOZ_RELEASE_ASSERT(svc); @@ -841,13 +848,14 @@ private: #ifdef DEBUG /** * Used to assert when AppendMessage() runs ControlMessages synchronously. */ bool mCanRunMessagesSynchronously; #endif dom::AudioChannel mAudioChannel; + const RefPtr<AbstractThread> mAbstractMainThread; }; } // namespace mozilla #endif /* MEDIASTREAMGRAPHIMPL_H_ */
--- a/dom/media/webaudio/AudioDestinationNode.cpp +++ b/dom/media/webaudio/AudioDestinationNode.cpp @@ -332,17 +332,17 @@ AudioDestinationNode::AudioDestinationNo , mAudioChannel(AudioChannel::Normal) , mIsOffline(aIsOffline) , mAudioChannelSuspended(false) , mCaptured(false) , mAudible(AudioChannelService::AudibleState::eAudible) { nsPIDOMWindowInner* window = aContext->GetParentObject(); MediaStreamGraph* graph = aIsOffline ? - MediaStreamGraph::CreateNonRealtimeInstance(aSampleRate) : + MediaStreamGraph::CreateNonRealtimeInstance(aSampleRate, window) : MediaStreamGraph::GetInstance(MediaStreamGraph::AUDIO_THREAD_DRIVER, aChannel, window); AudioNodeEngine* engine = aIsOffline ? new OfflineDestinationNodeEngine(this, aNumberOfChannels, aLength, aSampleRate) : static_cast<AudioNodeEngine*>(new DestinationNodeEngine(this)); AudioNodeStream::Flags flags = AudioNodeStream::NEED_MAIN_THREAD_CURRENT_TIME |