Bug 1245789 - Add abstract thread wrapper for the GMP thread. r=gerald,a=ritu
authorChris Pearce <cpearce@mozilla.com>
Tue, 12 Apr 2016 16:12:20 +1200
changeset 324032 46901779c9a370bf2dedc0187d16c0b99f9826ae
parent 324031 f1d62a2c836c5354b6faab06e58fd635b139512f
child 324033 59738be799b716dba2555cf056fc0e8ea2e6353c
push id5913
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 16:57:49 +0000
treeherdermozilla-beta@dcaf0a6fa115 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgerald, ritu
bugs1245789
milestone47.0a2
Bug 1245789 - Add abstract thread wrapper for the GMP thread. r=gerald,a=ritu I need to make GMPParent::Init() async, because the WebIDL JSON parsing must happen on the main thread, and GMPParent::Init() is called on the GMP thread, so I need GMPParent::Init() to be async so that in the Chrome manifest case it can dispatch a task to the main thread to parse the Chrome manifest before completing. So I'll make GMPParent::Init() return a promise, and to do that, I need the GMP thread to have an AbstractThread wrapper. MozReview-Commit-ID: 44b4Z4jpar8
dom/media/gmp/GMPService.cpp
dom/media/gmp/GMPService.h
dom/media/platforms/agnostic/eme/EMEDecoderModule.cpp
dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp
dom/media/platforms/agnostic/gmp/MediaDataDecoderProxy.cpp
dom/media/platforms/agnostic/gmp/MediaDataDecoderProxy.h
--- a/dom/media/gmp/GMPService.cpp
+++ b/dom/media/gmp/GMPService.cpp
@@ -352,26 +352,34 @@ GeckoMediaPluginService::GetThread(nsITh
       return NS_ERROR_FAILURE;
     }
 
     nsresult rv = NS_NewNamedThread("GMPThread", getter_AddRefs(mGMPThread));
     if (NS_FAILED(rv)) {
       return rv;
     }
 
+    mAbstractGMPThread = CreateXPCOMAbstractThreadWrapper(mGMPThread, false);
+
     // Tell the thread to initialize plugins
     InitializePlugins();
   }
 
   nsCOMPtr<nsIThread> copy = mGMPThread;
   copy.forget(aThread);
 
   return NS_OK;
 }
 
+RefPtr<AbstractThread>
+GeckoMediaPluginService::GetAbstractGMPThread()
+{
+  return mAbstractGMPThread;
+}
+
 class GetGMPContentParentForAudioDecoderDone : public GetGMPContentParentCallback
 {
 public:
   explicit GetGMPContentParentForAudioDecoderDone(UniquePtr<GetGMPAudioDecoderCallback>&& aCallback)
    : mCallback(Move(aCallback))
   {
   }
 
--- a/dom/media/gmp/GMPService.h
+++ b/dom/media/gmp/GMPService.h
@@ -14,16 +14,17 @@
 #include "mozilla/Monitor.h"
 #include "nsString.h"
 #include "nsCOMPtr.h"
 #include "nsIThread.h"
 #include "nsThreadUtils.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDocument.h"
 #include "nsIWeakReference.h"
+#include "mozilla/AbstractThread.h"
 
 template <class> struct already_AddRefed;
 
 namespace mozilla {
 
 extern LogModule* GetGMPLog();
 
 namespace gmp {
@@ -69,16 +70,18 @@ public:
                                const nsACString& aPluginName);
 
   // Sets the window to which 'PluginCrashed' chromeonly event is dispatched.
   // Note: if the plugin has crashed before the target window has been set,
   // the 'PluginCrashed' event is dispatched as soon as a target window is set.
   void AddPluginCrashedEventTarget(const uint32_t aPluginId,
                                    nsPIDOMWindowInner* aParentWindow);
 
+  RefPtr<AbstractThread> GetAbstractGMPThread();
+
 protected:
   GeckoMediaPluginService();
   virtual ~GeckoMediaPluginService();
 
   void RemoveObsoletePluginCrashCallbacks(); // Called from add/run.
 
   virtual void InitializePlugins() = 0;
   virtual bool GetContentParentFrom(const nsACString& aNodeId,
@@ -87,16 +90,17 @@ protected:
                                     UniquePtr<GetGMPContentParentCallback>&& aCallback) = 0;
 
   nsresult GMPDispatch(nsIRunnable* event, uint32_t flags = NS_DISPATCH_NORMAL);
   void ShutdownGMPThread();
 
   Mutex mMutex; // Protects mGMPThread and mGMPThreadShutdown and some members
                 // in derived classes.
   nsCOMPtr<nsIThread> mGMPThread;
+  RefPtr<AbstractThread> mAbstractGMPThread;
   bool mGMPThreadShutdown;
   bool mShuttingDownOnGMPThread;
 
   class GMPCrashCallback
   {
   public:
     NS_INLINE_DECL_REFCOUNTING(GMPCrashCallback)
 
--- a/dom/media/platforms/agnostic/eme/EMEDecoderModule.cpp
+++ b/dom/media/platforms/agnostic/eme/EMEDecoderModule.cpp
@@ -156,18 +156,21 @@ private:
   RefPtr<CDMProxy> mProxy;
   nsClassHashtable<nsRefPtrHashKey<MediaRawData>, DecryptPromiseRequestHolder> mDecrypts;
   RefPtr<SamplesWaitingForKey> mSamplesWaitingForKey;
   bool mIsShutdown;
 };
 
 class EMEMediaDataDecoderProxy : public MediaDataDecoderProxy {
 public:
-  EMEMediaDataDecoderProxy(nsIThread* aProxyThread, MediaDataDecoderCallback* aCallback, CDMProxy* aProxy, FlushableTaskQueue* aTaskQueue)
-   : MediaDataDecoderProxy(aProxyThread, aCallback)
+  EMEMediaDataDecoderProxy(already_AddRefed<AbstractThread> aProxyThread,
+                           MediaDataDecoderCallback* aCallback,
+                           CDMProxy* aProxy,
+                           FlushableTaskQueue* aTaskQueue)
+   : MediaDataDecoderProxy(Move(aProxyThread), aCallback)
    , mSamplesWaitingForKey(new SamplesWaitingForKey(this, aTaskQueue, aProxy))
    , mProxy(aProxy)
   {
   }
 
   nsresult Input(MediaRawData* aSample) override;
   nsresult Shutdown() override;
 
@@ -215,28 +218,26 @@ EMEDecoderModule::EMEDecoderModule(CDMPr
 
 EMEDecoderModule::~EMEDecoderModule()
 {
 }
 
 static already_AddRefed<MediaDataDecoderProxy>
 CreateDecoderWrapper(MediaDataDecoderCallback* aCallback, CDMProxy* aProxy, FlushableTaskQueue* aTaskQueue)
 {
-  nsCOMPtr<mozIGeckoMediaPluginService> gmpService = do_GetService("@mozilla.org/gecko-media-plugin-service;1");
-  if (!gmpService) {
+  RefPtr<gmp::GeckoMediaPluginService> s(gmp::GeckoMediaPluginService::GetGeckoMediaPluginService());
+  if (!s) {
     return nullptr;
   }
-
-  nsCOMPtr<nsIThread> thread;
-  nsresult rv = gmpService->GetThread(getter_AddRefs(thread));
-  if (NS_FAILED(rv)) {
+  RefPtr<AbstractThread> thread(s->GetAbstractGMPThread());
+  if (!thread) {
     return nullptr;
   }
-
-  RefPtr<MediaDataDecoderProxy> decoder(new EMEMediaDataDecoderProxy(thread, aCallback, aProxy, aTaskQueue));
+  RefPtr<MediaDataDecoderProxy> decoder(
+    new EMEMediaDataDecoderProxy(thread.forget(), aCallback, aProxy, aTaskQueue));
   return decoder.forget();
 }
 
 already_AddRefed<MediaDataDecoder>
 EMEDecoderModule::CreateVideoDecoder(const VideoInfo& aConfig,
                                      layers::LayersBackend aLayersBackend,
                                      layers::ImageContainer* aImageContainer,
                                      FlushableTaskQueue* aVideoTaskQueue,
--- a/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp
+++ b/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp
@@ -26,28 +26,25 @@ GMPDecoderModule::GMPDecoderModule()
 
 GMPDecoderModule::~GMPDecoderModule()
 {
 }
 
 static already_AddRefed<MediaDataDecoderProxy>
 CreateDecoderWrapper(MediaDataDecoderCallback* aCallback)
 {
-  nsCOMPtr<mozIGeckoMediaPluginService> gmpService = do_GetService("@mozilla.org/gecko-media-plugin-service;1");
-  if (!gmpService) {
+  RefPtr<gmp::GeckoMediaPluginService> s(gmp::GeckoMediaPluginService::GetGeckoMediaPluginService());
+  if (!s) {
     return nullptr;
   }
-
-  nsCOMPtr<nsIThread> thread;
-  nsresult rv = gmpService->GetThread(getter_AddRefs(thread));
-  if (NS_FAILED(rv)) {
+  RefPtr<AbstractThread> thread(s->GetAbstractGMPThread());
+  if (!thread) {
     return nullptr;
   }
-
-  RefPtr<MediaDataDecoderProxy> decoder(new MediaDataDecoderProxy(thread, aCallback));
+  RefPtr<MediaDataDecoderProxy> decoder(new MediaDataDecoderProxy(thread.forget(), aCallback));
   return decoder.forget();
 }
 
 already_AddRefed<MediaDataDecoder>
 GMPDecoderModule::CreateVideoDecoder(const VideoInfo& aConfig,
                                      layers::LayersBackend aLayersBackend,
                                      layers::ImageContainer* aImageContainer,
                                      FlushableTaskQueue* aVideoTaskQueue,
--- a/dom/media/platforms/agnostic/gmp/MediaDataDecoderProxy.cpp
+++ b/dom/media/platforms/agnostic/gmp/MediaDataDecoderProxy.cpp
@@ -29,75 +29,72 @@ MediaDataDecoderProxy::InternalInit()
   return mProxyDecoder->Init();
 }
 
 RefPtr<MediaDataDecoder::InitPromise>
 MediaDataDecoderProxy::Init()
 {
   MOZ_ASSERT(!mIsShutdown);
 
-  return InvokeAsync(mProxyThreadWrapper, this, __func__,
+  return InvokeAsync(mProxyThread, this, __func__,
                      &MediaDataDecoderProxy::InternalInit);
 }
 
 nsresult
 MediaDataDecoderProxy::Input(MediaRawData* aSample)
 {
   MOZ_ASSERT(!IsOnProxyThread());
   MOZ_ASSERT(!mIsShutdown);
 
   nsCOMPtr<nsIRunnable> task(new InputTask(mProxyDecoder, aSample));
-  nsresult rv = mProxyThread->Dispatch(task, NS_DISPATCH_NORMAL);
-  NS_ENSURE_SUCCESS(rv, rv);
+  mProxyThread->Dispatch(task.forget());
 
   return NS_OK;
 }
 
 nsresult
 MediaDataDecoderProxy::Flush()
 {
   MOZ_ASSERT(!IsOnProxyThread());
   MOZ_ASSERT(!mIsShutdown);
 
   mFlushComplete.Set(false);
 
   nsCOMPtr<nsIRunnable> task;
   task = NS_NewRunnableMethod(mProxyDecoder, &MediaDataDecoder::Flush);
-  nsresult rv = mProxyThread->Dispatch(task, NS_DISPATCH_NORMAL);
-  NS_ENSURE_SUCCESS(rv, rv);
+  mProxyThread->Dispatch(task.forget());
 
   mFlushComplete.WaitUntil(true);
 
   return NS_OK;
 }
 
 nsresult
 MediaDataDecoderProxy::Drain()
 {
   MOZ_ASSERT(!IsOnProxyThread());
   MOZ_ASSERT(!mIsShutdown);
 
   nsCOMPtr<nsIRunnable> task;
   task = NS_NewRunnableMethod(mProxyDecoder, &MediaDataDecoder::Drain);
-  nsresult rv = mProxyThread->Dispatch(task, NS_DISPATCH_NORMAL);
-  NS_ENSURE_SUCCESS(rv, rv);
+  mProxyThread->Dispatch(task.forget());
   return NS_OK;
 }
 
 nsresult
 MediaDataDecoderProxy::Shutdown()
 {
   // Note that this *may* be called from the proxy thread also.
   MOZ_ASSERT(!mIsShutdown);
 #if defined(DEBUG)
   mIsShutdown = true;
 #endif
   nsCOMPtr<nsIRunnable> task;
   task = NS_NewRunnableMethod(mProxyDecoder, &MediaDataDecoder::Shutdown);
-  nsresult rv = mProxyThread->Dispatch(task, NS_DISPATCH_SYNC);
+  nsresult rv = mProxyThread->AsXPCOMThread()->Dispatch(task, NS_DISPATCH_SYNC);
   NS_ENSURE_SUCCESS(rv, rv);
   return NS_OK;
 }
 
 void
 MediaDataDecoderProxy::FlushComplete()
 {
   mFlushComplete.Set(true);
--- a/dom/media/platforms/agnostic/gmp/MediaDataDecoderProxy.h
+++ b/dom/media/platforms/agnostic/gmp/MediaDataDecoderProxy.h
@@ -6,16 +6,17 @@
 
 #if !defined(MediaDataDecoderProxy_h_)
 #define MediaDataDecoderProxy_h_
 
 #include "PlatformDecoderModule.h"
 #include "mozilla/RefPtr.h"
 #include "nsThreadUtils.h"
 #include "nscore.h"
+#include "GMPService.h"
 
 namespace mozilla {
 
 class InputTask : public nsRunnable {
 public:
   InputTask(MediaDataDecoder* aDecoder,
             MediaRawData* aSample)
    : mDecoder(aDecoder)
@@ -57,17 +58,18 @@ private:
   Monitor mMonitor;
   T mCondition;
 };
 
 class MediaDataDecoderProxy;
 
 class MediaDataDecoderCallbackProxy : public MediaDataDecoderCallback {
 public:
-  MediaDataDecoderCallbackProxy(MediaDataDecoderProxy* aProxyDecoder, MediaDataDecoderCallback* aCallback)
+  MediaDataDecoderCallbackProxy(MediaDataDecoderProxy* aProxyDecoder,
+                                MediaDataDecoderCallback* aCallback)
    : mProxyDecoder(aProxyDecoder)
    , mProxyCallback(aCallback)
   {
   }
 
   void Output(MediaData* aData) override {
     mProxyCallback->Output(aData);
   }
@@ -95,25 +97,25 @@ public:
 
 private:
   MediaDataDecoderProxy* mProxyDecoder;
   MediaDataDecoderCallback* mProxyCallback;
 };
 
 class MediaDataDecoderProxy : public MediaDataDecoder {
 public:
-  MediaDataDecoderProxy(nsIThread* aProxyThread, MediaDataDecoderCallback* aCallback)
+  MediaDataDecoderProxy(already_AddRefed<AbstractThread> aProxyThread,
+                        MediaDataDecoderCallback* aCallback)
    : mProxyThread(aProxyThread)
    , mProxyCallback(this, aCallback)
    , mFlushComplete(false)
 #if defined(DEBUG)
    , mIsShutdown(false)
 #endif
   {
-    mProxyThreadWrapper = CreateXPCOMAbstractThreadWrapper(aProxyThread, false);
   }
 
   // Ideally, this would return a regular MediaDataDecoderCallback pointer
   // to retain the clean abstraction, but until MediaDataDecoderCallback
   // supports the FlushComplete interface, this will have to do.  When MDDC
   // supports FlushComplete, this, the GMP*Decoders, and the
   // *CallbackAdapters can be reverted to accepting a regular
   // MediaDataDecoderCallback pointer.
@@ -146,26 +148,25 @@ public:
   // Called by MediaDataDecoderCallbackProxy.
   void FlushComplete();
 
 private:
   RefPtr<InitPromise> InternalInit();
 
 #ifdef DEBUG
   bool IsOnProxyThread() {
-    return NS_GetCurrentThread() == mProxyThread;
+    return mProxyThread && mProxyThread->IsCurrentThreadIn();
   }
 #endif
 
   friend class InputTask;
   friend class InitTask;
 
   RefPtr<MediaDataDecoder> mProxyDecoder;
-  nsCOMPtr<nsIThread> mProxyThread;
-  RefPtr<AbstractThread> mProxyThreadWrapper;
+  RefPtr<AbstractThread> mProxyThread;
 
   MediaDataDecoderCallbackProxy mProxyCallback;
 
   Condition<bool> mFlushComplete;
 #if defined(DEBUG)
   bool mIsShutdown;
 #endif
 };