From f181df10f9bb97c63c99d42633be85464a1690cf Mon Sep 17 00:00:00 2001 From: Jean-Yves Avenard Date: Mon, 3 Aug 2020 08:01:09 +0000 Subject: [PATCH] Bug 1653638 - P2. Use a Controller TaskQueue for running webaudio tasks. r=mjf We can't create a media decoder on a decoder taskqueue, as this could lead to deadlocks should a decoder attempt to dispatch a synchronous runnable. Differential Revision: https://phabricator.services.mozilla.com/D85544 --- dom/media/webaudio/MediaBufferDecoder.cpp | 107 ++++++++++++---------- 1 file changed, 58 insertions(+), 49 deletions(-) diff --git a/dom/media/webaudio/MediaBufferDecoder.cpp b/dom/media/webaudio/MediaBufferDecoder.cpp index e586999a81d8..243c9a93e096 100644 --- a/dom/media/webaudio/MediaBufferDecoder.cpp +++ b/dom/media/webaudio/MediaBufferDecoder.cpp @@ -5,35 +5,37 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "MediaBufferDecoder.h" -#include "mozilla/dom/AudioContextBinding.h" -#include "mozilla/dom/BaseAudioContextBinding.h" -#include "mozilla/dom/DOMException.h" -#include "mozilla/dom/ScriptSettings.h" -#include "mozilla/AbstractThread.h" -#include "mozilla/StaticPrefs_media.h" + #include -#include "nsXPCOMCIDInternal.h" -#include "nsComponentManagerUtils.h" -#include "MediaQueue.h" + +#include "AudioBuffer.h" +#include "AudioContext.h" +#include "AudioNodeEngine.h" #include "BufferMediaResource.h" #include "DecoderTraits.h" -#include "AudioContext.h" -#include "AudioBuffer.h" -#include "js/MemoryFunctions.h" #include "MediaContainerType.h" #include "MediaDataDemuxer.h" -#include "nsContentUtils.h" -#include "nsIScriptObjectPrincipal.h" -#include "nsIScriptError.h" -#include "nsMimeTypes.h" +#include "MediaQueue.h" #include "PDMFactory.h" #include "VideoUtils.h" #include "WebAudioUtils.h" -#include "mozilla/dom/Promise.h" -#include "mozilla/Telemetry.h" +#include "js/MemoryFunctions.h" +#include "mozilla/AbstractThread.h" #include "mozilla/Logging.h" +#include "mozilla/StaticPrefs_media.h" +#include "mozilla/Telemetry.h" +#include "mozilla/dom/AudioContextBinding.h" +#include "mozilla/dom/BaseAudioContextBinding.h" +#include "mozilla/dom/DOMException.h" +#include "mozilla/dom/Promise.h" +#include "mozilla/dom/ScriptSettings.h" +#include "nsComponentManagerUtils.h" +#include "nsContentUtils.h" +#include "nsIScriptError.h" +#include "nsIScriptObjectPrincipal.h" +#include "nsMimeTypes.h" #include "nsPrintfCString.h" -#include "AudioNodeEngine.h" +#include "nsXPCOMCIDInternal.h" namespace mozilla { @@ -96,8 +98,10 @@ class MediaDecodeTask final : public Runnable { MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHOD Run() override; bool Init(); - TaskQueue* PDecoderTaskQueue() { return mPDecoderTaskQueue; } - bool OnPDecoderTaskQueue() { return mPDecoderTaskQueue->IsCurrentThreadIn(); } + TaskQueue* PControllerTaskQueue() { return mPControllerTaskQueue; } + bool OnPControllerTaskQueue() const { + return mPControllerTaskQueue->IsCurrentThreadIn(); + } private: MOZ_CAN_RUN_SCRIPT @@ -154,6 +158,7 @@ class MediaDecodeTask final : public Runnable { } mTrackDemuxer = nullptr; mDemuxer = nullptr; + mPControllerTaskQueue = nullptr; mPDecoderTaskQueue = nullptr; } @@ -164,6 +169,7 @@ class MediaDecodeTask final : public Runnable { const uint32_t mBatchSize; WebAudioDecodeJob& mDecodeJob; PhaseEnum mPhase; + RefPtr mPControllerTaskQueue; RefPtr mPDecoderTaskQueue; RefPtr mDemuxer; RefPtr mTrackDemuxer; @@ -199,6 +205,9 @@ bool MediaDecodeTask::Init() { mMainThread = mDecodeJob.mContext->GetOwnerGlobal()->AbstractMainThreadFor( TaskCategory::Other); + mPControllerTaskQueue = + new TaskQueue(GetMediaThreadPool(MediaThreadType::CONTROLLER), + "MediaBufferDecoder::mPControllerTaskQueue"); mPDecoderTaskQueue = new TaskQueue(GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER), "MediaBufferDecoder::mPDecoderTaskQueue"); @@ -232,16 +241,15 @@ class AutoResampler final { }; void MediaDecodeTask::Decode() { - MOZ_ASSERT(!NS_IsMainThread()); - MOZ_ASSERT(OnPDecoderTaskQueue()); + MOZ_ASSERT(OnPControllerTaskQueue()); - mDemuxer->Init()->Then(PDecoderTaskQueue(), __func__, this, + mDemuxer->Init()->Then(PControllerTaskQueue(), __func__, this, &MediaDecodeTask::OnInitDemuxerCompleted, &MediaDecodeTask::OnInitDemuxerFailed); } void MediaDecodeTask::OnInitDemuxerCompleted() { - MOZ_ASSERT(OnPDecoderTaskQueue()); + MOZ_ASSERT(OnPControllerTaskQueue()); if (!!mDemuxer->GetNumberTracks(TrackInfo::kAudioTrack)) { mTrackDemuxer = mDemuxer->GetTrackDemuxer(TrackInfo::kAudioTrack, 0); @@ -269,14 +277,14 @@ void MediaDecodeTask::OnInitDemuxerCompleted() { } void MediaDecodeTask::OnInitDemuxerFailed(const MediaResult& aError) { - MOZ_ASSERT(OnPDecoderTaskQueue()); + MOZ_ASSERT(OnPControllerTaskQueue()); LOG("MediaDecodeTask: Could not initialize the demuxer."); ReportFailureOnMainThread(WebAudioDecodeJob::InvalidContent); } MediaResult MediaDecodeTask::CreateDecoder(const AudioInfo& info) { - MOZ_ASSERT(OnPDecoderTaskQueue()); + MOZ_ASSERT(OnPControllerTaskQueue()); RefPtr pdm = new PDMFactory(); // result may not be updated by PDMFactory::CreateDecoder, as such it must be @@ -298,21 +306,21 @@ MediaResult MediaDecodeTask::CreateDecoder(const AudioInfo& info) { } void MediaDecodeTask::InitDecoder() { - MOZ_ASSERT(OnPDecoderTaskQueue()); + MOZ_ASSERT(OnPControllerTaskQueue()); - mDecoder->Init()->Then(PDecoderTaskQueue(), __func__, this, + mDecoder->Init()->Then(PControllerTaskQueue(), __func__, this, &MediaDecodeTask::OnInitDecoderCompleted, &MediaDecodeTask::OnInitDecoderFailed); } void MediaDecodeTask::OnInitDecoderCompleted() { - MOZ_ASSERT(OnPDecoderTaskQueue()); + MOZ_ASSERT(OnPControllerTaskQueue()); DoDemux(); } void MediaDecodeTask::OnInitDecoderFailed() { - MOZ_ASSERT(OnPDecoderTaskQueue()); + MOZ_ASSERT(OnPControllerTaskQueue()); ShutdownDecoder(); LOG("MediaDecodeTask: Could not initialize the decoder"); @@ -320,17 +328,17 @@ void MediaDecodeTask::OnInitDecoderFailed() { } void MediaDecodeTask::DoDemux() { - MOZ_ASSERT(OnPDecoderTaskQueue()); + MOZ_ASSERT(OnPControllerTaskQueue()); mTrackDemuxer->GetSamples(mBatchSize) - ->Then(PDecoderTaskQueue(), __func__, this, + ->Then(PControllerTaskQueue(), __func__, this, &MediaDecodeTask::OnAudioDemuxCompleted, &MediaDecodeTask::OnAudioDemuxFailed); } void MediaDecodeTask::OnAudioDemuxCompleted( RefPtr aSamples) { - MOZ_ASSERT(OnPDecoderTaskQueue()); + MOZ_ASSERT(OnPControllerTaskQueue()); mRawSamples.AppendElements(aSamples->GetSamples()); @@ -338,7 +346,7 @@ void MediaDecodeTask::OnAudioDemuxCompleted( } void MediaDecodeTask::OnAudioDemuxFailed(const MediaResult& aError) { - MOZ_ASSERT(OnPDecoderTaskQueue()); + MOZ_ASSERT(OnPControllerTaskQueue()); if (aError.Code() == NS_ERROR_DOM_MEDIA_END_OF_STREAM) { DoDecode(); @@ -350,7 +358,7 @@ void MediaDecodeTask::OnAudioDemuxFailed(const MediaResult& aError) { } void MediaDecodeTask::DoDecode() { - MOZ_ASSERT(OnPDecoderTaskQueue()); + MOZ_ASSERT(OnPControllerTaskQueue()); if (mRawSamples.IsEmpty()) { DoDrain(); @@ -366,7 +374,7 @@ void MediaDecodeTask::DoDecode() { } mDecoder->DecodeBatch(std::move(rawSampleBatch)) - ->Then(PDecoderTaskQueue(), __func__, this, + ->Then(PControllerTaskQueue(), __func__, this, &MediaDecodeTask::OnAudioDecodeCompleted, &MediaDecodeTask::OnAudioDecodeFailed); @@ -374,7 +382,7 @@ void MediaDecodeTask::DoDecode() { } else { RefPtr sample = std::move(mRawSamples[0]); - mDecoder->Decode(sample)->Then(PDecoderTaskQueue(), __func__, this, + mDecoder->Decode(sample)->Then(PControllerTaskQueue(), __func__, this, &MediaDecodeTask::OnAudioDecodeCompleted, &MediaDecodeTask::OnAudioDecodeFailed); @@ -384,7 +392,7 @@ void MediaDecodeTask::DoDecode() { void MediaDecodeTask::OnAudioDecodeCompleted( MediaDataDecoder::DecodedData&& aResults) { - MOZ_ASSERT(OnPDecoderTaskQueue()); + MOZ_ASSERT(OnPControllerTaskQueue()); for (auto&& sample : aResults) { MOZ_ASSERT(sample->mType == MediaData::Type::AUDIO_DATA); @@ -400,7 +408,7 @@ void MediaDecodeTask::OnAudioDecodeCompleted( } void MediaDecodeTask::OnAudioDecodeFailed(const MediaResult& aError) { - MOZ_ASSERT(OnPDecoderTaskQueue()); + MOZ_ASSERT(OnPControllerTaskQueue()); ShutdownDecoder(); LOG("MediaDecodeTask: decode audio failed."); @@ -408,16 +416,16 @@ void MediaDecodeTask::OnAudioDecodeFailed(const MediaResult& aError) { } void MediaDecodeTask::DoDrain() { - MOZ_ASSERT(OnPDecoderTaskQueue()); + MOZ_ASSERT(OnPControllerTaskQueue()); - mDecoder->Drain()->Then(PDecoderTaskQueue(), __func__, this, + mDecoder->Drain()->Then(PControllerTaskQueue(), __func__, this, &MediaDecodeTask::OnAudioDrainCompleted, &MediaDecodeTask::OnAudioDrainFailed); } void MediaDecodeTask::OnAudioDrainCompleted( MediaDataDecoder::DecodedData&& aResults) { - MOZ_ASSERT(OnPDecoderTaskQueue()); + MOZ_ASSERT(OnPControllerTaskQueue()); if (aResults.IsEmpty()) { FinishDecode(); @@ -434,7 +442,7 @@ void MediaDecodeTask::OnAudioDrainCompleted( } void MediaDecodeTask::OnAudioDrainFailed(const MediaResult& aError) { - MOZ_ASSERT(OnPDecoderTaskQueue()); + MOZ_ASSERT(OnPControllerTaskQueue()); ShutdownDecoder(); LOG("MediaDecodeTask: Drain audio failed"); @@ -442,7 +450,7 @@ void MediaDecodeTask::OnAudioDrainFailed(const MediaResult& aError) { } void MediaDecodeTask::ShutdownDecoder() { - MOZ_ASSERT(OnPDecoderTaskQueue()); + MOZ_ASSERT(OnPControllerTaskQueue()); if (!mDecoder) { return; @@ -454,7 +462,7 @@ void MediaDecodeTask::ShutdownDecoder() { } void MediaDecodeTask::FinishDecode() { - MOZ_ASSERT(OnPDecoderTaskQueue()); + MOZ_ASSERT(OnPControllerTaskQueue()); ShutdownDecoder(); @@ -649,10 +657,11 @@ void AsyncDecodeWebAudio(const char* aContentType, uint8_t* aBuffer, aDecodeJob.mContext->Dispatch(event.forget()); } else { // If we did this without a temporary: - // task->PDecoderTaskQueue()->Dispatch(task.forget()) - // we might evaluate the task.forget() before calling PDecoderTaskQueue(). + // task->PControllerTaskQueue()->Dispatch(task.forget()) + // we might evaluate the task.forget() before calling + // OnPControllerTaskQueue(). // Enforce a non-crashy order-of-operations. - TaskQueue* taskQueue = task->PDecoderTaskQueue(); + TaskQueue* taskQueue = task->PControllerTaskQueue(); nsresult rv = taskQueue->Dispatch(task.forget()); MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv)); Unused << rv;