Bug 1397141 - part2 : move resolution constraints to WMFVideoMFTManager draft
authorAlastor Wu <alwu@mozilla.com>
Wed, 13 Sep 2017 15:05:37 +0800
changeset 663587 e086c9d40284ae523489ee04b0e1505115a8a3b5
parent 663586 8f8659fc37a21ed94c39535c91ca3d1d06554174
child 663588 eeb2767b126c0662614dfccd9ee2a0a071a11751
push id79482
push useralwu@mozilla.com
push dateWed, 13 Sep 2017 07:06:40 +0000
bugs1397141
milestone57.0a1
Bug 1397141 - part2 : move resolution constraints to WMFVideoMFTManager WMFDecoderModule should only focus on whether the mime type is supported or not. Let WMFVideoMFTManager do the checking. MozReview-Commit-ID: K6jPfrntu7s
dom/media/MediaPrefs.h
dom/media/platforms/wmf/WMFDecoderModule.cpp
dom/media/platforms/wmf/WMFVideoMFTManager.cpp
gfx/thebes/gfxPrefs.h
--- a/dom/media/MediaPrefs.h
+++ b/dom/media/MediaPrefs.h
@@ -134,17 +134,16 @@ private:
   DECL_MEDIA_PREF("media.ffvpx.enabled",                      PDMFFVPXEnabled, bool, true);
 #endif
 #ifdef XP_WIN
   DECL_MEDIA_PREF("media.wmf.enabled",                        PDMWMFEnabled, bool, true);
   DECL_MEDIA_PREF("media.wmf.skip-blacklist",                 PDMWMFSkipBlacklist, bool, false);
   DECL_MEDIA_PREF("media.decoder-doctor.wmf-disabled-is-failure", DecoderDoctorWMFDisabledIsFailure, bool, false);
   DECL_MEDIA_PREF("media.wmf.vp9.enabled",                    PDMWMFVP9DecoderEnabled, bool, true);
   DECL_MEDIA_PREF("media.wmf.decoder.thread-count",           PDMWMFThreadCount, int32_t, -1);
-  DECL_MEDIA_PREF("media.wmf.allow-unsupported-resolutions",  PDMWMFAllowUnsupportedResolutions, bool, false);
 #endif
   DECL_MEDIA_PREF("media.decoder.fuzzing.enabled",            PDMFuzzingEnabled, bool, false);
   DECL_MEDIA_PREF("media.decoder.fuzzing.video-output-minimum-interval-ms", PDMFuzzingInterval, uint32_t, 0);
   DECL_MEDIA_PREF("media.decoder.fuzzing.dont-delay-inputexhausted", PDMFuzzingDelayInputExhausted, bool, true);
   DECL_MEDIA_PREF("media.decoder.recycle.enabled",            MediaDecoderCheckRecycling, bool, false);
   DECL_MEDIA_PREF("media.decoder.skip-to-next-key-frame.enabled", MFRSkipToNextKeyFrameEnabled, bool, true);
   DECL_MEDIA_PREF("media.gmp.decoder.enabled",                PDMGMPEnabled, bool, true);
   DECL_MEDIA_PREF("media.gmp.decoder.aac",                    GMPAACPreferred, uint32_t, 0);
--- a/dom/media/platforms/wmf/WMFDecoderModule.cpp
+++ b/dom/media/platforms/wmf/WMFDecoderModule.cpp
@@ -168,48 +168,16 @@ CanCreateWMFDecoder()
   StaticMutexAutoLock lock(sMutex);
   static Maybe<bool> result;
   if (result.isNothing()) {
     result.emplace(CanCreateMFTDecoder(aGuid));
   }
   return result.value();
 }
 
-static bool
-IsWin7H264Decoder4KCapable()
-{
-  WCHAR systemPath[MAX_PATH + 1];
-  if (!ConstructSystem32Path(L"msmpeg2vdec.dll", systemPath, MAX_PATH + 1)) {
-    // Cannot build path -> Assume it's the old DLL or it's missing.
-    return false;
-  }
-
-  DWORD zero;
-  DWORD infoSize = GetFileVersionInfoSizeW(systemPath, &zero);
-  if (infoSize == 0) {
-    // Can't get file info -> Assume it's the old DLL or it's missing.
-    return false;
-  }
-  auto infoData = MakeUnique<unsigned char[]>(infoSize);
-  VS_FIXEDFILEINFO *vInfo;
-  UINT vInfoLen;
-  if (GetFileVersionInfoW(systemPath, 0, infoSize, infoData.get()) &&
-    VerQueryValueW(infoData.get(), L"\\", (LPVOID*)&vInfo, &vInfoLen))
-  {
-    uint64_t version =
-      uint64_t(vInfo->dwFileVersionMS) << 32 | uint64_t(vInfo->dwFileVersionLS);
-    // 12.0.9200.16426 & later allow for >1920x1088 resolutions.
-    const uint64_t minimum =
-      (uint64_t(12) << 48) | (uint64_t(9200) << 16) | uint64_t(16426);
-    return version >= minimum;
-  }
-  // Can't get file version -> Assume it's the old DLL.
-  return false;
-}
-
 /* static */ bool
 WMFDecoderModule::HasH264()
 {
   return CanCreateWMFDecoder<CLSID_CMSH264DecoderMFT>();
 }
 
 /* static */ bool
 WMFDecoderModule::HasAAC()
@@ -234,34 +202,16 @@ WMFDecoderModule::Supports(const TrackIn
                            DecoderDoctorDiagnostics* aDiagnostics) const
 {
   if ((aTrackInfo.mMimeType.EqualsLiteral("audio/mp4a-latm") ||
        aTrackInfo.mMimeType.EqualsLiteral("audio/mp4")) &&
        WMFDecoderModule::HasAAC()) {
     return true;
   }
   if (MP4Decoder::IsH264(aTrackInfo.mMimeType) && WMFDecoderModule::HasH264()) {
-    if (!MediaPrefs::PDMWMFAllowUnsupportedResolutions()) {
-      const VideoInfo* videoInfo = aTrackInfo.GetAsVideoInfo();
-      MOZ_ASSERT(videoInfo);
-      // Check Windows format constraints, based on:
-      // https://msdn.microsoft.com/en-us/library/windows/desktop/dd797815(v=vs.85).aspx
-      if (IsWin8OrLater() || IsWin7H264Decoder4KCapable()) {
-        // Windows >7, and Win7 with recent-enough decoder, support at most
-        // 4096x2304.
-        if (videoInfo->mImage.width > 4096 || videoInfo->mImage.height > 2304) {
-          return false;
-        }
-      } else {
-        // Windows <=7 (with original decoder) supports at most 1920x1088.
-        if (videoInfo->mImage.width > 1920 || videoInfo->mImage.height > 1088) {
-          return false;
-        }
-      }
-    }
     return true;
   }
   if (aTrackInfo.mMimeType.EqualsLiteral("audio/mpeg") &&
       CanCreateWMFDecoder<CLSID_CMP3DecMediaObject>()) {
     return true;
   }
   if (MediaPrefs::PDMWMFVP9DecoderEnabled()) {
     if ((VPXDecoder::IsVP8(aTrackInfo.mMimeType) ||
--- a/dom/media/platforms/wmf/WMFVideoMFTManager.cpp
+++ b/dom/media/platforms/wmf/WMFVideoMFTManager.cpp
@@ -94,16 +94,48 @@ extern const GUID CLSID_WebmMfVpxDec =
   0xe3aaf548,
   0xc9a4,
   0x4c6e,
   { 0x23, 0x4d, 0x5a, 0xda, 0x37, 0x4b, 0x00, 0x00 }
 };
 
 namespace mozilla {
 
+static bool
+IsWin7H264Decoder4KCapable()
+{
+  WCHAR systemPath[MAX_PATH + 1];
+  if (!ConstructSystem32Path(L"msmpeg2vdec.dll", systemPath, MAX_PATH + 1)) {
+    // Cannot build path -> Assume it's the old DLL or it's missing.
+    return false;
+  }
+
+  DWORD zero;
+  DWORD infoSize = GetFileVersionInfoSizeW(systemPath, &zero);
+  if (infoSize == 0) {
+    // Can't get file info -> Assume it's the old DLL or it's missing.
+    return false;
+  }
+  auto infoData = MakeUnique<unsigned char[]>(infoSize);
+  VS_FIXEDFILEINFO *vInfo;
+  UINT vInfoLen;
+  if (GetFileVersionInfoW(systemPath, 0, infoSize, infoData.get()) &&
+    VerQueryValueW(infoData.get(), L"\\", (LPVOID*)&vInfo, &vInfoLen))
+  {
+    uint64_t version =
+      uint64_t(vInfo->dwFileVersionMS) << 32 | uint64_t(vInfo->dwFileVersionLS);
+    // 12.0.9200.16426 & later allow for >1920x1088 resolutions.
+    const uint64_t minimum =
+      (uint64_t(12) << 48) | (uint64_t(9200) << 16) | uint64_t(16426);
+    return version >= minimum;
+  }
+  // Can't get file version -> Assume it's the old DLL.
+  return false;
+}
+
 template<class T>
 class DeleteObjectTask: public Runnable {
 public:
   explicit DeleteObjectTask(nsAutoPtr<T>& aObject)
     : Runnable("VideoUtils::DeleteObjectTask")
     , mObject(aObject)
   {
   }
@@ -521,32 +553,49 @@ WMFVideoMFTManager::InitializeDXVA()
   mDXVA2Manager = event->mDXVA2Manager;
 
   return mDXVA2Manager != nullptr;
 }
 
 MediaResult
 WMFVideoMFTManager::ValidateVideoInfo()
 {
+  if (mStreamType != H264 ||
+      gfxPrefs::PDMWMFAllowUnsupportedResolutions()) {
+    return NS_OK;
+  }
+
   // The WMF H.264 decoder is documented to have a minimum resolution
   // 48x48 pixels. We've observed the decoder working for output smaller than
   // that, but on some output it hangs in IMFTransform::ProcessOutput(), so
   // we just reject streams which are less than the documented minimum.
   // https://msdn.microsoft.com/en-us/library/windows/desktop/dd797815(v=vs.85).aspx
+  const bool Is4KCapable = IsWin8OrLater() || IsWin7H264Decoder4KCapable();
   static const int32_t MIN_H264_FRAME_DIMENSION = 48;
+  static const int32_t MAX_H264_FRAME_WIDTH = Is4KCapable ? 4096 : 1920;
+  static const int32_t MAX_H264_FRAME_HEIGHT = Is4KCapable ? 2304 : 1088;
+
   if (mStreamType == H264 &&
       (mVideoInfo.mImage.width < MIN_H264_FRAME_DIMENSION ||
        mVideoInfo.mImage.height < MIN_H264_FRAME_DIMENSION)) {
     mIsValid = false;
     return MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
                        RESULT_DETAIL("Can't decode H.264 stream with width or "
                                      "height less than 48 pixels."));
   }
 
-  return MediaResult(NS_OK);
+  if (mVideoInfo.mImage.width > MAX_H264_FRAME_WIDTH  ||
+      mVideoInfo.mImage.height > MAX_H264_FRAME_HEIGHT) {
+    mIsValid = false;
+    return MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
+                       RESULT_DETAIL("Can't decode H.264 stream because its "
+                                     "resolution is out of the maximum limitation"));
+  }
+
+  return NS_OK;
 
 }
 
 already_AddRefed<MFTDecoder>
 WMFVideoMFTManager::LoadAMDVP9Decoder()
 {
   MOZ_ASSERT(mStreamType == VP9);
 
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -665,16 +665,17 @@ private:
   DECL_GFX_PREF(Live, "media.windows-media-foundation.allow-d3d11-dxva", PDMWMFAllowD3D11, bool, true);
   DECL_GFX_PREF(Live, "media.windows-media-foundation.max-dxva-videos", PDMWMFMaxDXVAVideos, uint32_t, 8);
   DECL_GFX_PREF(Live, "media.windows-media-foundation.use-nv12-format", PDMWMFUseNV12Format, bool, true);
   DECL_GFX_PREF(Once, "media.windows-media-foundation.use-sync-texture", PDMWMFUseSyncTexture, bool, true);
   DECL_GFX_PREF(Live, "media.wmf.low-latency.enabled", PDMWMFLowLatencyEnabled, bool, false);
   DECL_GFX_PREF(Live, "media.wmf.skip-blacklist", PDMWMFSkipBlacklist, bool, false);
   DECL_GFX_PREF(Live, "media.wmf.deblacklisting-for-telemetry-in-gpu-process", PDMWMFDeblacklistingForTelemetryInGPUProcess, bool, false);
   DECL_GFX_PREF(Live, "media.wmf.amd.vp9.enabled", PDMWMFAMDVP9DecoderEnabled, bool, true);
+  DECL_GFX_PREF(Live, "media.wmf.allow-unsupported-resolutions",  PDMWMFAllowUnsupportedResolutions, bool, false);
 #endif
 
   // These affect how line scrolls from wheel events will be accelerated.
   DECL_GFX_PREF(Live, "mousewheel.acceleration.factor",        MouseWheelAccelerationFactor, int32_t, -1);
   DECL_GFX_PREF(Live, "mousewheel.acceleration.start",         MouseWheelAccelerationStart, int32_t, -1);
 
   // This affects whether events will be routed through APZ or not.
   DECL_GFX_PREF(Live, "mousewheel.system_scroll_override_on_root_content.enabled",