Backed out 5 changesets (bug 1650996, bug 1649974) for hazard failures CLOSED TREE
authorBogdan Tara <btara@mozilla.com>
Wed, 08 Jul 2020 16:07:56 +0300
changeset 539339 d8abefec5bba959f42bac66237b9eabe2d04dfaa
parent 539338 d59f0a83a7e9ec6fda8f7327f3154d67b266ec65
child 539340 569112cc1631bf463d441c6278a146f8cce999ec
push id37579
push userdluca@mozilla.com
push dateWed, 08 Jul 2020 21:49:35 +0000
treeherdermozilla-central@ee89deeb4fb6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1650996, 1649974
milestone80.0a1
backs outde5e55b59a31aee8cf5092c2c975236dc34de07e
35faa46f46f1004e78a8f8feaaef0eec769c52dd
6f779a3875a89a4717750e9520d4454abc786fcb
fac1e5a07a6c3e33ea24dddb221e4d9bab628f9e
3c5157a9e8722e1e4213ddc9f613479b70e769bf
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
Backed out 5 changesets (bug 1650996, bug 1649974) for hazard failures CLOSED TREE Backed out changeset de5e55b59a31 (bug 1650996) Backed out changeset 35faa46f46f1 (bug 1650996) Backed out changeset 6f779a3875a8 (bug 1650996) Backed out changeset fac1e5a07a6c (bug 1649974) Backed out changeset 3c5157a9e872 (bug 1649974)
build/clang-plugin/ThreadAllows.txt
dom/media/ipc/GpuDecoderModule.cpp
dom/media/ipc/RemoteDecoderChild.cpp
dom/media/ipc/RemoteDecoderChild.h
dom/media/ipc/RemoteDecoderManagerChild.cpp
dom/media/ipc/RemoteDecoderManagerChild.h
dom/media/ipc/RemoteDecoderManagerParent.cpp
dom/media/ipc/RemoteDecoderModule.cpp
dom/media/ipc/RemoteDecoderModule.h
dom/media/platforms/PDMFactory.cpp
mfbt/WeakPtr.h
--- 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 {                                                                      \