Bug 1156131 - Use correct DLL on WinVista, 7, and 8 for WMF decoding in gmp-clearkey. r=edwin, a=sledru
authorChris Pearce <cpearce@mozilla.com>
Mon, 20 Apr 2015 20:07:24 +1200
changeset 260215 e7210d2ce8a9
parent 260214 d1e5b60cd47c
child 260216 5712fefbace8
push id721
push userjlund@mozilla.com
push date2015-04-21 23:03 +0000
treeherdermozilla-release@d27c9211ebb3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersedwin, sledru
bugs1156131
milestone38.0
Bug 1156131 - Use correct DLL on WinVista, 7, and 8 for WMF decoding in gmp-clearkey. r=edwin, a=sledru
media/gmp-clearkey/0.1/ClearKeySessionManager.cpp
media/gmp-clearkey/0.1/VideoDecoder.cpp
media/gmp-clearkey/0.1/WMFAACDecoder.cpp
media/gmp-clearkey/0.1/WMFH264Decoder.cpp
media/gmp-clearkey/0.1/WMFSymbols.h
media/gmp-clearkey/0.1/WMFUtils.cpp
media/gmp-clearkey/0.1/WMFUtils.h
media/gmp-clearkey/0.1/clearkey.info.in
--- a/media/gmp-clearkey/0.1/ClearKeySessionManager.cpp
+++ b/media/gmp-clearkey/0.1/ClearKeySessionManager.cpp
@@ -9,16 +9,17 @@
 #include "ClearKeyDecryptionManager.h"
 #include "ClearKeySessionManager.h"
 #include "ClearKeyUtils.h"
 #include "ClearKeyStorage.h"
 #include "ClearKeyPersistence.h"
 #include "gmp-task-utils.h"
 #if defined(ENABLE_WMF)
 #include "WMFUtils.h"
+#include <VersionHelpers.h>
 #endif
 
 #include "mozilla/Assertions.h"
 
 using namespace mozilla;
 using namespace std;
 
 ClearKeySessionManager::ClearKeySessionManager()
@@ -35,33 +36,52 @@ ClearKeySessionManager::ClearKeySessionM
 
 ClearKeySessionManager::~ClearKeySessionManager()
 {
   CK_LOGD("ClearKeySessionManager dtor %p", this);
    MOZ_ASSERT(!mRefCount);
 }
 
 static bool
+ShouldBeAbleToDecode()
+{
+#if !defined(ENABLE_WMF)
+  return false;
+#else
+  return IsWindowsVistaOrGreater();
+#endif
+}
+
+static bool
 CanDecode()
 {
   return
 #if defined(ENABLE_WMF)
     wmf::EnsureLibs() ||
 #endif
     false;
 }
 
 void
 ClearKeySessionManager::Init(GMPDecryptorCallback* aCallback)
 {
   CK_LOGD("ClearKeySessionManager::Init");
   mCallback = aCallback;
-  mCallback->SetCapabilities(CanDecode() ?
-                             GMP_EME_CAP_DECRYPT_AND_DECODE_AUDIO | GMP_EME_CAP_DECRYPT_AND_DECODE_VIDEO :
-                             GMP_EME_CAP_DECRYPT_AUDIO | GMP_EME_CAP_DECRYPT_VIDEO);
+  if (ShouldBeAbleToDecode()) {
+    if (!CanDecode()) {
+      const char* err = "EME plugin can't load system decoder!";
+      mCallback->SessionError(nullptr, 0, kGMPAbortError, 0, err, strlen(err));
+    } else {
+      mCallback->SetCapabilities(GMP_EME_CAP_DECRYPT_AND_DECODE_AUDIO |
+                                 GMP_EME_CAP_DECRYPT_AND_DECODE_VIDEO);
+    }
+  } else {
+    mCallback->SetCapabilities(GMP_EME_CAP_DECRYPT_AUDIO |
+                               GMP_EME_CAP_DECRYPT_VIDEO);
+  }
   ClearKeyPersistence::EnsureInitialized();
 }
 
 void
 ClearKeySessionManager::CreateSession(uint32_t aCreateSessionToken,
                                       uint32_t aPromiseId,
                                       const char* aInitDataType,
                                       uint32_t aInitDataTypeSize,
--- a/media/gmp-clearkey/0.1/VideoDecoder.cpp
+++ b/media/gmp-clearkey/0.1/VideoDecoder.cpp
@@ -52,22 +52,24 @@ VideoDecoder::InitDecode(const GMPVideoC
                          GMPVideoDecoderCallback* aCallback,
                          int32_t aCoreCount)
 {
   mCallback = aCallback;
   assert(mCallback);
   mDecoder = new WMFH264Decoder();
   HRESULT hr = mDecoder->Init();
   if (FAILED(hr)) {
+    CK_LOGD("VideoDecoder::InitDecode failed to init WMFH264Decoder");
     mCallback->Error(GMPGenericErr);
     return;
   }
 
   auto err = GetPlatform()->createmutex(&mMutex);
   if (GMP_FAILED(err)) {
+    CK_LOGD("VideoDecoder::InitDecode failed to create GMPMutex");
     mCallback->Error(GMPGenericErr);
     return;
   }
 
   // The first byte is mPacketizationMode, which is only relevant for
   // WebRTC/OpenH264 usecase.
   const uint8_t* avcc = aCodecSpecific + 1;
   const uint8_t* avccEnd = aCodecSpecific + aCodecSpecificLength;
--- a/media/gmp-clearkey/0.1/WMFAACDecoder.cpp
+++ b/media/gmp-clearkey/0.1/WMFAACDecoder.cpp
@@ -87,21 +87,21 @@ WMFAACDecoder::Init(int32_t aChannelCoun
                     int32_t aSampleRate,
                     BYTE* aAACAudioSpecificConfig,
                     UINT32 aAudioConfigLength)
 {
   HRESULT hr;
 
   // AAC decoder is in msauddecmft on Win8, and msmpeg2adec in earlier versions.
   hr = CreateMFT(CLSID_CMSAACDecMFT,
-                 "msauddecmft.dll",
+                 WMFDecoderDllNameFor(AAC),
                  mDecoder);
   if (FAILED(hr)) {
     hr = CreateMFT(CLSID_CMSAACDecMFT,
-                   "msmpeg2adec.dll",
+                   WMFDecoderDllNameFor(AAC),
                    mDecoder);
     if (FAILED(hr)) {
       LOG("Failed to create AAC decoder\n");
       return E_FAIL;
     }
   }
 
   BYTE* userData = nullptr;
--- a/media/gmp-clearkey/0.1/WMFH264Decoder.cpp
+++ b/media/gmp-clearkey/0.1/WMFH264Decoder.cpp
@@ -31,23 +31,23 @@ WMFH264Decoder::~WMFH264Decoder()
 }
 
 HRESULT
 WMFH264Decoder::Init()
 {
   HRESULT hr;
 
   hr = CreateMFT(__uuidof(CMSH264DecoderMFT),
-                 "msmpeg2vdec.dll",
+                 WMFDecoderDllNameFor(H264),
                  mDecoder);
   if (FAILED(hr)) {
     // Windows 7 Enterprise Server N (which is what Mozilla's mochitests run
     // on) need a different CLSID to instantiate the H.264 decoder.
     hr = CreateMFT(CLSID_CMSH264DecMFT,
-                   "msmpeg2vdec.dll",
+                   WMFDecoderDllNameFor(H264),
                    mDecoder);
   }
   ENSURE(SUCCEEDED(hr), hr);
 
   hr = SetDecoderInputType();
   ENSURE(SUCCEEDED(hr), hr);
 
   hr = SetDecoderOutputType();
--- a/media/gmp-clearkey/0.1/WMFSymbols.h
+++ b/media/gmp-clearkey/0.1/WMFSymbols.h
@@ -1,8 +1,8 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-MFPLAT_FUNC(MFCreateSample);
-MFPLAT_FUNC(MFCreateAlignedMemoryBuffer);
-MFPLAT_FUNC(MFGetStrideForBitmapInfoHeader);
-MFPLAT_FUNC(MFCreateMediaType);
+MFPLAT_FUNC(MFCreateSample, "mfplat.dll");
+MFPLAT_FUNC(MFCreateAlignedMemoryBuffer, "mfplat.dll");
+MFPLAT_FUNC(MFGetStrideForBitmapInfoHeader, "evr.dll");
+MFPLAT_FUNC(MFCreateMediaType, "mfplat.dll");
\ No newline at end of file
--- a/media/gmp-clearkey/0.1/WMFUtils.cpp
+++ b/media/gmp-clearkey/0.1/WMFUtils.cpp
@@ -10,16 +10,18 @@
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 #include "WMFUtils.h"
+#include "ClearKeyUtils.h"
+#include <VersionHelpers.h>
 
 #include <stdio.h>
 
 #define INITGUID
 #include <guiddef.h>
 
 #pragma comment(lib, "mfuuid.lib")
 #pragma comment(lib, "wmcodecdspuuid")
@@ -40,52 +42,79 @@ void LOG(const char* format, ...)
 DEFINE_GUID(CLSID_CMSAACDecMFT, 0x32D186A7, 0x218F, 0x4C75, 0x88, 0x76, 0xDD, 0x77, 0x27, 0x3A, 0x89, 0x99);
 #endif
 
 DEFINE_GUID(CLSID_CMSH264DecMFT, 0x62CE7E72, 0x4C71, 0x4d20, 0xB1, 0x5D, 0x45, 0x28, 0x31, 0xA8, 0x7D, 0x9D);
 
 namespace wmf {
 
 
-#define MFPLAT_FUNC(_func) \
+#define MFPLAT_FUNC(_func, _dllname) \
   decltype(::_func)* _func;
 #include "WMFSymbols.h"
 #undef MFPLAT_FUNC
 
 static bool
 LinkMfplat()
 {
   static bool sInitDone = false;
   static bool sInitOk = false;
   if (!sInitDone) {
     sInitDone = true;
-    auto handle = GetModuleHandleA("mfplat.dll");
-#define MFPLAT_FUNC(_func) \
-    if (!(_func = (decltype(_func))(GetProcAddress(handle, #_func)))) { \
-      return false; \
-    }
+    HMODULE handle;
+
+#define MFPLAT_FUNC(_func, _dllname) \
+      handle = GetModuleHandleA(_dllname); \
+      if (!(_func = (decltype(_func))(GetProcAddress(handle, #_func)))) { \
+        return false; \
+      }
+
 #include "WMFSymbols.h"
 #undef MFPLAT_FUNC
     sInitOk = true;
   }
   return sInitOk;
 }
 
+const char*
+WMFDecoderDllNameFor(CodecType aCodec)
+{
+  if (aCodec == H264) {
+    // For H.264 decoding, we need msmpeg2vdec.dll on Win 7 & 8,
+    // and mfh264dec.dll on Vista.
+    if (IsWindows7OrGreater()) {
+      return "msmpeg2vdec.dll";
+    } else {
+      return "mfh264dec.dll";
+    }
+  } else if (aCodec == AAC) {
+    // For AAC decoding, we need to use msauddecmft.dll on Win8,
+    // msmpeg2adec.dll on Win7, and msheaacdec.dll on Vista.
+    if (IsWindows8OrGreater()) {
+      return "msauddecmft.dll";
+    } else if (IsWindows7OrGreater()) {
+      return "msmpeg2adec.dll";
+    } else {
+      return "mfheaacdec.dll";
+    }
+  } else {
+    return "";
+  }
+}
+
+
 bool
 EnsureLibs()
 {
   static bool sInitDone = false;
   static bool sInitOk = false;
   if (!sInitDone) {
-    // Note: For AAC decoding, we need to use msauddecmft.dll on Win8,
-    // and msmpeg2adec.dll on earlier Windows. So if we have at least
-    // one of these, assume we can decode.
     sInitOk = LinkMfplat() &&
-      (!!GetModuleHandleA("msauddecmft.dll") || !!GetModuleHandleA("msmpeg2adec.dll")) &&
-      !!GetModuleHandleA("msmpeg2vdec.dll");
+              !!GetModuleHandleA(WMFDecoderDllNameFor(AAC)) &&
+              !!GetModuleHandleA(WMFDecoderDllNameFor(H264));
     sInitDone = true;
   }
   return sInitOk;
 }
 
 int32_t
 MFOffsetToInt32(const MFOffset& aOffset)
 {
--- a/media/gmp-clearkey/0.1/WMFUtils.h
+++ b/media/gmp-clearkey/0.1/WMFUtils.h
@@ -117,17 +117,17 @@ typedef int64_t Microseconds;
 #endif
 
 #define ENSURE(condition, ret) \
 { if (!(condition)) { LOG("##condition## FAILED %S:%d\n", __FILE__, __LINE__); return ret; } }
 
 #define GMP_SUCCEEDED(x) ((x) == GMPNoErr)
 #define GMP_FAILED(x) ((x) != GMPNoErr)
 
-#define MFPLAT_FUNC(_func) \
+#define MFPLAT_FUNC(_func, _dllname) \
   extern decltype(::_func)* _func;
 #include "WMFSymbols.h"
 #undef MFPLAT_FUNC
 
 bool
 EnsureLibs();
 
 HRESULT
@@ -260,11 +260,20 @@ private:
 
 void dump(const uint8_t* data, uint32_t len, const char* filename);
 
 HRESULT
 CreateMFT(const CLSID& clsid,
           const char* aDllName,
           CComPtr<IMFTransform>& aOutMFT);
 
+enum CodecType {
+  H264,
+  AAC,
+};
+
+// Returns the name of the DLL that is needed to decode H.264 or AAC on
+// the given windows version we're running on.
+const char* WMFDecoderDllNameFor(CodecType aCodec);
+
 } // namespace wmf
 
 #endif // __WMFUtils_h__
--- a/media/gmp-clearkey/0.1/clearkey.info.in
+++ b/media/gmp-clearkey/0.1/clearkey.info.in
@@ -1,10 +1,10 @@
 Name: clearkey
 Description: ClearKey Gecko Media Plugin
 Version: 1
 #ifdef ENABLE_WMF
 APIs: eme-decrypt-v7[org.w3.clearkey], decode-audio[aac:org.w3.clearkey], decode-video[h264:org.w3.clearkey]
-Libraries: dxva2.dll, d3d9.dll, msmpeg2vdec.dll, msmpeg2adec.dll, MSAudDecMFT.dll
+Libraries: dxva2.dll, d3d9.dll, msmpeg2vdec.dll, msmpeg2adec.dll, MSAudDecMFT.dll, evr.dll, mfheaacdec.dll, mfh264dec.dll, mfplat.dll
 #else
 APIs: eme-decrypt-v7[org.w3.clearkey]
 Libraries:
 #endif