author | Andrea Marchesini <amarchesini@mozilla.com> |
Mon, 11 May 2015 15:07:24 +0100 | |
changeset 243364 | bad7af6079e93cdac37461f8e55ca0a7a528230b |
parent 243363 | 6b1f47f5127108307a513220a0db57a011ed24a0 |
child 243365 | 4c5f304c7451b8e9e14baba2677ce54f95bdfd87 |
push id | 28738 |
push user | cbook@mozilla.com |
push date | Tue, 12 May 2015 14:11:31 +0000 |
treeherder | mozilla-central@bedce1b405a3 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | padenot |
bugs | 1161946 |
milestone | 40.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/DOMMediaStream.cpp +++ b/dom/media/DOMMediaStream.cpp @@ -465,21 +465,20 @@ DOMMediaStream::NotifyMediaStreamGraphSh // to prevent leaks. mNotifiedOfMediaStreamGraphShutdown = true; mRunOnTracksAvailable.Clear(); mConsumersToKeepAlive.Clear(); } void -DOMMediaStream::NotifyStreamStateChanged() +DOMMediaStream::NotifyStreamFinished() { - if (IsFinished()) { - mConsumersToKeepAlive.Clear(); - } + MOZ_ASSERT(IsFinished()); + mConsumersToKeepAlive.Clear(); } void DOMMediaStream::OnTracksAvailable(OnTracksAvailableCallback* aRunnable) { if (mNotifiedOfMediaStreamGraphShutdown) { // No more tracks will ever be added, so just delete the callback now. delete aRunnable;
--- a/dom/media/DOMMediaStream.h +++ b/dom/media/DOMMediaStream.h @@ -163,19 +163,19 @@ public: /** * Called when this stream's MediaStreamGraph has been shut down. Normally * MSGs are only shut down when all streams have been removed, so this * will only be called during a forced shutdown due to application exit. */ void NotifyMediaStreamGraphShutdown(); /** - * Called when the main-thread state of the MediaStream changed. + * Called when the main-thread state of the MediaStream goes to finished. */ - void NotifyStreamStateChanged(); + void NotifyStreamFinished(); // Webrtc allows the remote side to name a stream whatever it wants, and we // need to surface this to content. void AssignId(const nsAString& aID) { mID = aID; } /** * Create an nsDOMMediaStream whose underlying stream is a SourceMediaStream. */
--- a/dom/media/MediaStreamGraph.cpp +++ b/dom/media/MediaStreamGraph.cpp @@ -1538,21 +1538,24 @@ MediaStreamGraphImpl::ApplyStreamUpdate( mMonitor.AssertCurrentThreadOwns(); MediaStream* stream = aUpdate->mStream; if (!stream) return; stream->mMainThreadCurrentTime = aUpdate->mNextMainThreadCurrentTime; stream->mMainThreadFinished = aUpdate->mNextMainThreadFinished; - if (stream->mWrapper) { - stream->mWrapper->NotifyStreamStateChanged(); - } - for (int32_t i = stream->mMainThreadListeners.Length() - 1; i >= 0; --i) { - stream->mMainThreadListeners[i]->NotifyMainThreadStateChanged(); + if (stream->ShouldNotifyStreamFinished()) { + if (stream->mWrapper) { + stream->mWrapper->NotifyStreamFinished(); + } + + for (int32_t i = stream->mMainThreadListeners.Length() - 1; i >= 0; --i) { + stream->mMainThreadListeners[i]->NotifyMainThreadStreamFinished(); + } } } void MediaStreamGraphImpl::ForceShutDown() { NS_ASSERTION(NS_IsMainThread(), "Must be called on main thread"); STREAM_LOG(PR_LOG_DEBUG, ("MediaStreamGraph %p ForceShutdown", this)); @@ -1913,16 +1916,17 @@ MediaStream::MediaStream(DOMMediaStream* , mFinished(false) , mNotifiedFinished(false) , mNotifiedBlocked(false) , mHasCurrentData(false) , mNotifiedHasCurrentData(false) , mWrapper(aWrapper) , mMainThreadCurrentTime(0) , mMainThreadFinished(false) + , mFinishedNotificationSent(false) , mMainThreadDestroyed(false) , mGraph(nullptr) , mAudioChannelType(dom::AudioChannel::Normal) { MOZ_COUNT_CTOR(MediaStream); // aWrapper should not already be connected to a MediaStream! It needs // to be hooked up to this stream, and since this stream is only just // being created now, aWrapper must not be connected to anything.
--- a/dom/media/MediaStreamGraph.h +++ b/dom/media/MediaStreamGraph.h @@ -221,17 +221,17 @@ public: * You should do something non-blocking and non-reentrant (e.g. dispatch an * event) and return. DispatchFromMainThreadAfterNextStreamStateUpdate * would be a good choice. * The listener is allowed to synchronously remove itself from the stream, but * not add or remove any other listeners. */ class MainThreadMediaStreamListener { public: - virtual void NotifyMainThreadStateChanged() = 0; + virtual void NotifyMainThreadStreamFinished() = 0; }; /** * Helper struct used to keep track of memory usage by AudioNodes. */ struct AudioNodeSizes { AudioNodeSizes() : mDomNode(0), mStream(0), mEngine(0), mNodeType() {} @@ -412,16 +412,17 @@ public: return mMainThreadCurrentTime; } // Return the main thread's view of whether this stream has finished. bool IsFinished() { NS_ASSERTION(NS_IsMainThread(), "Call only on main thread"); return mMainThreadFinished; } + bool IsDestroyed() { NS_ASSERTION(NS_IsMainThread(), "Call only on main thread"); return mMainThreadDestroyed; } friend class MediaStreamGraphImpl; friend class MediaInputPort; @@ -591,16 +592,27 @@ protected: mBufferStartTime += aBlockedTime; mGraphUpdateIndices.InsertTimeAtStart(aBlockedTime); mGraphUpdateIndices.AdvanceCurrentTime(aCurrentTime); mExplicitBlockerCount.AdvanceCurrentTime(aCurrentTime); mBuffer.ForgetUpTo(aCurrentTime - mBufferStartTime); } + bool ShouldNotifyStreamFinished() + { + NS_ASSERTION(NS_IsMainThread(), "Call only on main thread"); + if (!mMainThreadFinished || mFinishedNotificationSent) { + return false; + } + + mFinishedNotificationSent = true; + return true; + } + // This state is all initialized on the main thread but // otherwise modified only on the media graph thread. // Buffered data. The start of the buffer corresponds to mBufferStartTime. // Conceptually the buffer contains everything this stream has ever played, // but we forget some prefix of the buffered data to bound the space usage. StreamBuffer mBuffer; // The time when the buffered data could be considered to have started playing. @@ -691,16 +703,17 @@ protected: // True if this stream should be blocked in this phase. bool mBlockInThisPhase; // This state is only used on the main thread. DOMMediaStream* mWrapper; // Main-thread views of state StreamTime mMainThreadCurrentTime; bool mMainThreadFinished; + bool mFinishedNotificationSent; bool mMainThreadDestroyed; // Our media stream graph. null if destroyed on the graph thread. MediaStreamGraphImpl* mGraph; dom::AudioChannel mAudioChannelType; };
--- a/dom/media/webaudio/AudioBufferSourceNode.cpp +++ b/dom/media/webaudio/AudioBufferSourceNode.cpp @@ -557,17 +557,16 @@ AudioBufferSourceNode::AudioBufferSource ChannelInterpretation::Speakers) , mLoopStart(0.0) , mLoopEnd(0.0) // mOffset and mDuration are initialized in Start(). , mPlaybackRate(new AudioParam(this, SendPlaybackRateToStream, 1.0f, "playbackRate")) , mDetune(new AudioParam(this, SendDetuneToStream, 0.0f, "detune")) , mLoop(false) , mStartCalled(false) - , mStopped(false) { AudioBufferSourceNodeEngine* engine = new AudioBufferSourceNodeEngine(this, aContext->Destination()); mStream = aContext->Graph()->CreateAudioNodeStream(engine, MediaStreamGraph::SOURCE_STREAM); engine->SetSourceStream(static_cast<AudioNodeStream*>(mStream.get())); mStream->AddMainThreadListener(this); } AudioBufferSourceNode::~AudioBufferSourceNode() @@ -705,48 +704,45 @@ AudioBufferSourceNode::Stop(double aWhen // We've already stopped and had our stream shut down return; } ns->SetStreamTimeParameter(STOP, Context(), std::max(0.0, aWhen)); } void -AudioBufferSourceNode::NotifyMainThreadStateChanged() +AudioBufferSourceNode::NotifyMainThreadStreamFinished() { - if (mStream->IsFinished()) { - class EndedEventDispatcher final : public nsRunnable + MOZ_ASSERT(mStream->IsFinished()); + + class EndedEventDispatcher final : public nsRunnable + { + public: + explicit EndedEventDispatcher(AudioBufferSourceNode* aNode) + : mNode(aNode) {} + NS_IMETHODIMP Run() override { - public: - explicit EndedEventDispatcher(AudioBufferSourceNode* aNode) - : mNode(aNode) {} - NS_IMETHODIMP Run() override - { - // If it's not safe to run scripts right now, schedule this to run later - if (!nsContentUtils::IsSafeToRunScript()) { - nsContentUtils::AddScriptRunner(this); - return NS_OK; - } - - mNode->DispatchTrustedEvent(NS_LITERAL_STRING("ended")); + // If it's not safe to run scripts right now, schedule this to run later + if (!nsContentUtils::IsSafeToRunScript()) { + nsContentUtils::AddScriptRunner(this); return NS_OK; } - private: - nsRefPtr<AudioBufferSourceNode> mNode; - }; - if (!mStopped) { - // Only dispatch the ended event once - NS_DispatchToMainThread(new EndedEventDispatcher(this)); - mStopped = true; + + mNode->DispatchTrustedEvent(NS_LITERAL_STRING("ended")); + return NS_OK; } + private: + nsRefPtr<AudioBufferSourceNode> mNode; + }; - // Drop the playing reference - // Warning: The below line might delete this. - MarkInactive(); - } + NS_DispatchToMainThread(new EndedEventDispatcher(this)); + + // Drop the playing reference + // Warning: The below line might delete this. + MarkInactive(); } void AudioBufferSourceNode::SendPlaybackRateToStream(AudioNode* aNode) { AudioBufferSourceNode* This = static_cast<AudioBufferSourceNode*>(aNode); SendTimelineParameterToStream(This, PLAYBACKRATE, *This->mPlaybackRate); }
--- a/dom/media/webaudio/AudioBufferSourceNode.h +++ b/dom/media/webaudio/AudioBufferSourceNode.h @@ -89,17 +89,17 @@ public: { mLoopEnd = aEnd; SendLoopParametersToStream(); } void SendDopplerShiftToStream(double aDopplerShift); IMPL_EVENT_HANDLER(ended) - virtual void NotifyMainThreadStateChanged() override; + virtual void NotifyMainThreadStreamFinished() override; virtual const char* NodeType() const override { return "AudioBufferSourceNode"; } virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override; virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override; @@ -142,16 +142,15 @@ private: double mLoopEnd; double mOffset; double mDuration; nsRefPtr<AudioBuffer> mBuffer; nsRefPtr<AudioParam> mPlaybackRate; nsRefPtr<AudioParam> mDetune; bool mLoop; bool mStartCalled; - bool mStopped; }; } } #endif
--- a/dom/media/webaudio/AudioDestinationNode.cpp +++ b/dom/media/webaudio/AudioDestinationNode.cpp @@ -346,17 +346,16 @@ AudioDestinationNode::AudioDestinationNo float aSampleRate) : AudioNode(aContext, aIsOffline ? aNumberOfChannels : 2, ChannelCountMode::Explicit, ChannelInterpretation::Speakers) , mFramesToProduce(aLength) , mAudioChannel(AudioChannel::Normal) , mIsOffline(aIsOffline) - , mHasFinished(false) , mAudioChannelAgentPlaying(false) , mExtraCurrentTime(0) , mExtraCurrentTimeSinceLastStartedBlocking(0) , mExtraCurrentTimeUpdatedSinceLastStableState(false) { bool startWithAudioDriver = true; MediaStreamGraph* graph = aIsOffline ? MediaStreamGraph::CreateNonRealtimeInstance(aSampleRate) : @@ -421,25 +420,24 @@ AudioDestinationNode::DestroyMediaStream MediaStreamGraph* graph = mStream->Graph(); if (graph->IsNonRealtime()) { MediaStreamGraph::DestroyNonRealtimeInstance(graph); } AudioNode::DestroyMediaStream(); } void -AudioDestinationNode::NotifyMainThreadStateChanged() +AudioDestinationNode::NotifyMainThreadStreamFinished() { - if (mStream->IsFinished() && !mHasFinished) { - mHasFinished = true; - if (mIsOffline) { - nsCOMPtr<nsIRunnable> runnable = - NS_NewRunnableMethod(this, &AudioDestinationNode::FireOfflineCompletionEvent); - NS_DispatchToCurrentThread(runnable); - } + MOZ_ASSERT(mStream->IsFinished()); + + if (mIsOffline) { + nsCOMPtr<nsIRunnable> runnable = + NS_NewRunnableMethod(this, &AudioDestinationNode::FireOfflineCompletionEvent); + NS_DispatchToCurrentThread(runnable); } } void AudioDestinationNode::FireOfflineCompletionEvent() { AudioNodeStream* stream = static_cast<AudioNodeStream*>(Stream()); OfflineDestinationNodeEngine* engine =
--- a/dom/media/webaudio/AudioDestinationNode.h +++ b/dom/media/webaudio/AudioDestinationNode.h @@ -59,17 +59,17 @@ public: void OfflineShutdown(); // nsIDOMEventListener - by proxy NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) override; AudioChannel MozAudioChannelType() const; void SetMozAudioChannelType(AudioChannel aValue, ErrorResult& aRv); - virtual void NotifyMainThreadStateChanged() override; + virtual void NotifyMainThreadStreamFinished() override; void FireOfflineCompletionEvent(); // An amount that should be added to the MediaStream's current time to // get the AudioContext.currentTime. double ExtraCurrentTime(); // When aIsOnlyNode is true, this is the only node for the AudioContext. void SetIsOnlyNodeForContext(bool aIsOnlyNode); @@ -104,17 +104,16 @@ private: nsCOMPtr<nsIAudioChannelAgent> mAudioChannelAgent; nsRefPtr<EventProxyHandler> mEventProxyHelper; nsRefPtr<Promise> mOfflineRenderingPromise; // Audio Channel Type. AudioChannel mAudioChannel; bool mIsOffline; - bool mHasFinished; bool mAudioChannelAgentPlaying; TimeStamp mStartedBlockingDueToBeingOnlyNode; double mExtraCurrentTime; double mExtraCurrentTimeSinceLastStartedBlocking; bool mExtraCurrentTimeUpdatedSinceLastStableState; };
--- a/dom/media/webaudio/OscillatorNode.cpp +++ b/dom/media/webaudio/OscillatorNode.cpp @@ -379,17 +379,16 @@ OscillatorNode::OscillatorNode(AudioCont : AudioNode(aContext, 2, ChannelCountMode::Max, ChannelInterpretation::Speakers) , mType(OscillatorType::Sine) , mFrequency(new AudioParam(this, SendFrequencyToStream, 440.0f, "frequency")) , mDetune(new AudioParam(this, SendDetuneToStream, 0.0f, "detune")) , mStartCalled(false) - , mStopped(false) { OscillatorNodeEngine* engine = new OscillatorNodeEngine(this, aContext->Destination()); mStream = aContext->Graph()->CreateAudioNodeStream(engine, MediaStreamGraph::SOURCE_STREAM); engine->SetSourceStream(static_cast<AudioNodeStream*> (mStream.get())); mStream->AddMainThreadListener(this); } OscillatorNode::~OscillatorNode() @@ -507,44 +506,41 @@ OscillatorNode::Stop(double aWhen, Error } // TODO: Perhaps we need to do more here. ns->SetStreamTimeParameter(OscillatorNodeEngine::STOP, Context(), std::max(0.0, aWhen)); } void -OscillatorNode::NotifyMainThreadStateChanged() +OscillatorNode::NotifyMainThreadStreamFinished() { - if (mStream->IsFinished()) { - class EndedEventDispatcher final : public nsRunnable + MOZ_ASSERT(mStream->IsFinished()); + + class EndedEventDispatcher final : public nsRunnable + { + public: + explicit EndedEventDispatcher(OscillatorNode* aNode) + : mNode(aNode) {} + NS_IMETHOD Run() override { - public: - explicit EndedEventDispatcher(OscillatorNode* aNode) - : mNode(aNode) {} - NS_IMETHOD Run() override - { - // If it's not safe to run scripts right now, schedule this to run later - if (!nsContentUtils::IsSafeToRunScript()) { - nsContentUtils::AddScriptRunner(this); - return NS_OK; - } - - mNode->DispatchTrustedEvent(NS_LITERAL_STRING("ended")); + // If it's not safe to run scripts right now, schedule this to run later + if (!nsContentUtils::IsSafeToRunScript()) { + nsContentUtils::AddScriptRunner(this); return NS_OK; } - private: - nsRefPtr<OscillatorNode> mNode; - }; - if (!mStopped) { - // Only dispatch the ended event once - NS_DispatchToMainThread(new EndedEventDispatcher(this)); - mStopped = true; + + mNode->DispatchTrustedEvent(NS_LITERAL_STRING("ended")); + return NS_OK; } + private: + nsRefPtr<OscillatorNode> mNode; + }; - // Drop the playing reference - // Warning: The below line might delete this. - MarkInactive(); - } + NS_DispatchToMainThread(new EndedEventDispatcher(this)); + + // Drop the playing reference + // Warning: The below line might delete this. + MarkInactive(); } } }
--- a/dom/media/webaudio/OscillatorNode.h +++ b/dom/media/webaudio/OscillatorNode.h @@ -73,17 +73,17 @@ public: mPeriodicWave = &aPeriodicWave; // SendTypeToStream will call SendPeriodicWaveToStream for us. mType = OscillatorType::Custom; SendTypeToStream(); } IMPL_EVENT_HANDLER(ended) - virtual void NotifyMainThreadStateChanged() override; + virtual void NotifyMainThreadStreamFinished() override; virtual const char* NodeType() const override { return "OscillatorNode"; } virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override; virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override; @@ -98,16 +98,15 @@ private: void SendPeriodicWaveToStream(); private: OscillatorType mType; nsRefPtr<PeriodicWave> mPeriodicWave; nsRefPtr<AudioParam> mFrequency; nsRefPtr<AudioParam> mDetune; bool mStartCalled; - bool mStopped; }; } } #endif