Backed out 5 changesets (bug 1650996, bug 1649974) for perma failures on Android 7.0. CLOSED TREE
authorRazvan Maries <rmaries@mozilla.com>
Thu, 09 Jul 2020 10:33:45 +0300
changeset 539533 b8fad3d28fcdb62558ce1766933bd47cb2343303
parent 539532 03e70cb012757fe65c35ac2d27654dff44db606f
child 539534 c245b8a73f2a235892ac706082f3443b387d3bc9
push id37582
push userapavel@mozilla.com
push dateThu, 09 Jul 2020 15:42:10 +0000
treeherdermozilla-central@ccd521ebc464 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1650996, 1649974
milestone80.0a1
backs out8f8174ba409dd3bb236f0bebd6ba9279ad3bf65f
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
Backed out 5 changesets (bug 1650996, bug 1649974) for perma failures on Android 7.0. CLOSED TREE Backed out changeset 8f8174ba409d (bug 1650996) Backed out changeset 374598f9c37a (bug 1650996) Backed out changeset 236757acc073 (bug 1650996) Backed out changeset 89d5cabfa2df (bug 1649974) Backed out changeset 6e475ddbd18c (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
xpcom/base/nsISupportsImpl.cpp
--- 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