author | Razvan Maries <rmaries@mozilla.com> |
Thu, 09 Jul 2020 10:33:45 +0300 | |
changeset 539533 | b8fad3d28fcdb62558ce1766933bd47cb2343303 |
parent 539532 | 03e70cb012757fe65c35ac2d27654dff44db606f |
child 539534 | c245b8a73f2a235892ac706082f3443b387d3bc9 |
push id | 37582 |
push user | apavel@mozilla.com |
push date | Thu, 09 Jul 2020 15:42:10 +0000 |
treeherder | mozilla-central@ccd521ebc464 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
bugs | 1650996, 1649974 |
milestone | 80.0a1 |
backs out | 8f8174ba409dd3bb236f0bebd6ba9279ad3bf65f 374598f9c37a0189ddb2f0baffbf1897e346602c 236757acc073d19d42b3a32a6577094ceaa4c6ca 89d5cabfa2dfe6c31cc30d4d942949d3033480e6 6e475ddbd18c4fdbcdf990a75d6a07fa86fcd5b5 |
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/build/clang-plugin/ThreadAllows.txt +++ b/build/clang-plugin/ThreadAllows.txt @@ -60,16 +60,17 @@ Permission PlayEventSound ProcessHangMon ProfSymbolTable ProfilerChild ProxyResolution RemoteLzyStream RWLockTester RacingServMan +RemVidChild Sandbox Testing SaveScripts Socket Thread SpeechWorker SpinEventLoop StressRunner SuicideManager SuicideThread
--- a/dom/media/ipc/GpuDecoderModule.cpp +++ b/dom/media/ipc/GpuDecoderModule.cpp @@ -1,20 +1,22 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "GpuDecoderModule.h" -#include "RemoteDecoderManagerChild.h" -#include "RemoteMediaDataDecoder.h" +#include "base/thread.h" +#include "mozilla/layers/SynchronousTask.h" +#include "mozilla/StaticPrefs_media.h" #include "RemoteVideoDecoder.h" -#include "mozilla/StaticPrefs_media.h" -#include "mozilla/SyncRunnable.h" +#include "RemoteDecoderManagerChild.h" + +#include "RemoteMediaDataDecoder.h" namespace mozilla { using namespace ipc; using namespace layers; using namespace gfx; nsresult GpuDecoderModule::Startup() { @@ -43,30 +45,29 @@ static inline bool IsRemoteAcceleratedCo already_AddRefed<MediaDataDecoder> GpuDecoderModule::CreateVideoDecoder( const CreateDecoderParams& aParams) { if (!StaticPrefs::media_gpu_process_decoder() || !aParams.mKnowsCompositor || !IsRemoteAcceleratedCompositor(aParams.mKnowsCompositor)) { return mWrapped->CreateVideoDecoder(aParams); } RefPtr<GpuRemoteVideoDecoderChild> child = new GpuRemoteVideoDecoderChild(); + SynchronousTask task("InitIPDL"); MediaResult result(NS_OK); - RefPtr<Runnable> task = NS_NewRunnableFunction( - "dom::GpuDecoderModule::CreateVideoDecoder", [&]() { - result = child->InitIPDL( - aParams.VideoConfig(), aParams.mRate.mValue, aParams.mOptions, - aParams.mKnowsCompositor->GetTextureFactoryIdentifier()); - if (NS_FAILED(result)) { - // Release GpuRemoteVideoDecoderChild here, while we're on - // manager thread. Don't just let the RefPtr go out of scope. - child = nullptr; - } - }); - SyncRunnable::DispatchToThread(RemoteDecoderManagerChild::GetManagerThread(), - task); + RemoteDecoderManagerChild::GetManagerThread()->Dispatch( + NS_NewRunnableFunction( + "dom::GpuDecoderModule::CreateVideoDecoder", + [&, child]() { + AutoCompleteTask complete(&task); + result = child->InitIPDL( + aParams.VideoConfig(), aParams.mRate.mValue, aParams.mOptions, + aParams.mKnowsCompositor->GetTextureFactoryIdentifier()); + }), + NS_DISPATCH_NORMAL); + task.Wait(); if (NS_FAILED(result)) { if (aParams.mError) { *aParams.mError = result; } return nullptr; }
--- a/dom/media/ipc/RemoteDecoderChild.cpp +++ b/dom/media/ipc/RemoteDecoderChild.cpp @@ -249,17 +249,17 @@ void RemoteDecoderChild::SetSeekThreshol MediaDataDecoder::ConversionRequired RemoteDecoderChild::NeedsConversion() const { AssertOnManagerThread(); return mConversion; } void RemoteDecoderChild::AssertOnManagerThread() const { - MOZ_ASSERT(mThread->IsOnCurrentThread()); + MOZ_ASSERT(NS_GetCurrentThread() == mThread); } RemoteDecoderManagerChild* RemoteDecoderChild::GetManager() { if (!CanSend()) { return nullptr; } return static_cast<RemoteDecoderManagerChild*>(Manager()); }
--- a/dom/media/ipc/RemoteDecoderChild.h +++ b/dom/media/ipc/RemoteDecoderChild.h @@ -50,17 +50,17 @@ class RemoteDecoderChild : public PRemot virtual MediaResult ProcessOutput(const DecodedOutputIPDL& aDecodedData) = 0; virtual void RecordShutdownTelemetry(bool aForAbnormalShutdown) {} RefPtr<RemoteDecoderChild> mIPDLSelfRef; MediaDataDecoder::DecodedData mDecodedData; private: - const nsCOMPtr<nsISerialEventTarget> mThread; + RefPtr<nsIThread> mThread; MozPromiseHolder<MediaDataDecoder::InitPromise> mInitPromise; MozPromiseRequestHolder<PRemoteDecoderChild::InitPromise> mInitPromiseRequest; MozPromiseHolder<MediaDataDecoder::DecodePromise> mDecodePromise; MozPromiseHolder<MediaDataDecoder::DecodePromise> mDrainPromise; MozPromiseHolder<MediaDataDecoder::FlushPromise> mFlushPromise; MozPromiseHolder<mozilla::ShutdownPromise> mShutdownPromise;
--- a/dom/media/ipc/RemoteDecoderManagerChild.cpp +++ b/dom/media/ipc/RemoteDecoderManagerChild.cpp @@ -1,130 +1,132 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "RemoteDecoderManagerChild.h" +#include "base/task.h" + #include "RemoteDecoderChild.h" -#include "VideoUtils.h" #include "mozilla/dom/ContentChild.h" #include "mozilla/gfx/2D.h" +#include "mozilla/ipc/ProtocolUtils.h" +#include "mozilla/layers/SynchronousTask.h" #include "mozilla/gfx/DataSurfaceHelpers.h" -#include "mozilla/ipc/ProtocolUtils.h" #include "mozilla/layers/ISurfaceAllocator.h" -#include "mozilla/layers/SynchronousTask.h" namespace mozilla { using namespace layers; using namespace gfx; // Only modified on the main-thread -StaticRefPtr<TaskQueue> sRemoteDecoderManagerChildThread; +StaticRefPtr<nsIThread> sRemoteDecoderManagerChildThread; // Only accessed from sRemoteDecoderManagerChildThread static StaticRefPtr<RemoteDecoderManagerChild> sRemoteDecoderManagerChildForRDDProcess; static StaticRefPtr<RemoteDecoderManagerChild> sRemoteDecoderManagerChildForGPUProcess; static UniquePtr<nsTArray<RefPtr<Runnable>>> sRecreateTasks; /* static */ void RemoteDecoderManagerChild::InitializeThread() { MOZ_ASSERT(NS_IsMainThread()); if (!sRemoteDecoderManagerChildThread) { - // We can't use a MediaThreadType::PLAYBACK as the GpuDecoderModule and - // RemoteDecoderModule runs on it and dispatch synchronous tasks to the - // manager thread, should more than 4 concurrent videos being instantiated - // at the same time, we could end up in a deadlock. - sRemoteDecoderManagerChildThread = new TaskQueue( - GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER), "RemVidChild"); + RefPtr<nsIThread> childThread; + nsresult rv = NS_NewNamedThread("RemVidChild", getter_AddRefs(childThread)); + NS_ENSURE_SUCCESS_VOID(rv); + sRemoteDecoderManagerChildThread = childThread; sRecreateTasks = MakeUnique<nsTArray<RefPtr<Runnable>>>(); } } /* static */ void RemoteDecoderManagerChild::InitForRDDProcess( Endpoint<PRemoteDecoderManagerChild>&& aVideoManager) { InitializeThread(); - MOZ_ALWAYS_SUCCEEDS(sRemoteDecoderManagerChildThread->Dispatch( + sRemoteDecoderManagerChildThread->Dispatch( NewRunnableFunction("InitForContentRunnable", &OpenForRDDProcess, - std::move(aVideoManager)))); + std::move(aVideoManager)), + NS_DISPATCH_NORMAL); } /* static */ void RemoteDecoderManagerChild::InitForGPUProcess( Endpoint<PRemoteDecoderManagerChild>&& aVideoManager) { InitializeThread(); - MOZ_ALWAYS_SUCCEEDS(sRemoteDecoderManagerChildThread->Dispatch( + sRemoteDecoderManagerChildThread->Dispatch( NewRunnableFunction("InitForContentRunnable", &OpenForGPUProcess, - std::move(aVideoManager)))); + std::move(aVideoManager)), + NS_DISPATCH_NORMAL); } /* static */ void RemoteDecoderManagerChild::Shutdown() { MOZ_ASSERT(NS_IsMainThread()); if (sRemoteDecoderManagerChildThread) { - MOZ_ALWAYS_SUCCEEDS( - sRemoteDecoderManagerChildThread->Dispatch(NS_NewRunnableFunction( - "dom::RemoteDecoderManagerChild::Shutdown", []() { + sRemoteDecoderManagerChildThread->Dispatch( + NS_NewRunnableFunction( + "dom::RemoteDecoderManagerChild::Shutdown", + []() { if (sRemoteDecoderManagerChildForRDDProcess && sRemoteDecoderManagerChildForRDDProcess->CanSend()) { sRemoteDecoderManagerChildForRDDProcess->Close(); + sRemoteDecoderManagerChildForRDDProcess = nullptr; } - sRemoteDecoderManagerChildForRDDProcess = nullptr; if (sRemoteDecoderManagerChildForGPUProcess && sRemoteDecoderManagerChildForGPUProcess->CanSend()) { sRemoteDecoderManagerChildForGPUProcess->Close(); + sRemoteDecoderManagerChildForGPUProcess = nullptr; } - sRemoteDecoderManagerChildForGPUProcess = nullptr; - }))); + }), + NS_DISPATCH_NORMAL); - sRemoteDecoderManagerChildThread->BeginShutdown(); - sRemoteDecoderManagerChildThread->AwaitShutdownAndIdle(); + sRemoteDecoderManagerChildThread->Shutdown(); sRemoteDecoderManagerChildThread = nullptr; sRecreateTasks = nullptr; } } void RemoteDecoderManagerChild::RunWhenGPUProcessRecreated( already_AddRefed<Runnable> aTask) { - MOZ_ASSERT(GetManagerThread() && GetManagerThread()->IsOnCurrentThread()); + MOZ_ASSERT(NS_GetCurrentThread() == GetManagerThread()); // If we've already been recreated, then run the task immediately. if (GetGPUProcessSingleton() && GetGPUProcessSingleton() != this && GetGPUProcessSingleton()->CanSend()) { RefPtr<Runnable> task = aTask; task->Run(); } else { sRecreateTasks->AppendElement(aTask); } } /* static */ RemoteDecoderManagerChild* RemoteDecoderManagerChild::GetRDDProcessSingleton() { - MOZ_ASSERT(GetManagerThread() && GetManagerThread()->IsOnCurrentThread()); + MOZ_ASSERT(NS_GetCurrentThread() == GetManagerThread()); return sRemoteDecoderManagerChildForRDDProcess; } /* static */ RemoteDecoderManagerChild* RemoteDecoderManagerChild::GetGPUProcessSingleton() { - MOZ_ASSERT(GetManagerThread() && GetManagerThread()->IsOnCurrentThread()); + MOZ_ASSERT(NS_GetCurrentThread() == GetManagerThread()); return sRemoteDecoderManagerChildForGPUProcess; } /* static */ -nsISerialEventTarget* RemoteDecoderManagerChild::GetManagerThread() { +nsIThread* RemoteDecoderManagerChild::GetManagerThread() { return sRemoteDecoderManagerChildThread; } PRemoteDecoderChild* RemoteDecoderManagerChild::AllocPRemoteDecoderChild( const RemoteDecoderInfoIPDL& /* not used */, const CreateDecoderParams::OptionSet& aOptions, const Maybe<layers::TextureFactoryIdentifier>& aIdentifier, bool* aSuccess, nsCString* /* not used */) { @@ -144,25 +146,25 @@ bool RemoteDecoderManagerChild::DeallocP } RemoteDecoderManagerChild::RemoteDecoderManagerChild( layers::VideoBridgeSource aSource) : mSource(aSource) {} void RemoteDecoderManagerChild::OpenForRDDProcess( Endpoint<PRemoteDecoderManagerChild>&& aEndpoint) { - MOZ_ASSERT(GetManagerThread() && GetManagerThread()->IsOnCurrentThread()); + MOZ_ASSERT(NS_GetCurrentThread() == GetManagerThread()); // Only create RemoteDecoderManagerChild, bind new endpoint and init // ipdl if: // 1) haven't init'd sRemoteDecoderManagerChild // or - // 2) if ActorDestroy was called meaning the other end of the ipc channel was - // torn down + // 2) if ActorDestroy was called (mCanSend is false) meaning the other + // end of the ipc channel was torn down if (sRemoteDecoderManagerChildForRDDProcess && - sRemoteDecoderManagerChildForRDDProcess->CanSend()) { + sRemoteDecoderManagerChildForRDDProcess->mCanSend) { return; } sRemoteDecoderManagerChildForRDDProcess = nullptr; if (aEndpoint.IsValid()) { RefPtr<RemoteDecoderManagerChild> manager = new RemoteDecoderManagerChild(VideoBridgeSource::RddProcess); if (aEndpoint.Bind(manager)) { sRemoteDecoderManagerChildForRDDProcess = manager; @@ -186,33 +188,44 @@ void RemoteDecoderManagerChild::OpenForG } for (Runnable* task : *sRecreateTasks) { task->Run(); } sRecreateTasks->Clear(); } void RemoteDecoderManagerChild::InitIPDL() { + mCanSend = true; mIPDLSelfRef = this; } +void RemoteDecoderManagerChild::ActorDestroy(ActorDestroyReason aWhy) { + mCanSend = false; +} + void RemoteDecoderManagerChild::ActorDealloc() { mIPDLSelfRef = nullptr; } +bool RemoteDecoderManagerChild::CanSend() { + MOZ_ASSERT(NS_GetCurrentThread() == GetManagerThread()); + return mCanSend; +} + bool RemoteDecoderManagerChild::DeallocShmem(mozilla::ipc::Shmem& aShmem) { - if (!sRemoteDecoderManagerChildThread->IsOnCurrentThread()) { + if (NS_GetCurrentThread() != sRemoteDecoderManagerChildThread) { RefPtr<RemoteDecoderManagerChild> self = this; mozilla::ipc::Shmem shmem = aShmem; - MOZ_ALWAYS_SUCCEEDS( - sRemoteDecoderManagerChildThread->Dispatch(NS_NewRunnableFunction( - "RemoteDecoderManagerChild::DeallocShmem", [self, shmem]() { - if (self->CanSend()) { - mozilla::ipc::Shmem shmemCopy = shmem; - self->DeallocShmem(shmemCopy); - } - }))); + sRemoteDecoderManagerChildThread->Dispatch( + NS_NewRunnableFunction("RemoteDecoderManagerChild::DeallocShmem", + [self, shmem]() { + if (self->CanSend()) { + mozilla::ipc::Shmem shmemCopy = shmem; + self->DeallocShmem(shmemCopy); + } + }), + NS_DISPATCH_NORMAL); return true; } return PRemoteDecoderManagerChild::DeallocShmem(aShmem); } struct SurfaceDescriptorUserData { SurfaceDescriptorUserData(RemoteDecoderManagerChild* aAllocator, SurfaceDescriptor& aSD) @@ -234,22 +247,24 @@ already_AddRefed<SourceSurface> RemoteDe // We can't use NS_DISPATCH_SYNC here since that can spin the event // loop while it waits. This function can be called from JS and we // don't want that to happen. SynchronousTask task("Readback sync"); RefPtr<RemoteDecoderManagerChild> ref = this; SurfaceDescriptor sd; if (NS_FAILED(sRemoteDecoderManagerChildThread->Dispatch( - NS_NewRunnableFunction("RemoteDecoderManagerChild::Readback", [&]() { - AutoCompleteTask complete(&task); - if (ref->CanSend()) { - ref->SendReadback(aSD, &sd); - } - })))) { + NS_NewRunnableFunction("RemoteDecoderManagerChild::Readback", + [&]() { + AutoCompleteTask complete(&task); + if (ref->CanSend()) { + ref->SendReadback(aSD, &sd); + } + }), + NS_DISPATCH_NORMAL))) { return nullptr; } task.Wait(); if (!IsSurfaceDescriptorValid(sd)) { return nullptr; } @@ -268,23 +283,24 @@ already_AddRefed<SourceSurface> RemoteDe return source.forget(); } void RemoteDecoderManagerChild::DeallocateSurfaceDescriptor( const SurfaceDescriptorGPUVideo& aSD) { RefPtr<RemoteDecoderManagerChild> ref = this; SurfaceDescriptorGPUVideo sd = std::move(aSD); - MOZ_ALWAYS_SUCCEEDS( - sRemoteDecoderManagerChildThread->Dispatch(NS_NewRunnableFunction( + sRemoteDecoderManagerChildThread->Dispatch( + NS_NewRunnableFunction( "RemoteDecoderManagerChild::DeallocateSurfaceDescriptor", [ref, sd]() { if (ref->CanSend()) { ref->SendDeallocateSurfaceDescriptorGPUVideo(sd); } - }))); + }), + NS_DISPATCH_NORMAL); } void RemoteDecoderManagerChild::HandleFatalError(const char* aMsg) const { dom::ContentChild::FatalErrorIfNotUsingGPUProcess(aMsg, OtherPid()); } } // namespace mozilla
--- a/dom/media/ipc/RemoteDecoderManagerChild.h +++ b/dom/media/ipc/RemoteDecoderManagerChild.h @@ -1,18 +1,18 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef include_dom_media_ipc_RemoteDecoderManagerChild_h #define include_dom_media_ipc_RemoteDecoderManagerChild_h -#include "GPUVideoImage.h" #include "mozilla/PRemoteDecoderManagerChild.h" #include "mozilla/layers/VideoBridgeUtils.h" +#include "GPUVideoImage.h" namespace mozilla { class RemoteDecoderManagerChild final : public PRemoteDecoderManagerChild, public mozilla::ipc::IShmemAllocator, public mozilla::layers::IGPUVideoSurfaceManager { friend class PRemoteDecoderManagerChild; @@ -20,17 +20,17 @@ class RemoteDecoderManagerChild final public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RemoteDecoderManagerChild, override) // Can only be called from the manager thread static RemoteDecoderManagerChild* GetRDDProcessSingleton(); static RemoteDecoderManagerChild* GetGPUProcessSingleton(); // Can be called from any thread. - static nsISerialEventTarget* GetManagerThread(); + static nsIThread* GetManagerThread(); // Can be called from any thread, dispatches the request to the IPDL thread // internally and will be ignored if the IPDL actor has been destroyed. already_AddRefed<gfx::SourceSurface> Readback( const SurfaceDescriptorGPUVideo& aSD) override; void DeallocateSurfaceDescriptor( const SurfaceDescriptorGPUVideo& aSD) override; @@ -46,55 +46,62 @@ class RemoteDecoderManagerChild final aShmem); } // Can be called from any thread, dispatches the request to the IPDL thread // internally and will be ignored if the IPDL actor has been destroyed. bool DeallocShmem(mozilla::ipc::Shmem& aShmem) override; // Main thread only - static void InitializeThread(); static void InitForRDDProcess( Endpoint<PRemoteDecoderManagerChild>&& aVideoManager); static void InitForGPUProcess( Endpoint<PRemoteDecoderManagerChild>&& aVideoManager); static void Shutdown(); // Run aTask (on the manager thread) when we next attempt to create a new // manager (even if creation fails). Intended to be called from ActorDestroy // when we get notified that the old manager is being destroyed. Can only be // called from the manager thread. void RunWhenGPUProcessRecreated(already_AddRefed<Runnable> aTask); + bool CanSend(); layers::VideoBridgeSource GetSource() const { return mSource; } protected: void InitIPDL(); + void ActorDestroy(ActorDestroyReason aWhy) override; void ActorDealloc() override; void HandleFatalError(const char* aMsg) const override; PRemoteDecoderChild* AllocPRemoteDecoderChild( const RemoteDecoderInfoIPDL& aRemoteDecoderInfo, const CreateDecoderParams::OptionSet& aOptions, const Maybe<layers::TextureFactoryIdentifier>& aIdentifier, bool* aSuccess, nsCString* aErrorDescription); bool DeallocPRemoteDecoderChild(PRemoteDecoderChild* actor); private: + // Main thread only + static void InitializeThread(); + explicit RemoteDecoderManagerChild(layers::VideoBridgeSource aSource); ~RemoteDecoderManagerChild() = default; static void OpenForRDDProcess( Endpoint<PRemoteDecoderManagerChild>&& aEndpoint); static void OpenForGPUProcess( Endpoint<PRemoteDecoderManagerChild>&& aEndpoint); RefPtr<RemoteDecoderManagerChild> mIPDLSelfRef; // The associated source of this decoder manager layers::VideoBridgeSource mSource; + + // Should only ever be accessed on the manager thread. + bool mCanSend = false; }; } // namespace mozilla #endif // include_dom_media_ipc_RemoteDecoderManagerChild_h
--- a/dom/media/ipc/RemoteDecoderManagerParent.cpp +++ b/dom/media/ipc/RemoteDecoderManagerParent.cpp @@ -4,36 +4,37 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "RemoteDecoderManagerParent.h" #if XP_WIN # include <objbase.h> #endif -#include "ImageContainer.h" #include "RemoteAudioDecoder.h" #include "RemoteVideoDecoder.h" #include "VideoUtils.h" // for MediaThreadType -#include "mozilla/SyncRunnable.h" + +#include "ImageContainer.h" +#include "mozilla/layers/VideoBridgeChild.h" #include "mozilla/layers/ImageDataSerializer.h" -#include "mozilla/layers/VideoBridgeChild.h" +#include "mozilla/SyncRunnable.h" namespace mozilla { #ifdef XP_WIN extern const nsCString GetFoundD3D11BlacklistedDLL(); extern const nsCString GetFoundD3D9BlacklistedDLL(); #endif // XP_WIN using namespace ipc; using namespace layers; using namespace gfx; -StaticRefPtr<TaskQueue> sRemoteDecoderManagerParentThread; +StaticRefPtr<nsISerialEventTarget> sRemoteDecoderManagerParentThread; SurfaceDescriptorGPUVideo RemoteDecoderManagerParent::StoreImage( Image* aImage, TextureClient* aTexture) { SurfaceDescriptorRemoteDecoder ret; aTexture->GetSurfaceDescriptorRemoteDecoder(&ret); mImageMap[ret.handle()] = aImage; mTextureMap[ret.handle()] = aTexture; @@ -66,39 +67,47 @@ bool RemoteDecoderManagerParent::Startup return true; } nsCOMPtr<nsIObserverService> observerService = services::GetObserverService(); if (!observerService) { return false; } - sRemoteDecoderManagerParentThread = new TaskQueue( - GetMediaThreadPool(MediaThreadType::PLAYBACK), "RemVidParent"); + nsCOMPtr<nsISerialEventTarget> managerThread; + nsresult rv = NS_CreateBackgroundTaskQueue("RemVidParent", + getter_AddRefs(managerThread)); + if (NS_FAILED(rv)) { + return false; + } + sRemoteDecoderManagerParentThread = managerThread; if (XRE_IsGPUProcess()) { - MOZ_ALWAYS_SUCCEEDS( - sRemoteDecoderManagerParentThread->Dispatch(NS_NewRunnableFunction( + sRemoteDecoderManagerParentThread->Dispatch( + NS_NewRunnableFunction( "RemoteDecoderManagerParent::StartupThreads", - []() { layers::VideoBridgeChild::StartupForGPUProcess(); }))); + []() { layers::VideoBridgeChild::StartupForGPUProcess(); }), + NS_DISPATCH_NORMAL); } auto* obs = new RemoteDecoderManagerThreadShutdownObserver(); observerService->AddObserver(obs, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false); return true; } void RemoteDecoderManagerParent::ShutdownThreads() { - sRemoteDecoderManagerParentThread->BeginShutdown(); - sRemoteDecoderManagerParentThread->AwaitShutdownAndIdle(); sRemoteDecoderManagerParentThread = nullptr; } -/* static */ void RemoteDecoderManagerParent::ShutdownVideoBridge() { if (sRemoteDecoderManagerParentThread) { + if (sRemoteDecoderManagerParentThread->IsOnCurrentThread()) { + VideoBridgeChild::Shutdown(); + return; + } + RefPtr<Runnable> task = NS_NewRunnableFunction( "RemoteDecoderManagerParent::ShutdownVideoBridge", []() { VideoBridgeChild::Shutdown(); }); SyncRunnable::DispatchToThread(sRemoteDecoderManagerParentThread, task); } } bool RemoteDecoderManagerParent::OnManagerThread() { @@ -117,18 +126,18 @@ bool RemoteDecoderManagerParent::CreateF RefPtr<RemoteDecoderManagerParent> parent = new RemoteDecoderManagerParent(sRemoteDecoderManagerParentThread); RefPtr<Runnable> task = NewRunnableMethod<Endpoint<PRemoteDecoderManagerParent>&&>( "dom::RemoteDecoderManagerParent::Open", parent, &RemoteDecoderManagerParent::Open, std::move(aEndpoint)); - MOZ_ALWAYS_SUCCEEDS( - sRemoteDecoderManagerParentThread->Dispatch(task.forget())); + sRemoteDecoderManagerParentThread->Dispatch(task.forget(), + NS_DISPATCH_NORMAL); return true; } bool RemoteDecoderManagerParent::CreateVideoBridgeToOtherProcess( Endpoint<PVideoBridgeChild>&& aEndpoint) { // We never want to decode in the GPU process, but output // frames to the parent process. MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_RDD); @@ -136,18 +145,18 @@ bool RemoteDecoderManagerParent::CreateV if (!StartupThreads()) { return false; } RefPtr<Runnable> task = NewRunnableFunction("gfx::VideoBridgeChild::Open", &VideoBridgeChild::Open, std::move(aEndpoint)); - MOZ_ALWAYS_SUCCEEDS( - sRemoteDecoderManagerParentThread->Dispatch(task.forget())); + sRemoteDecoderManagerParentThread->Dispatch(task.forget(), + NS_DISPATCH_NORMAL); return true; } RemoteDecoderManagerParent::RemoteDecoderManagerParent( nsISerialEventTarget* aThread) : mThread(aThread) { MOZ_COUNT_CTOR(RemoteDecoderManagerParent); }
--- a/dom/media/ipc/RemoteDecoderModule.cpp +++ b/dom/media/ipc/RemoteDecoderModule.cpp @@ -1,53 +1,43 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "RemoteDecoderModule.h" +#include "base/thread.h" +#include "mozilla/dom/ContentChild.h" // for launching RDD w/ ContentChild +#include "mozilla/layers/SynchronousTask.h" #include "mozilla/StaticPrefs_media.h" #include "mozilla/SyncRunnable.h" -#include "mozilla/dom/ContentChild.h" // for launching RDD w/ ContentChild -#include "mozilla/layers/SynchronousTask.h" #ifdef MOZ_AV1 # include "AOMDecoder.h" #endif -#include "OpusDecoder.h" #include "RemoteAudioDecoder.h" #include "RemoteDecoderManagerChild.h" #include "RemoteMediaDataDecoder.h" #include "RemoteVideoDecoder.h" +#include "OpusDecoder.h" #include "VideoUtils.h" #include "VorbisDecoder.h" #include "WAVDecoder.h" -#include "nsIXULRuntime.h" // for BrowserTabsRemoteAutostart namespace mozilla { using dom::ContentChild; using namespace ipc; using namespace layers; StaticMutex RemoteDecoderModule::sLaunchMonitor; RemoteDecoderModule::RemoteDecoderModule() - : mManagerThread(RemoteDecoderManagerChild::GetManagerThread()) { - MOZ_DIAGNOSTIC_ASSERT(mManagerThread); -} - -/* static */ -void RemoteDecoderModule::Init() { - if (!BrowserTabsRemoteAutostart()) { - return; - } - RemoteDecoderManagerChild::InitializeThread(); -} + : mManagerThread(RemoteDecoderManagerChild::GetManagerThread()) {} bool RemoteDecoderModule::SupportsMimeType( const nsACString& aMimeType, DecoderDoctorDiagnostics* aDiagnostics) const { bool supports = false; #ifdef MOZ_AV1 if (StaticPrefs::media_av1_enabled()) { supports |= AOMDecoder::IsAV1(aMimeType); @@ -72,17 +62,17 @@ bool RemoteDecoderModule::SupportsMimeTy } MOZ_LOG( sPDMLog, LogLevel::Debug, ("Sandbox decoder %s requested type", supports ? "supports" : "rejects")); return supports; } -void RemoteDecoderModule::LaunchRDDProcessIfNeeded() const { +void RemoteDecoderModule::LaunchRDDProcessIfNeeded() { if (!XRE_IsContentProcess()) { return; } StaticMutexAutoLock mon(sLaunchMonitor); // We have a couple possible states here. We are in a content process // and: @@ -93,34 +83,41 @@ void RemoteDecoderModule::LaunchRDDProce // In the code below, we assume we need to launch the RDD process and // setup the IPC connections. However, if the manager thread for // RemoteDecoderManagerChild is available we do a quick check to see // if we can send (meaning the IPC channel is open). If we can send, // then no work is necessary. If we can't send, then we call // LaunchRDDProcess which will launch RDD if necessary, and setup the // IPC connections between *this* content process and the RDD process. bool needsLaunch = true; - RefPtr<Runnable> task = NS_NewRunnableFunction( - "RemoteDecoderModule::LaunchRDDProcessIfNeeded-CheckSend", [&]() { - if (RemoteDecoderManagerChild::GetRDDProcessSingleton()) { - needsLaunch = - !RemoteDecoderManagerChild::GetRDDProcessSingleton()->CanSend(); - } - }); - SyncRunnable::DispatchToThread(mManagerThread, task); + if (mManagerThread) { + RefPtr<Runnable> task = NS_NewRunnableFunction( + "RemoteDecoderModule::LaunchRDDProcessIfNeeded-CheckSend", [&]() { + if (RemoteDecoderManagerChild::GetRDDProcessSingleton()) { + needsLaunch = + !RemoteDecoderManagerChild::GetRDDProcessSingleton()->CanSend(); + } + }); + SyncRunnable::DispatchToThread(mManagerThread, task); + } if (needsLaunch) { ContentChild::GetSingleton()->LaunchRDDProcess(); + mManagerThread = RemoteDecoderManagerChild::GetManagerThread(); } } already_AddRefed<MediaDataDecoder> RemoteDecoderModule::CreateAudioDecoder( const CreateDecoderParams& aParams) { LaunchRDDProcessIfNeeded(); + if (!mManagerThread) { + return nullptr; + } + // OpusDataDecoder will check this option to provide the same info // that IsDefaultPlaybackDeviceMono provides. We want to avoid calls // to IsDefaultPlaybackDeviceMono on RDD because initializing audio // backends on RDD will be blocked by the sandbox. CreateDecoderParams::OptionSet options(aParams.mOptions); if (OpusDataDecoder::IsOpus(aParams.mConfig.mMimeType) && IsDefaultPlaybackDeviceMono()) { options += CreateDecoderParams::Option::DefaultPlaybackDeviceMono; @@ -157,16 +154,20 @@ already_AddRefed<MediaDataDecoder> Remot return object.forget(); } already_AddRefed<MediaDataDecoder> RemoteDecoderModule::CreateVideoDecoder( const CreateDecoderParams& aParams) { LaunchRDDProcessIfNeeded(); + if (!mManagerThread) { + return nullptr; + } + RefPtr<RemoteVideoDecoderChild> child = new RemoteVideoDecoderChild(); MediaResult result(NS_OK); // We can use child as a ref here because this is a sync dispatch. In // the error case for InitIPDL, we can't just let the RefPtr go out of // scope at the end of the method because it will release the // RemoteVideoDecoderChild on the wrong thread. This will assert in // RemoteDecoderChild's destructor. Passing the RefPtr by reference // allows us to release the RemoteVideoDecoderChild on the manager
--- a/dom/media/ipc/RemoteDecoderModule.h +++ b/dom/media/ipc/RemoteDecoderModule.h @@ -1,42 +1,41 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef include_dom_media_ipc_RemoteDecoderModule_h #define include_dom_media_ipc_RemoteDecoderModule_h #include "PlatformDecoderModule.h" + #include "mozilla/StaticMutex.h" namespace mozilla { // A PDM implementation that creates a RemoteMediaDataDecoder (a // MediaDataDecoder) that proxies to a RemoteVideoDecoderChild. // A decoder child will talk to its respective decoder parent // (RemoteVideoDecoderParent) on the RDD process. class RemoteDecoderModule : public PlatformDecoderModule { public: - static void Init(); - RemoteDecoderModule(); bool SupportsMimeType(const nsACString& aMimeType, DecoderDoctorDiagnostics* aDiagnostics) const override; already_AddRefed<MediaDataDecoder> CreateVideoDecoder( const CreateDecoderParams& aParams) override; already_AddRefed<MediaDataDecoder> CreateAudioDecoder( const CreateDecoderParams& aParams) override; protected: - void LaunchRDDProcessIfNeeded() const; + void LaunchRDDProcessIfNeeded(); private: - const nsCOMPtr<nsISerialEventTarget> mManagerThread; + RefPtr<nsIThread> mManagerThread; static StaticMutex sLaunchMonitor; }; } // namespace mozilla #endif // include_dom_media_ipc_RemoteDecoderModule_h
--- a/dom/media/platforms/PDMFactory.cpp +++ b/dom/media/platforms/PDMFactory.cpp @@ -67,17 +67,16 @@ class PDMFactoryImpl final { OmxDecoderModule::Init(); #endif #ifdef MOZ_FFVPX FFVPXRuntimeLinker::Init(); #endif #ifdef MOZ_FFMPEG FFmpegRuntimeLinker::Init(); #endif - RemoteDecoderModule::Init(); } }; StaticAutoPtr<PDMFactoryImpl> PDMFactory::sInstance; StaticMutex PDMFactory::sMonitor; class SupportChecker { public:
--- a/mfbt/WeakPtr.h +++ b/mfbt/WeakPtr.h @@ -93,22 +93,22 @@ // the object pointer locally and is about to add a reference to it. // // Hence, a non-null weak proxy object is considered to have a single // "owning thread". It means that each query for a weak reference, // its dereference, and destruction of the real object must all happen // on a single thread. The following macros implement assertions for // checking these conditions. // -// We re-use XPCOM's nsAutoOwningEventTarget checks when they are available. -// This has the advantage that it works with cooperative thread pools. +// We re-use XPCOM's nsAutoOwningThread checks when they are available. This has +// the advantage that it works with cooperative thread pools. # define MOZ_WEAKPTR_DECLARE_THREAD_SAFETY_CHECK \ /* Will be none if mPtr = nullptr. */ \ - Maybe<nsAutoOwningEventTarget> _owningThread; + Maybe<nsAutoOwningThread> _owningThread; # define MOZ_WEAKPTR_INIT_THREAD_SAFETY_CHECK() \ do { \ if (p) { \ _owningThread.emplace(); \ } \ } while (false) # define MOZ_WEAKPTR_ASSERT_THREAD_SAFETY() \ do { \
--- a/xpcom/base/nsISupportsImpl.cpp +++ b/xpcom/base/nsISupportsImpl.cpp @@ -59,15 +59,12 @@ void nsAutoOwningEventTarget ::AssertCur const char* msg) const { if (MOZ_UNLIKELY(!IsCurrentThread())) { // `msg` is a string literal by construction. MOZ_CRASH_UNSAFE(msg); } } bool nsAutoOwningEventTarget::IsCurrentThread() const { - // This API is only ever used for debug builds and has no JS implementation - // Avoid triggering the Hazard static-analyzer. - JS::AutoSuppressGCAnalysis suppress; return mTarget->IsOnCurrentThread(); } #endif