Bug 1539030 - (redux) don't attempt RDD launch unless needed. r=jya
authorMichael Froman <mfroman@mozilla.com>
Thu, 02 May 2019 21:08:58 +0000
changeset 531180 6638560366c476bb2d62e4f26eea39b0dfcf4905
parent 531179 3be80123e3af0bf2aece853e560891b3163e5d7a
child 531181 8141f59dd1237917e845f055f63395753dcea70b
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjya
bugs1539030
milestone68.0a1
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
Bug 1539030 - (redux) don't attempt RDD launch unless needed. r=jya Detect content process that already has connection to the RDD process and don't attempt to relaunch or needlessly call RDDProcessManager::CreateContentBridge. Calling CreateContentBridge unnecessarily causes churn by recreating RemoteDecoderManagerParents. Differential Revision: https://phabricator.services.mozilla.com/D29013
dom/media/ipc/RemoteDecoderModule.cpp
dom/media/ipc/RemoteDecoderModule.h
--- a/dom/media/ipc/RemoteDecoderModule.cpp
+++ b/dom/media/ipc/RemoteDecoderModule.cpp
@@ -22,16 +22,19 @@
 
 namespace mozilla {
 
 using base::Thread;
 using dom::ContentChild;
 using namespace ipc;
 using namespace layers;
 
+RemoteDecoderModule::RemoteDecoderModule()
+    : mManagerThread(RemoteDecoderManagerChild::GetManagerThread()) {}
+
 bool RemoteDecoderModule::SupportsMimeType(
     const nsACString& aMimeType, DecoderDoctorDiagnostics* aDiagnostics) const {
   bool supports = false;
 
 #ifdef MOZ_AV1
   if (StaticPrefs::MediaAv1Enabled()) {
     supports |= AOMDecoder::IsAV1(aMimeType);
   }
@@ -41,74 +44,101 @@ bool RemoteDecoderModule::SupportsMimeTy
   }
 
   MOZ_LOG(
       sPDMLog, LogLevel::Debug,
       ("Sandbox decoder %s requested type", supports ? "supports" : "rejects"));
   return supports;
 }
 
+void RemoteDecoderModule::LaunchRDDProcessIfNeeded() {
+  if (!XRE_IsContentProcess()) {
+    return;
+  }
+
+  // We have a couple possible states here.  We are in a content process
+  // and:
+  // 1) the RDD process has never been launched.  RDD should be launched
+  //    and the IPC connections setup.
+  // 2) the RDD process has been launched, but this particular content
+  //    process has not setup (or has lost) its IPC connection.
+  // 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;
+  if (mManagerThread) {
+    RefPtr<Runnable> task = NS_NewRunnableFunction(
+        "RemoteDecoderModule::LaunchRDDProcessIfNeeded-CheckSend", [&]() {
+          if (RemoteDecoderManagerChild::GetSingleton()) {
+            needsLaunch = !RemoteDecoderManagerChild::GetSingleton()->CanSend();
+          }
+        });
+    SyncRunnable::DispatchToThread(mManagerThread, task);
+  }
+
+  if (needsLaunch) {
+    ContentChild::GetSingleton()->LaunchRDDProcess();
+    mManagerThread = RemoteDecoderManagerChild::GetManagerThread();
+  }
+}
+
 already_AddRefed<MediaDataDecoder> RemoteDecoderModule::CreateAudioDecoder(
     const CreateDecoderParams& aParams) {
-  if (XRE_IsContentProcess()) {
-    ContentChild* contentChild = ContentChild::GetSingleton();
-    contentChild->LaunchRDDProcess();
-  }
+  LaunchRDDProcessIfNeeded();
 
-  if (!RemoteDecoderManagerChild::GetManagerThread()) {
+  if (!mManagerThread) {
     return nullptr;
   }
 
   RefPtr<RemoteAudioDecoderChild> child = new RemoteAudioDecoderChild();
   RefPtr<RemoteMediaDataDecoder> object = new RemoteMediaDataDecoder(
-      child, RemoteDecoderManagerChild::GetManagerThread(),
+      child, mManagerThread,
       RemoteDecoderManagerChild::GetManagerAbstractThread());
 
   MediaResult result(NS_OK);
   RefPtr<Runnable> task = NS_NewRunnableFunction(
       "RemoteDecoderModule::CreateAudioDecoder", [&, child]() {
         result = child->InitIPDL(aParams.AudioConfig(), aParams.mOptions);
       });
-  SyncRunnable::DispatchToThread(RemoteDecoderManagerChild::GetManagerThread(),
-                                 task);
+  SyncRunnable::DispatchToThread(mManagerThread, task);
 
   if (NS_FAILED(result)) {
     if (aParams.mError) {
       *aParams.mError = result;
     }
     return nullptr;
   }
 
   return object.forget();
 }
 
 already_AddRefed<MediaDataDecoder> RemoteDecoderModule::CreateVideoDecoder(
     const CreateDecoderParams& aParams) {
-  if (XRE_IsContentProcess()) {
-    ContentChild* contentChild = ContentChild::GetSingleton();
-    contentChild->LaunchRDDProcess();
-  }
+  LaunchRDDProcessIfNeeded();
 
-  if (!RemoteDecoderManagerChild::GetManagerThread()) {
+  if (!mManagerThread) {
     return nullptr;
   }
 
   RefPtr<RemoteVideoDecoderChild> child = new RemoteVideoDecoderChild();
   RefPtr<RemoteMediaDataDecoder> object = new RemoteMediaDataDecoder(
-      child, RemoteDecoderManagerChild::GetManagerThread(),
+      child, mManagerThread,
       RemoteDecoderManagerChild::GetManagerAbstractThread());
 
   MediaResult result(NS_OK);
   RefPtr<Runnable> task = NS_NewRunnableFunction(
       "RemoteDecoderModule::CreateVideoDecoder", [&, child]() {
         result = child->InitIPDL(aParams.VideoConfig(), aParams.mRate.mValue,
                                  aParams.mOptions);
       });
-  SyncRunnable::DispatchToThread(RemoteDecoderManagerChild::GetManagerThread(),
-                                 task);
+  SyncRunnable::DispatchToThread(mManagerThread, task);
 
   if (NS_FAILED(result)) {
     if (aParams.mError) {
       *aParams.mError = result;
     }
     return nullptr;
   }
 
--- a/dom/media/ipc/RemoteDecoderModule.h
+++ b/dom/media/ipc/RemoteDecoderModule.h
@@ -10,23 +10,29 @@
 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:
-  RemoteDecoderModule() = default;
+  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();
+
+ private:
+  RefPtr<nsIThread> mManagerThread;
 };
 
 }  // namespace mozilla
 
 #endif  // include_dom_media_ipc_RemoteDecoderModule_h