diff --git a/dom/media/AbstractThread.cpp b/dom/media/AbstractThread.cpp index 7be75d83f0c5..5437f46e1f63 100644 --- a/dom/media/AbstractThread.cpp +++ b/dom/media/AbstractThread.cpp @@ -34,6 +34,21 @@ AbstractThreadImpl::IsCurrentThreadIn() return in; } +void +AbstractThread::MaybeTailDispatch(already_AddRefed aRunnable, + bool aAssertDispatchSuccess) +{ + MediaTaskQueue* currentQueue = MediaTaskQueue::GetCurrentQueue(); + if (currentQueue && currentQueue->RequiresTailDispatch()) { + currentQueue->TailDispatcher().AddTask(this, Move(aRunnable), aAssertDispatchSuccess); + } else { + nsresult rv = Dispatch(Move(aRunnable)); + MOZ_DIAGNOSTIC_ASSERT(!aAssertDispatchSuccess || NS_SUCCEEDED(rv)); + unused << rv; + } +} + + AbstractThread* AbstractThread::MainThread() { diff --git a/dom/media/AbstractThread.h b/dom/media/AbstractThread.h index f060f686bf50..9b9ad4c9f669 100644 --- a/dom/media/AbstractThread.h +++ b/dom/media/AbstractThread.h @@ -35,6 +35,11 @@ public: virtual nsresult Dispatch(already_AddRefed aRunnable) = 0; virtual bool IsCurrentThreadIn() = 0; + // Convenience method for dispatching a runnable when we may be running on + // a thread that requires runnables to be dispatched with tail dispatch. + void MaybeTailDispatch(already_AddRefed aRunnable, + bool aAssertDispatchSuccess = true); + template static AbstractThread* Create(TargetType* aTarget); // Convenience method for getting an AbstractThread for the main thread. diff --git a/dom/media/MediaDecoderStateMachine.cpp b/dom/media/MediaDecoderStateMachine.cpp index e4ef68838751..90ea4f074800 100644 --- a/dom/media/MediaDecoderStateMachine.cpp +++ b/dom/media/MediaDecoderStateMachine.cpp @@ -47,6 +47,8 @@ using namespace mozilla::layers; using namespace mozilla::dom; using namespace mozilla::gfx; +#define NS_DispatchToMainThread(...) CompileError_UseTailDispatchInstead + // avoid redefined macro in unified build #undef DECODER_LOG #undef VERBOSE_LOG @@ -252,7 +254,7 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder, // Set up our task queue. RefPtr pool(GetMediaThreadPool()); MOZ_DIAGNOSTIC_ASSERT(pool); - mTaskQueue = new MediaTaskQueue(pool.forget()); + mTaskQueue = new MediaTaskQueue(pool.forget(), /* aAssertTailDispatch = */ true); static bool sPrefCacheInit = false; if (!sPrefCacheInit) { @@ -862,10 +864,12 @@ MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType, MOZ_ASSERT(mReader->IsWaitForDataSupported(), "Readers that send WAITING_FOR_DATA need to implement WaitForData"); WaitRequestRef(aType).Begin(ProxyMediaCall(DecodeTaskQueue(), mReader.get(), __func__, - &MediaDecoderReader::WaitForData, aType) + &MediaDecoderReader::WaitForData, aType, + TailDispatcher()) ->RefableThen(TaskQueue(), __func__, this, &MediaDecoderStateMachine::OnWaitForDataResolved, - &MediaDecoderStateMachine::OnWaitForDataRejected)); + &MediaDecoderStateMachine::OnWaitForDataRejected, + TailDispatcher())); return; } @@ -1083,12 +1087,9 @@ MediaDecoderStateMachine::CheckIfSeekComplete() if (audioSeekComplete && videoSeekComplete) { mDecodeToSeekTarget = false; - RefPtr task( + nsCOMPtr task( NS_NewRunnableMethod(this, &MediaDecoderStateMachine::SeekCompleted)); - nsresult rv = TaskQueue()->Dispatch(task); - if (NS_FAILED(rv)) { - DecodeError(); - } + TailDispatch(TaskQueue(), task.forget()); } } @@ -1229,7 +1230,7 @@ void MediaDecoderStateMachine::UpdatePlaybackPositionInternal(int64_t aTime) mEndTime = aTime; nsCOMPtr event = NS_NewRunnableMethod(mDecoder, &MediaDecoder::DurationChanged); - NS_DispatchToMainThread(event); + TailDispatch(AbstractThread::MainThread(), event.forget()); } } @@ -1246,7 +1247,7 @@ void MediaDecoderStateMachine::UpdatePlaybackPosition(int64_t aTime) mDecoder, &MediaDecoder::PlaybackPositionChanged, MediaDecoderEventVisibility::Observable); - NS_DispatchToMainThread(event); + TailDispatch(AbstractThread::MainThread(), event.forget()); } mMetadataManager.DispatchMetadataIfNeeded(mDecoder, aTime); @@ -1409,7 +1410,7 @@ void MediaDecoderStateMachine::SetDuration(int64_t aDuration) // Queue seek to new end position. nsCOMPtr task = new SeekRunnable(mDecoder, double(mEndTime) / USECS_PER_S); - NS_DispatchToMainThread(task); + AbstractThread::MainThread()->MaybeTailDispatch(task.forget()); } } } @@ -1423,7 +1424,7 @@ void MediaDecoderStateMachine::UpdateEstimatedDuration(int64_t aDuration) SetDuration(aDuration); nsCOMPtr event = NS_NewRunnableMethod(mDecoder, &MediaDecoder::DurationChanged); - NS_DispatchToMainThread(event); + AbstractThread::MainThread()->MaybeTailDispatch(event.forget()); } } @@ -1486,8 +1487,8 @@ void MediaDecoderStateMachine::SetDormant(bool aDormant) // back to MediaDecoder when we come out of dormant? nsRefPtr unused = mQueuedSeek.mPromise.Ensure(__func__); } - mPendingSeek.RejectIfExists(__func__); - mCurrentSeek.RejectIfExists(__func__); + mPendingSeek.RejectIfExists(__func__, TailDispatcher()); + mCurrentSeek.RejectIfExists(__func__, TailDispatcher()); SetState(DECODER_STATE_DORMANT); if (IsPlaying()) { StopPlayback(); @@ -1501,9 +1502,8 @@ void MediaDecoderStateMachine::SetDormant(bool aDormant) // that run after ResetDecode are supposed to run with a clean slate. We rely // on that in other places (i.e. seeking), so it seems reasonable to rely on // it here as well. - DebugOnly rv = DecodeTaskQueue()->Dispatch( - NS_NewRunnableMethod(mReader, &MediaDecoderReader::ReleaseMediaResources)); - MOZ_ASSERT(NS_SUCCEEDED(rv)); + nsCOMPtr r = NS_NewRunnableMethod(mReader, &MediaDecoderReader::ReleaseMediaResources); + TailDispatch(DecodeTaskQueue(), r.forget()); // There's now no possibility of mPendingWakeDecoder being needed again. Revoke it. mPendingWakeDecoder = nullptr; mDecoder->GetReentrantMonitor().NotifyAll(); @@ -1672,12 +1672,12 @@ MediaDecoderStateMachine::Seek(SeekTarget aTarget) if (mState < DECODER_STATE_DECODING) { DECODER_LOG("Seek() Not Enough Data to continue at this stage, queuing seek"); - mQueuedSeek.RejectIfExists(__func__); + mQueuedSeek.RejectIfExists(__func__, TailDispatcher()); mQueuedSeek.mTarget = aTarget; return mQueuedSeek.mPromise.Ensure(__func__); } - mQueuedSeek.RejectIfExists(__func__); - mPendingSeek.RejectIfExists(__func__); + mQueuedSeek.RejectIfExists(__func__, TailDispatcher()); + mPendingSeek.RejectIfExists(__func__, TailDispatcher()); mPendingSeek.mTarget = aTarget; DECODER_LOG("Changed state to SEEKING (to %lld)", mPendingSeek.mTarget.mTime); @@ -1722,10 +1722,9 @@ MediaDecoderStateMachine::EnqueueDecodeFirstFrameTask() AssertCurrentThreadInMonitor(); MOZ_ASSERT(mState == DECODER_STATE_DECODING_FIRSTFRAME); - RefPtr task( + nsCOMPtr task( NS_NewRunnableMethod(this, &MediaDecoderStateMachine::CallDecodeFirstFrame)); - nsresult rv = TaskQueue()->Dispatch(task); - NS_ENSURE_SUCCESS(rv, rv); + TailDispatch(TaskQueue(), task.forget()); return NS_OK; } @@ -1797,12 +1796,9 @@ MediaDecoderStateMachine::DispatchDecodeTasksIfNeeded() DECODER_LOG("Dispatching SetReaderIdle() audioQueue=%lld videoQueue=%lld", GetDecodedAudioDuration(), VideoQueue().Duration()); - RefPtr event = NS_NewRunnableMethod( + nsCOMPtr task = NS_NewRunnableMethod( this, &MediaDecoderStateMachine::SetReaderIdle); - nsresult rv = DecodeTaskQueue()->Dispatch(event.forget()); - if (NS_FAILED(rv) && !IsShutdown()) { - DECODER_WARN("Failed to dispatch event to set decoder idle state"); - } + TailDispatch(DecodeTaskQueue(), task.forget()); } } @@ -1812,7 +1808,7 @@ MediaDecoderStateMachine::InitiateSeek() MOZ_ASSERT(OnTaskQueue()); AssertCurrentThreadInMonitor(); - mCurrentSeek.RejectIfExists(__func__); + mCurrentSeek.RejectIfExists(__func__, TailDispatcher()); mCurrentSeek.Steal(mPendingSeek); // Bound the seek time to be inside the media range. @@ -1836,7 +1832,7 @@ MediaDecoderStateMachine::InitiateSeek() &MediaDecoder::RecreateDecodedStream, seekTime - mStartTime, nullptr); - NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); + TailDispatch(AbstractThread::MainThread(), event.forget()); } mDropAudioUntilNextDiscontinuity = HasAudio(); @@ -1859,7 +1855,7 @@ MediaDecoderStateMachine::InitiateSeek() mDecoder, &MediaDecoder::SeekingStarted, mCurrentSeek.mTarget.mEventVisibility); - NS_DispatchToMainThread(startEvent, NS_DISPATCH_NORMAL); + TailDispatch(AbstractThread::MainThread(), startEvent.forget()); // Reset our state machine and decoding pipeline before seeking. Reset(); @@ -1867,10 +1863,11 @@ MediaDecoderStateMachine::InitiateSeek() // Do the seek. mSeekRequest.Begin(ProxyMediaCall(DecodeTaskQueue(), mReader.get(), __func__, &MediaDecoderReader::Seek, mCurrentSeek.mTarget.mTime, - GetEndTime()) + GetEndTime(), TailDispatcher()) ->RefableThen(TaskQueue(), __func__, this, &MediaDecoderStateMachine::OnSeekCompleted, - &MediaDecoderStateMachine::OnSeekFailed)); + &MediaDecoderStateMachine::OnSeekFailed, + TailDispatcher())); } nsresult @@ -1915,10 +1912,12 @@ MediaDecoderStateMachine::EnsureAudioDecodeTaskQueued() AudioQueue().GetSize(), mReader->SizeOfAudioQueueInFrames()); mAudioDataRequest.Begin(ProxyMediaCall(DecodeTaskQueue(), mReader.get(), - __func__, &MediaDecoderReader::RequestAudioData) + __func__, &MediaDecoderReader::RequestAudioData, + TailDispatcher()) ->RefableThen(TaskQueue(), __func__, this, &MediaDecoderStateMachine::OnAudioDecoded, - &MediaDecoderStateMachine::OnAudioNotDecoded)); + &MediaDecoderStateMachine::OnAudioNotDecoded, + TailDispatcher())); return NS_OK; } @@ -1975,10 +1974,11 @@ MediaDecoderStateMachine::EnsureVideoDecodeTaskQueued() mVideoDataRequest.Begin(ProxyMediaCall(DecodeTaskQueue(), mReader.get(), __func__, &MediaDecoderReader::RequestVideoData, - skipToNextKeyFrame, currentTime) + skipToNextKeyFrame, currentTime, TailDispatcher()) ->RefableThen(TaskQueue(), __func__, this, &MediaDecoderStateMachine::OnVideoDecoded, - &MediaDecoderStateMachine::OnVideoNotDecoded)); + &MediaDecoderStateMachine::OnVideoNotDecoded, + TailDispatcher())); return NS_OK; } @@ -2113,7 +2113,7 @@ MediaDecoderStateMachine::DecodeError() // machine. nsCOMPtr event = NS_NewRunnableMethod(mDecoder, &MediaDecoder::DecodeError); - NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); + TailDispatch(AbstractThread::MainThread(), event.forget()); } void @@ -2184,7 +2184,7 @@ MediaDecoderStateMachine::EnqueueLoadedMetadataEvent() MediaDecoderEventVisibility::Observable; nsCOMPtr metadataLoadedEvent = new MetadataEventRunner(mDecoder, info, mMetadataTags, visibility); - NS_DispatchToMainThread(metadataLoadedEvent, NS_DISPATCH_NORMAL); + TailDispatch(AbstractThread::MainThread(), metadataLoadedEvent.forget()); mSentLoadedMetadataEvent = true; } @@ -2199,7 +2199,7 @@ MediaDecoderStateMachine::EnqueueFirstFrameLoadedEvent() MediaDecoderEventVisibility::Observable; nsCOMPtr event = new FirstFrameLoadedEventRunner(mDecoder, info, visibility); - NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); + TailDispatch(AbstractThread::MainThread(), event.forget()); mSentFirstFrameLoadedEvent = true; } @@ -2250,18 +2250,22 @@ MediaDecoderStateMachine::DecodeFirstFrame() } else { if (HasAudio()) { mAudioDataRequest.Begin(ProxyMediaCall(DecodeTaskQueue(), mReader.get(), - __func__, &MediaDecoderReader::RequestAudioData) + __func__, &MediaDecoderReader::RequestAudioData, + TailDispatcher()) ->RefableThen(TaskQueue(), __func__, this, &MediaDecoderStateMachine::OnAudioDecoded, - &MediaDecoderStateMachine::OnAudioNotDecoded)); + &MediaDecoderStateMachine::OnAudioNotDecoded, + TailDispatcher())); } if (HasVideo()) { mVideoDecodeStartTime = TimeStamp::Now(); mVideoDataRequest.Begin(ProxyMediaCall(DecodeTaskQueue(), mReader.get(), - __func__, &MediaDecoderReader::RequestVideoData, false, int64_t(0)) + __func__, &MediaDecoderReader::RequestVideoData, false, + int64_t(0), TailDispatcher()) ->RefableThen(TaskQueue(), __func__, this, &MediaDecoderStateMachine::OnVideoDecoded, - &MediaDecoderStateMachine::OnVideoNotDecoded)); + &MediaDecoderStateMachine::OnVideoNotDecoded, + TailDispatcher())); } } @@ -2443,7 +2447,7 @@ MediaDecoderStateMachine::SeekCompleted() // if we need to buffer after the seek. mQuickBuffering = false; - mCurrentSeek.Resolve(mState == DECODER_STATE_COMPLETED, __func__); + mCurrentSeek.Resolve(mState == DECODER_STATE_COMPLETED, __func__, TailDispatcher()); ScheduleStateMachine(); if (video) { @@ -2451,7 +2455,7 @@ MediaDecoderStateMachine::SeekCompleted() RenderVideoFrame(video, TimeStamp::Now()); nsCOMPtr event = NS_NewRunnableMethod(mDecoder, &MediaDecoder::Invalidate); - NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); + TailDispatch(AbstractThread::MainThread(), event.forget()); } } @@ -2524,7 +2528,8 @@ MediaDecoderStateMachine::FinishShutdown() TaskQueue()->BeginShutdown()->Then(AbstractThread::MainThread(), __func__, disposer.get(), &DecoderDisposer::OnTaskQueueShutdown, - &DecoderDisposer::OnTaskQueueShutdown); + &DecoderDisposer::OnTaskQueueShutdown, + TailDispatcher()); } nsresult MediaDecoderStateMachine::RunStateMachine() @@ -2550,9 +2555,9 @@ nsresult MediaDecoderStateMachine::RunStateMachine() } case DECODER_STATE_SHUTDOWN: { - mQueuedSeek.RejectIfExists(__func__); - mPendingSeek.RejectIfExists(__func__); - mCurrentSeek.RejectIfExists(__func__); + mQueuedSeek.RejectIfExists(__func__, TailDispatcher()); + mPendingSeek.RejectIfExists(__func__, TailDispatcher()); + mCurrentSeek.RejectIfExists(__func__, TailDispatcher()); if (IsPlaying()) { StopPlayback(); @@ -2562,10 +2567,9 @@ nsresult MediaDecoderStateMachine::RunStateMachine() // Put a task in the decode queue to shutdown the reader. // the queue to spin down. - RefPtr task; - task = NS_NewRunnableMethod(this, &MediaDecoderStateMachine::ShutdownReader); - DebugOnly rv = DecodeTaskQueue()->Dispatch(task); - MOZ_ASSERT(NS_SUCCEEDED(rv)); + nsCOMPtr task + = NS_NewRunnableMethod(this, &MediaDecoderStateMachine::ShutdownReader); + TailDispatch(DecodeTaskQueue(), task.forget()); DECODER_LOG("Shutdown started"); return NS_OK; @@ -2590,10 +2594,11 @@ nsresult MediaDecoderStateMachine::RunStateMachine() if (!mMetadataRequest.Exists()) { DECODER_LOG("Dispatching CallReadMetadata"); mMetadataRequest.Begin(ProxyMediaCall(DecodeTaskQueue(), mReader.get(), __func__, - &MediaDecoderReader::CallReadMetadata) + &MediaDecoderReader::CallReadMetadata, TailDispatcher()) ->RefableThen(TaskQueue(), __func__, this, &MediaDecoderStateMachine::OnMetadataRead, - &MediaDecoderStateMachine::OnMetadataNotRead)); + &MediaDecoderStateMachine::OnMetadataNotRead, + TailDispatcher())); } return NS_OK; @@ -2715,7 +2720,7 @@ nsresult MediaDecoderStateMachine::RunStateMachine() nsCOMPtr event = NS_NewRunnableMethod(mDecoder, &MediaDecoder::PlaybackEnded); - NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); + TailDispatch(AbstractThread::MainThread(), event.forget()); mSentPlaybackEndedEvent = true; } @@ -2767,9 +2772,9 @@ MediaDecoderStateMachine::Reset() mVideoWaitRequest.DisconnectIfExists(); mSeekRequest.DisconnectIfExists(); - RefPtr resetTask = + nsCOMPtr resetTask = NS_NewRunnableMethod(mReader, &MediaDecoderReader::ResetDecode); - DecodeTaskQueue()->Dispatch(resetTask); + TailDispatch(DecodeTaskQueue(), resetTask.forget()); } void MediaDecoderStateMachine::RenderVideoFrame(VideoData* aData, @@ -2799,7 +2804,9 @@ void MediaDecoderStateMachine::RenderVideoFrame(VideoData* aData, mReader->VideoIsHardwareAccelerated() && frameStats.GetPresentedFrames() > 30 && mCorruptFrames.mean() >= 1 /* 10% */) { - DecodeTaskQueue()->Dispatch(NS_NewRunnableMethod(mReader, &MediaDecoderReader::DisableHardwareAcceleration)); + nsCOMPtr task = + NS_NewRunnableMethod(mReader, &MediaDecoderReader::DisableHardwareAcceleration); + TailDispatch(DecodeTaskQueue(), task.forget()); mDisabledHardwareAcceleration = true; } } else { @@ -3202,7 +3209,7 @@ void MediaDecoderStateMachine::UpdateReadyState() { */ nsCOMPtr event; event = NS_NewRunnableMethod(mDecoder, &MediaDecoder::UpdateReadyStateForData); - NS_DispatchToMainThread(event); + AbstractThread::MainThread()->MaybeTailDispatch(event.forget()); } bool MediaDecoderStateMachine::JustExitedQuickBuffering() @@ -3293,11 +3300,9 @@ MediaDecoderStateMachine::ScheduleStateMachine() { } mDispatchedStateMachine = true; - RefPtr task = + nsCOMPtr task = NS_NewRunnableMethod(this, &MediaDecoderStateMachine::RunStateMachine); - nsresult rv = TaskQueue()->Dispatch(task); - MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv)); - (void) rv; + TaskQueue()->MaybeTailDispatch(task.forget()); } void @@ -3476,3 +3481,5 @@ uint32_t MediaDecoderStateMachine::GetAmpleVideoFrames() const #undef VERBOSE_LOG #undef DECODER_WARN #undef DECODER_WARN_HELPER + +#undef NS_DispatchToMainThread diff --git a/dom/media/MediaDecoderStateMachine.h b/dom/media/MediaDecoderStateMachine.h index 1ce5b802154d..7b85f694bfae 100644 --- a/dom/media/MediaDecoderStateMachine.h +++ b/dom/media/MediaDecoderStateMachine.h @@ -331,6 +331,22 @@ public: // Returns the state machine task queue. MediaTaskQueue* TaskQueue() const { return mTaskQueue; } + // Returns the tail dispatcher associated with TaskQueue(), which will fire + // its tasks when the current task completes. May only be called when running + // in TaskQueue(). + TaskDispatcher& TailDispatcher() + { + MOZ_ASSERT(OnTaskQueue()); + return TaskQueue()->TailDispatcher(); + } + + // Convenience method to perform a tail dispatch. + void TailDispatch(AbstractThread* aThread, + already_AddRefed aTask) + { + TailDispatcher().AddTask(aThread, Move(aTask)); + } + // Calls ScheduleStateMachine() after taking the decoder lock. Also // notifies the decoder thread in case it's waiting on the decoder lock. void ScheduleStateMachineWithLockAndWakeDecoder(); @@ -811,7 +827,7 @@ public: mRequest.Begin(mMediaTimer->WaitUntil(mTarget, __func__)->RefableThen( mSelf->TaskQueue(), __func__, mSelf, &MediaDecoderStateMachine::OnDelayedSchedule, - &MediaDecoderStateMachine::NotReached)); + &MediaDecoderStateMachine::NotReached, mSelf->TailDispatcher())); } void CompleteRequest() @@ -901,17 +917,17 @@ public: return mTarget.IsValid(); } - void Resolve(bool aAtEnd, const char* aCallSite) + void Resolve(bool aAtEnd, const char* aCallSite, TaskDispatcher& aDispatcher) { mTarget.Reset(); MediaDecoder::SeekResolveValue val(aAtEnd, mTarget.mEventVisibility); - mPromise.Resolve(val, aCallSite); + mPromise.Resolve(val, aCallSite, aDispatcher); } - void RejectIfExists(const char* aCallSite) + void RejectIfExists(const char* aCallSite, TaskDispatcher& aDispatcher) { mTarget.Reset(); - mPromise.RejectIfExists(true, aCallSite); + mPromise.RejectIfExists(true, aCallSite, aDispatcher); } ~SeekJob() diff --git a/dom/media/MediaQueue.h b/dom/media/MediaQueue.h index c4aa178eadc4..6b292daa7412 100644 --- a/dom/media/MediaQueue.h +++ b/dom/media/MediaQueue.h @@ -176,7 +176,7 @@ private: , mTarget(aOther.mTarget) { } - RefPtr mRunnable; + nsCOMPtr mRunnable; RefPtr mTarget; }; @@ -185,7 +185,8 @@ private: void NotifyPopListeners() { for (uint32_t i = 0; i < mPopListeners.Length(); i++) { Listener& l = mPopListeners[i]; - l.mTarget->Dispatch(l.mRunnable); + nsCOMPtr r = l.mRunnable; + l.mTarget->MaybeTailDispatch(r.forget()); } } diff --git a/dom/media/MediaStreamGraph.cpp b/dom/media/MediaStreamGraph.cpp index aa2dcb90b730..83614b3dc88e 100644 --- a/dom/media/MediaStreamGraph.cpp +++ b/dom/media/MediaStreamGraph.cpp @@ -278,7 +278,11 @@ MediaStreamGraphImpl::UpdateBufferSufficiencyState(SourceMediaStream* aStream) } for (uint32_t i = 0; i < runnables.Length(); ++i) { - runnables[i].mTarget->Dispatch(runnables[i].mRunnable); + // This dispatch was observed to fail in test_video_dimensions.html on + // win8 64 debug when invoked from noop_resampler::fill on the cubeb audio + // thread. + nsCOMPtr r = runnables[i].mRunnable; + runnables[i].mTarget->MaybeTailDispatch(r.forget(), /* aAssertDispatchSuccess = */ false); } } @@ -2501,7 +2505,8 @@ SourceMediaStream::DispatchWhenNotEnoughBuffered(TrackID aID, MutexAutoLock lock(mMutex); TrackData* data = FindDataForTrack(aID); if (!data) { - aSignalQueue->Dispatch(aSignalRunnable); + nsCOMPtr r = aSignalRunnable; + aSignalQueue->MaybeTailDispatch(r.forget()); return; } @@ -2510,7 +2515,8 @@ SourceMediaStream::DispatchWhenNotEnoughBuffered(TrackID aID, data->mDispatchWhenNotEnough.AppendElement()->Init(aSignalQueue, aSignalRunnable); } } else { - aSignalQueue->Dispatch(aSignalRunnable); + nsCOMPtr r = aSignalRunnable; + aSignalQueue->MaybeTailDispatch(r.forget()); } } diff --git a/dom/media/MediaStreamGraph.h b/dom/media/MediaStreamGraph.h index 2992ccf910b9..efd07611e7c9 100644 --- a/dom/media/MediaStreamGraph.h +++ b/dom/media/MediaStreamGraph.h @@ -855,7 +855,7 @@ protected: } nsRefPtr mTarget; - RefPtr mRunnable; + nsCOMPtr mRunnable; }; enum TrackCommands { TRACK_CREATE = MediaStreamListener::TRACK_EVENT_CREATED,