Bug 1271491: [WMF] P2. Allow creation of DXVA manager on any thread. r?cpearce draft
authorJean-Yves Avenard <jyavenard@mozilla.com>
Tue, 10 May 2016 14:45:40 +1000
changeset 366280 c5a8a8c7727c43301d8339d56630bb0f72a35b9c
parent 366279 f2aa7fea1630ea167dc8aa4c2a548dddba448e23
child 366281 ce0780e57849cdecf6f826bda709494844a41d66
push id17951
push userbmo:jyavenard@mozilla.com
push dateThu, 12 May 2016 11:23:16 +0000
reviewerscpearce
bugs1271491
milestone49.0a1
Bug 1271491: [WMF] P2. Allow creation of DXVA manager on any thread. r?cpearce MozReview-Commit-ID: 8sbA3x0Pge5
dom/media/platforms/wmf/DXVA2Manager.cpp
dom/media/platforms/wmf/WMFVideoMFTManager.cpp
--- a/dom/media/platforms/wmf/DXVA2Manager.cpp
+++ b/dom/media/platforms/wmf/DXVA2Manager.cpp
@@ -7,16 +7,17 @@
 #include "DXVA2Manager.h"
 #include <d3d11.h>
 #include "nsThreadUtils.h"
 #include "ImageContainer.h"
 #include "gfxWindowsPlatform.h"
 #include "D3D9SurfaceImage.h"
 #include "mozilla/layers/D3D11ShareHandleImage.h"
 #include "mozilla/layers/ImageBridgeChild.h"
+#include "mozilla/StaticMutex.h"
 #include "mozilla/Telemetry.h"
 #include "MediaTelemetryConstants.h"
 #include "mfapi.h"
 #include "MediaPrefs.h"
 #include "MFTDecoder.h"
 #include "DriverCrashGuard.h"
 #include "nsPrintfCString.h"
 
@@ -231,37 +232,33 @@ D3D9DXVA2Manager::SupportsConfig(IMFMedi
 }
 
 D3D9DXVA2Manager::D3D9DXVA2Manager()
   : mResetToken(0)
   , mFirstFrame(true)
   , mIsAMDPreUVD4(false)
 {
   MOZ_COUNT_CTOR(D3D9DXVA2Manager);
-  MOZ_ASSERT(NS_IsMainThread());
 }
 
 D3D9DXVA2Manager::~D3D9DXVA2Manager()
 {
   MOZ_COUNT_DTOR(D3D9DXVA2Manager);
-  MOZ_ASSERT(NS_IsMainThread());
 }
 
 IUnknown*
 D3D9DXVA2Manager::GetDXVADeviceManager()
 {
   MutexAutoLock lock(mLock);
   return mDeviceManager;
 }
 
 HRESULT
 D3D9DXVA2Manager::Init(nsACString& aFailureReason)
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
   gfx::D3D9VideoCrashGuard crashGuard;
   if (crashGuard.Crashed()) {
     NS_WARNING("DXVA2D3D9 crash detected");
     aFailureReason.AssignLiteral("DXVA2D3D9 crashes detected in the past");
     return E_FAIL;
   }
 
   // Create D3D9Ex.
@@ -458,38 +455,39 @@ D3D9DXVA2Manager::CopyToImage(IMFSample*
   hr = mSyncSurface->UnlockRect();
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
   image.forget(aOutImage);
   return S_OK;
 }
 
 // Count of the number of DXVAManager's we've created. This is also the
-// number of videos we're decoding with DXVA. Use on main thread only.
+// number of videos we're decoding with DXVA.
+static StaticMutex sMutex;
 static uint32_t sDXVAVideosCount = 0;
 
 /* static */
 DXVA2Manager*
 DXVA2Manager::CreateD3D9DXVA(nsACString& aFailureReason)
 {
-  MOZ_ASSERT(NS_IsMainThread());
-  HRESULT hr;
-
+  nsAutoPtr<D3D9DXVA2Manager> d3d9Manager;
   // DXVA processing takes up a lot of GPU resources, so limit the number of
   // videos we use DXVA with at any one time.
   const uint32_t dxvaLimit = MediaPrefs::PDMWMFMaxDXVAVideos();
-  if (sDXVAVideosCount == dxvaLimit) {
-    aFailureReason.AssignLiteral("Too many DXVA videos playing");
-    return nullptr;
-  }
-
-  nsAutoPtr<D3D9DXVA2Manager> d3d9Manager(new D3D9DXVA2Manager());
-  hr = d3d9Manager->Init(aFailureReason);
-  if (SUCCEEDED(hr)) {
-    return d3d9Manager.forget();
+  {
+    StaticMutexAutoLock mon(sMutex);
+    if (sDXVAVideosCount == dxvaLimit) {
+      aFailureReason.AssignLiteral("Too many DXVA videos playing");
+      return nullptr;
+    }
+    d3d9Manager = new D3D9DXVA2Manager();
+    HRESULT hr = d3d9Manager->Init(aFailureReason);
+    if (SUCCEEDED(hr)) {
+      return d3d9Manager.forget();
+    }
   }
 
   // No hardware accelerated video decoding. :(
   return nullptr;
 }
 
 class D3D11DXVA2Manager : public DXVA2Manager
 {
@@ -865,37 +863,41 @@ D3D11DXVA2Manager::ConfigureForSize(uint
 
   return S_OK;
 }
 
 /* static */
 DXVA2Manager*
 DXVA2Manager::CreateD3D11DXVA(nsACString& aFailureReason)
 {
+  nsAutoPtr<D3D11DXVA2Manager> manager;
   // DXVA processing takes up a lot of GPU resources, so limit the number of
   // videos we use DXVA with at any one time.
   const uint32_t dxvaLimit = MediaPrefs::PDMWMFMaxDXVAVideos();
-  if (sDXVAVideosCount == dxvaLimit) {
-    aFailureReason.AssignLiteral("Too many DXVA videos playing");
-    return nullptr;
+  {
+    StaticMutexAutoLock mon(sMutex);
+    if (sDXVAVideosCount == dxvaLimit) {
+      aFailureReason.AssignLiteral("Too many DXVA videos playing");
+      return nullptr;
+    }
+    manager = new D3D11DXVA2Manager();
+    HRESULT hr = manager->Init(aFailureReason);
+    if (SUCCEEDED(hr)) {
+      return manager.forget();
+    }
   }
-
-  nsAutoPtr<D3D11DXVA2Manager> manager(new D3D11DXVA2Manager());
-  HRESULT hr = manager->Init(aFailureReason);
-  NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
-
-  return manager.forget();
+  return nullptr;
 }
 
 DXVA2Manager::DXVA2Manager()
   : mLock("DXVA2Manager")
 {
-  MOZ_ASSERT(NS_IsMainThread());
+  sMutex.AssertCurrentThreadOwns();
   ++sDXVAVideosCount;
 }
 
 DXVA2Manager::~DXVA2Manager()
 {
-  MOZ_ASSERT(NS_IsMainThread());
+  StaticMutexAutoLock mon(sMutex);
   --sDXVAVideosCount;
 }
 
 } // namespace mozilla
--- a/dom/media/platforms/wmf/WMFVideoMFTManager.cpp
+++ b/dom/media/platforms/wmf/WMFVideoMFTManager.cpp
@@ -101,20 +101,16 @@ WMFVideoMFTManager::WMFVideoMFTManager(
   } else {
     mStreamType = Unknown;
   }
 }
 
 WMFVideoMFTManager::~WMFVideoMFTManager()
 {
   MOZ_COUNT_DTOR(WMFVideoMFTManager);
-  // Ensure DXVA/D3D9 related objects are released on the main thread.
-  if (mDXVA2Manager) {
-    DeleteOnMainThread(mDXVA2Manager);
-  }
 
   // Record whether the video decoder successfully decoded, or output null
   // samples but did/didn't recover.
   uint32_t telemetry = (mNullOutputCount == 0) ? 0 :
                        (mGotValidOutputAfterNullOutput && mGotExcessiveNullOutput) ? 1 :
                        mGotExcessiveNullOutput ? 2 :
                        mGotValidOutputAfterNullOutput ? 3 :
                        4;
@@ -660,17 +656,17 @@ WMFVideoMFTManager::Output(int64_t aStre
 
   return S_OK;
 }
 
 void
 WMFVideoMFTManager::Shutdown()
 {
   mDecoder = nullptr;
-  DeleteOnMainThread(mDXVA2Manager);
+  mDXVA2Manager = nullptr;
 }
 
 bool
 WMFVideoMFTManager::IsHardwareAccelerated(nsACString& aFailureReason) const
 {
   aFailureReason = mDXVAFailureReason;
   return mDecoder && mUseHwAccel;
 }