Bug 1277626 - Create test DXVA decoders on the main thread so that we can protect them with a crash guard. r=jya,dvander
authorMatt Woodrow <mwoodrow@mozilla.com>
Mon, 25 Jul 2016 15:18:55 +1200
changeset 331675 6047635058edf8b297698f4b1bb182f0d00bf2f1
parent 331674 5adee976c6cc1693a6327abe9cca29a42111a0ce
child 331676 d15df91ece8112498ebe8a70c3df28cd1d2bb9e6
push id9858
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 14:37:10 +0000
treeherdermozilla-aurora@203106ef6cb6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjya, dvander
bugs1277626
milestone50.0a1
Bug 1277626 - Create test DXVA decoders on the main thread so that we can protect them with a crash guard. r=jya,dvander
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
@@ -186,16 +186,23 @@ static const GUID DXVA2_Intel_ModeH264_E
 
 // This tests if a DXVA video decoder can be created for the given media type/resolution.
 // It uses the same decoder device (DXVA2_ModeH264_E - DXVA2_ModeH264_VLD_NoFGT) as the H264
 // decoder MFT provided by windows (CLSID_CMSH264DecoderMFT) uses, so we can use it to determine
 // if the MFT will use software fallback or not.
 bool
 D3D9DXVA2Manager::SupportsConfig(IMFMediaType* aType, float aFramerate)
 {
+  MOZ_ASSERT(NS_IsMainThread());
+  gfx::D3D9VideoCrashGuard crashGuard;
+  if (crashGuard.Crashed()) {
+    NS_WARNING("DXVA2D3D9 crash detected");
+    return false;
+  }
+
   DXVA2_VideoDesc desc;
   HRESULT hr = ConvertMFTypeToDXVAType(aType, &desc);
   NS_ENSURE_TRUE(SUCCEEDED(hr), false);
 
   // AMD cards with UVD3 or earlier perform poorly trying to decode 1080p60 in hardware,
   // so use software instead. Pick 45 as an arbitrary upper bound for the framerate we can
   // handle.
   if (mIsAMDPreUVD4 &&
@@ -537,16 +544,23 @@ private:
   uint32_t mHeight;
   UINT mDeviceManagerToken;
   bool mIsAMDPreUVD4;
 };
 
 bool
 D3D11DXVA2Manager::SupportsConfig(IMFMediaType* aType, float aFramerate)
 {
+  MOZ_ASSERT(NS_IsMainThread());
+  gfx::D3D11VideoCrashGuard crashGuard;
+  if (crashGuard.Crashed()) {
+    NS_WARNING("DXVA2D3D9 crash detected");
+    return false;
+  }
+
   RefPtr<ID3D11VideoDevice> videoDevice;
   HRESULT hr = mDevice->QueryInterface(static_cast<ID3D11VideoDevice**>(getter_AddRefs(videoDevice)));
   NS_ENSURE_TRUE(SUCCEEDED(hr), false);
 
   D3D11_VIDEO_DECODER_DESC desc;
   desc.Guid = mDecoderGUID;
 
   UINT32 width = 0;
--- a/dom/media/platforms/wmf/WMFVideoMFTManager.cpp
+++ b/dom/media/platforms/wmf/WMFVideoMFTManager.cpp
@@ -494,41 +494,76 @@ WMFVideoMFTManager::Input(MediaRawData* 
   NS_ENSURE_TRUE(SUCCEEDED(hr) && mLastInput != nullptr, hr);
 
   mLastDuration = aSample->mDuration;
 
   // Forward sample data to the decoder.
   return mDecoder->Input(mLastInput);
 }
 
+class SupportsConfigEvent : public Runnable {
+public:
+  SupportsConfigEvent(DXVA2Manager* aDXVA2Manager, IMFMediaType* aMediaType, float aFramerate)
+    : mDXVA2Manager(aDXVA2Manager)
+    , mMediaType(aMediaType)
+    , mFramerate(aFramerate)
+    , mSupportsConfig(false)
+  {}
+
+  NS_IMETHOD Run() {
+    MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
+    mSupportsConfig = mDXVA2Manager->SupportsConfig(mMediaType, mFramerate);
+    return NS_OK;
+  }
+  DXVA2Manager* mDXVA2Manager;
+  IMFMediaType* mMediaType;
+  float mFramerate;
+  bool mSupportsConfig;
+};
+
 // The MFTransform we use for decoding h264 video will silently fall
 // back to software decoding (even if we've negotiated DXVA) if the GPU
 // doesn't support decoding the given resolution. It will then upload
 // the software decoded frames into d3d textures to preserve behaviour.
 //
 // Unfortunately this seems to cause corruption (see bug 1193547) and is
 // slow because the upload is done into a non-shareable texture and requires
 // us to copy it.
 //
 // This code tests if the given resolution can be supported directly on the GPU,
 // and makes sure we only ask the MFT for DXVA if it can be supported properly.
+//
+// Ideally we'd know the framerate during initialization and would also ensure
+// that new decoders are created if the resolution changes. Then we could move
+// this check into Init and consolidate the main thread blocking code.
 bool
 WMFVideoMFTManager::CanUseDXVA(IMFMediaType* aType)
 {
   MOZ_ASSERT(mDXVA2Manager);
   // SupportsConfig only checks for valid h264 decoders currently.
   if (mStreamType != H264) {
     return true;
   }
 
   // Assume the current samples duration is representative for the
   // entire video.
   float framerate = 1000000.0 / mLastDuration;
 
-  return mDXVA2Manager->SupportsConfig(aType, framerate);
+  // The supports config check must be done on the main thread since we have
+  // a crash guard protecting it.
+  RefPtr<SupportsConfigEvent> event =
+    new SupportsConfigEvent(mDXVA2Manager, aType, framerate);
+
+  if (NS_IsMainThread()) {
+    event->Run();
+  } else {
+    NS_DispatchToMainThread(event, NS_DISPATCH_SYNC);
+  }
+
+  return event->mSupportsConfig;
 }
 
 HRESULT
 WMFVideoMFTManager::ConfigureVideoFrameGeometry()
 {
   RefPtr<IMFMediaType> mediaType;
   HRESULT hr = mDecoder->GetOutputMediaType(mediaType);
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);