Bug 1397141 - part2 : move the resolution check into WMFVideoMFTManager. draft
authorAlastor Wu <alwu@mozilla.com>
Wed, 06 Sep 2017 18:16:18 +0800
changeset 659875 97771ce0cecbd40284175a9ce64b2737eb8ac547
parent 659874 4b165c013d7faed8bc91de55e805d9567406e908
child 659876 d5a19d32b86b9c7346719aecc021c4f6305c7746
push id78224
push useralwu@mozilla.com
push dateWed, 06 Sep 2017 10:19:09 +0000
bugs1397141
milestone57.0a1
Bug 1397141 - part2 : move the resolution check into WMFVideoMFTManager. MozReview-Commit-ID: 760xXxgVSj
dom/media/platforms/wmf/WMFDecoderModule.cpp
dom/media/platforms/wmf/WMFVideoMFTManager.cpp
--- a/dom/media/platforms/wmf/WMFDecoderModule.cpp
+++ b/dom/media/platforms/wmf/WMFDecoderModule.cpp
@@ -164,48 +164,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()
@@ -230,34 +198,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
@@ -8,16 +8,17 @@
 
 #include "DXVA2Manager.h"
 #include "GMPUtils.h" // For SplitAt. TODO: Move SplitAt to a central place.
 #include "IMFYCbCrImage.h"
 #include "ImageContainer.h"
 #include "Layers.h"
 #include "MP4Decoder.h"
 #include "MediaInfo.h"
+#include "MediaPrefs.h"
 #include "MediaTelemetryConstants.h"
 #include "VPXDecoder.h"
 #include "VideoUtils.h"
 #include "WMFUtils.h"
 #include "gfx2DGlue.h"
 #include "gfxPrefs.h"
 #include "gfxWindowsPlatform.h"
 #include "mozilla/gfx/gfxVars.h"
@@ -94,16 +95,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)
   {
   }
@@ -526,25 +559,39 @@ WMFVideoMFTManager::InitializeDXVA()
 bool
 WMFVideoMFTManager::ValidateVideoInfo(MediaResult* aError)
 {
   // 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;
-  if (mStreamType == H264 &&
-      (mVideoInfo.mImage.width < MIN_H264_FRAME_DIMENSION ||
-       mVideoInfo.mImage.height < MIN_H264_FRAME_DIMENSION)) {
-    MOZ_ASSERT(aError);
+  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 ||
+      MediaPrefs::PDMWMFAllowUnsupportedResolutions()) {
+    return mIsValid;
+  }
+
+  MOZ_ASSERT(aError);
+  if (mVideoInfo.mImage.width < MIN_H264_FRAME_DIMENSION ||
+      mVideoInfo.mImage.height < MIN_H264_FRAME_DIMENSION) {
     *aError = MediaResult(
       NS_ERROR_DOM_MEDIA_FATAL_ERR,
       RESULT_DETAIL("Can't decode H.264 stream with width or height less than 48 pixels."));
     mIsValid = false;
+  } else if (mVideoInfo.mImage.width > MAX_H264_FRAME_WIDTH ||
+             mVideoInfo.mImage.height > MAX_H264_FRAME_HEIGHT) {
+    *aError = MediaResult(
+      NS_ERROR_DOM_MEDIA_FATAL_ERR,
+      RESULT_DETAIL("Can't decode H.264 stream with oversize image resolution."));
+    mIsValid = false;
   }
 
   return mIsValid;
 }
 
 already_AddRefed<MFTDecoder>
 WMFVideoMFTManager::LoadAMDVP9Decoder()
 {