content/media/wmf/WMFUtils.cpp

Fri, 16 Jan 2015 04:50:19 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 04:50:19 +0100
branch
TOR_BUG_9701
changeset 13
44a2da4a2ab2
permissions
-rw-r--r--

Replace accessor implementation with direct member state manipulation, by
request https://trac.torproject.org/projects/tor/ticket/9701#comment:32

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "WMFUtils.h"
     8 #include <stdint.h>
     9 #include "mozilla/ArrayUtils.h"
    10 #include "mozilla/RefPtr.h"
    11 #include "mozilla/WindowsVersion.h"
    12 #include "prlog.h"
    13 #include "nsThreadUtils.h"
    14 #include "nsWindowsHelpers.h"
    15 #include "mozilla/CheckedInt.h"
    16 #include "VideoUtils.h"
    17 #include <initguid.h>
    19 #ifdef WMF_MUST_DEFINE_AAC_MFT_CLSID
    20 // Some SDK versions don't define the AAC decoder CLSID.
    21 // {32D186A7-218F-4C75-8876-DD77273A8999}
    22 DEFINE_GUID(CLSID_CMSAACDecMFT, 0x32D186A7, 0x218F, 0x4C75, 0x88, 0x76, 0xDD, 0x77, 0x27, 0x3A, 0x89, 0x99);
    23 #endif
    25 namespace mozilla {
    27 struct GuidToName {
    28   GUID guid;
    29   const char* name;
    30 };
    32 #define GUID_TO_NAME_ENTRY(g) { g, #g }
    33 #define INTERFACE_TO_NAME_ENTRY(i) {IID_##i, #i }
    35 GuidToName GuidToNameTable[] = {
    36   GUID_TO_NAME_ENTRY(MF_MT_MAJOR_TYPE),
    37   GUID_TO_NAME_ENTRY(MF_MT_MAJOR_TYPE),
    38   GUID_TO_NAME_ENTRY(MF_MT_SUBTYPE),
    39   GUID_TO_NAME_ENTRY(MF_MT_ALL_SAMPLES_INDEPENDENT),
    40   GUID_TO_NAME_ENTRY(MF_MT_FIXED_SIZE_SAMPLES),
    41   GUID_TO_NAME_ENTRY(MF_MT_COMPRESSED),
    42   GUID_TO_NAME_ENTRY(MF_MT_SAMPLE_SIZE),
    43   GUID_TO_NAME_ENTRY(MF_MT_WRAPPED_TYPE),
    44   GUID_TO_NAME_ENTRY(MF_MT_AUDIO_NUM_CHANNELS),
    45   GUID_TO_NAME_ENTRY(MF_MT_AUDIO_SAMPLES_PER_SECOND),
    46   GUID_TO_NAME_ENTRY(MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND),
    47   GUID_TO_NAME_ENTRY(MF_MT_AUDIO_AVG_BYTES_PER_SECOND),
    48   GUID_TO_NAME_ENTRY(MF_MT_AUDIO_BLOCK_ALIGNMENT),
    49   GUID_TO_NAME_ENTRY(MF_MT_AUDIO_BITS_PER_SAMPLE),
    50   GUID_TO_NAME_ENTRY(MF_MT_AUDIO_VALID_BITS_PER_SAMPLE),
    51   GUID_TO_NAME_ENTRY(MF_MT_AUDIO_SAMPLES_PER_BLOCK),
    52   GUID_TO_NAME_ENTRY(MF_MT_AUDIO_CHANNEL_MASK),
    53   GUID_TO_NAME_ENTRY(MF_MT_AUDIO_FOLDDOWN_MATRIX),
    54   GUID_TO_NAME_ENTRY(MF_MT_AUDIO_WMADRC_PEAKREF),
    55   GUID_TO_NAME_ENTRY(MF_MT_AUDIO_WMADRC_PEAKTARGET),
    56   GUID_TO_NAME_ENTRY(MF_MT_AUDIO_WMADRC_AVGREF),
    57   GUID_TO_NAME_ENTRY(MF_MT_AUDIO_WMADRC_AVGTARGET),
    58   GUID_TO_NAME_ENTRY(MF_MT_AUDIO_PREFER_WAVEFORMATEX),
    59   GUID_TO_NAME_ENTRY(MF_MT_AAC_PAYLOAD_TYPE),
    60   GUID_TO_NAME_ENTRY(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION),
    61   GUID_TO_NAME_ENTRY(MF_MT_FRAME_SIZE),
    62   GUID_TO_NAME_ENTRY(MF_MT_FRAME_RATE),
    63   GUID_TO_NAME_ENTRY(MF_MT_FRAME_RATE_RANGE_MAX),
    64   GUID_TO_NAME_ENTRY(MF_MT_FRAME_RATE_RANGE_MIN),
    65   GUID_TO_NAME_ENTRY(MF_MT_PIXEL_ASPECT_RATIO),
    66   GUID_TO_NAME_ENTRY(MF_MT_DRM_FLAGS),
    67   GUID_TO_NAME_ENTRY(MF_MT_PAD_CONTROL_FLAGS),
    68   GUID_TO_NAME_ENTRY(MF_MT_SOURCE_CONTENT_HINT),
    69   GUID_TO_NAME_ENTRY(MF_MT_VIDEO_CHROMA_SITING),
    70   GUID_TO_NAME_ENTRY(MF_MT_INTERLACE_MODE),
    71   GUID_TO_NAME_ENTRY(MF_MT_TRANSFER_FUNCTION),
    72   GUID_TO_NAME_ENTRY(MF_MT_VIDEO_PRIMARIES),
    73   GUID_TO_NAME_ENTRY(MF_MT_CUSTOM_VIDEO_PRIMARIES),
    74   GUID_TO_NAME_ENTRY(MF_MT_YUV_MATRIX),
    75   GUID_TO_NAME_ENTRY(MF_MT_VIDEO_LIGHTING),
    76   GUID_TO_NAME_ENTRY(MF_MT_VIDEO_NOMINAL_RANGE),
    77   GUID_TO_NAME_ENTRY(MF_MT_GEOMETRIC_APERTURE),
    78   GUID_TO_NAME_ENTRY(MF_MT_MINIMUM_DISPLAY_APERTURE),
    79   GUID_TO_NAME_ENTRY(MF_MT_PAN_SCAN_APERTURE),
    80   GUID_TO_NAME_ENTRY(MF_MT_PAN_SCAN_ENABLED),
    81   GUID_TO_NAME_ENTRY(MF_MT_AVG_BITRATE),
    82   GUID_TO_NAME_ENTRY(MF_MT_AVG_BIT_ERROR_RATE),
    83   GUID_TO_NAME_ENTRY(MF_MT_MAX_KEYFRAME_SPACING),
    84   GUID_TO_NAME_ENTRY(MF_MT_DEFAULT_STRIDE),
    85   GUID_TO_NAME_ENTRY(MF_MT_PALETTE),
    86   GUID_TO_NAME_ENTRY(MF_MT_USER_DATA),
    87   GUID_TO_NAME_ENTRY(MF_MT_AM_FORMAT_TYPE),
    88   GUID_TO_NAME_ENTRY(MF_MT_MPEG_START_TIME_CODE),
    89   GUID_TO_NAME_ENTRY(MF_MT_MPEG2_PROFILE),
    90   GUID_TO_NAME_ENTRY(MF_MT_MPEG2_LEVEL),
    91   GUID_TO_NAME_ENTRY(MF_MT_MPEG2_FLAGS),
    92   GUID_TO_NAME_ENTRY(MF_MT_MPEG_SEQUENCE_HEADER),
    93   GUID_TO_NAME_ENTRY(MF_MT_DV_AAUX_SRC_PACK_0),
    94   GUID_TO_NAME_ENTRY(MF_MT_DV_AAUX_CTRL_PACK_0),
    95   GUID_TO_NAME_ENTRY(MF_MT_DV_AAUX_SRC_PACK_1),
    96   GUID_TO_NAME_ENTRY(MF_MT_DV_AAUX_CTRL_PACK_1),
    97   GUID_TO_NAME_ENTRY(MF_MT_DV_VAUX_SRC_PACK),
    98   GUID_TO_NAME_ENTRY(MF_MT_DV_VAUX_CTRL_PACK),
    99   GUID_TO_NAME_ENTRY(MF_MT_ARBITRARY_HEADER),
   100   GUID_TO_NAME_ENTRY(MF_MT_ARBITRARY_FORMAT),
   101   GUID_TO_NAME_ENTRY(MF_MT_IMAGE_LOSS_TOLERANT),
   102   GUID_TO_NAME_ENTRY(MF_MT_MPEG4_SAMPLE_DESCRIPTION),
   103   GUID_TO_NAME_ENTRY(MF_MT_MPEG4_CURRENT_SAMPLE_ENTRY),
   104   GUID_TO_NAME_ENTRY(MF_MT_ORIGINAL_4CC),
   105   GUID_TO_NAME_ENTRY(MF_MT_ORIGINAL_WAVE_FORMAT_TAG),
   107   GUID_TO_NAME_ENTRY(MFMediaType_Audio),
   108   GUID_TO_NAME_ENTRY(MFMediaType_Video),
   109   GUID_TO_NAME_ENTRY(MFMediaType_Protected),
   110   GUID_TO_NAME_ENTRY(MFMediaType_SAMI),
   111   GUID_TO_NAME_ENTRY(MFMediaType_Script),
   112   GUID_TO_NAME_ENTRY(MFMediaType_Image),
   113   GUID_TO_NAME_ENTRY(MFMediaType_HTML),
   114   GUID_TO_NAME_ENTRY(MFMediaType_Binary),
   115   GUID_TO_NAME_ENTRY(MFMediaType_FileTransfer),
   117   GUID_TO_NAME_ENTRY(MFVideoFormat_AI44),
   118   GUID_TO_NAME_ENTRY(MFVideoFormat_ARGB32),
   119   GUID_TO_NAME_ENTRY(MFVideoFormat_AYUV),
   120   GUID_TO_NAME_ENTRY(MFVideoFormat_DV25),
   121   GUID_TO_NAME_ENTRY(MFVideoFormat_DV50),
   122   GUID_TO_NAME_ENTRY(MFVideoFormat_DVH1),
   123   GUID_TO_NAME_ENTRY(MFVideoFormat_DVSD),
   124   GUID_TO_NAME_ENTRY(MFVideoFormat_DVSL),
   125   GUID_TO_NAME_ENTRY(MFVideoFormat_H264),
   126   GUID_TO_NAME_ENTRY(MFVideoFormat_I420),
   127   GUID_TO_NAME_ENTRY(MFVideoFormat_IYUV),
   128   GUID_TO_NAME_ENTRY(MFVideoFormat_M4S2),
   129   GUID_TO_NAME_ENTRY(MFVideoFormat_MJPG),
   130   GUID_TO_NAME_ENTRY(MFVideoFormat_MP43),
   131   GUID_TO_NAME_ENTRY(MFVideoFormat_MP4S),
   132   GUID_TO_NAME_ENTRY(MFVideoFormat_MP4V),
   133   GUID_TO_NAME_ENTRY(MFVideoFormat_MPG1),
   134   GUID_TO_NAME_ENTRY(MFVideoFormat_MSS1),
   135   GUID_TO_NAME_ENTRY(MFVideoFormat_MSS2),
   136   GUID_TO_NAME_ENTRY(MFVideoFormat_NV11),
   137   GUID_TO_NAME_ENTRY(MFVideoFormat_NV12),
   138   GUID_TO_NAME_ENTRY(MFVideoFormat_P010),
   139   GUID_TO_NAME_ENTRY(MFVideoFormat_P016),
   140   GUID_TO_NAME_ENTRY(MFVideoFormat_P210),
   141   GUID_TO_NAME_ENTRY(MFVideoFormat_P216),
   142   GUID_TO_NAME_ENTRY(MFVideoFormat_RGB24),
   143   GUID_TO_NAME_ENTRY(MFVideoFormat_RGB32),
   144   GUID_TO_NAME_ENTRY(MFVideoFormat_RGB555),
   145   GUID_TO_NAME_ENTRY(MFVideoFormat_RGB565),
   146   GUID_TO_NAME_ENTRY(MFVideoFormat_RGB8),
   147   GUID_TO_NAME_ENTRY(MFVideoFormat_UYVY),
   148   GUID_TO_NAME_ENTRY(MFVideoFormat_v210),
   149   GUID_TO_NAME_ENTRY(MFVideoFormat_v410),
   150   GUID_TO_NAME_ENTRY(MFVideoFormat_WMV1),
   151   GUID_TO_NAME_ENTRY(MFVideoFormat_WMV2),
   152   GUID_TO_NAME_ENTRY(MFVideoFormat_WMV3),
   153   GUID_TO_NAME_ENTRY(MFVideoFormat_WVC1),
   154   GUID_TO_NAME_ENTRY(MFVideoFormat_Y210),
   155   GUID_TO_NAME_ENTRY(MFVideoFormat_Y216),
   156   GUID_TO_NAME_ENTRY(MFVideoFormat_Y410),
   157   GUID_TO_NAME_ENTRY(MFVideoFormat_Y416),
   158   GUID_TO_NAME_ENTRY(MFVideoFormat_Y41P),
   159   GUID_TO_NAME_ENTRY(MFVideoFormat_Y41T),
   160   GUID_TO_NAME_ENTRY(MFVideoFormat_YUY2),
   161   GUID_TO_NAME_ENTRY(MFVideoFormat_YV12),
   162   GUID_TO_NAME_ENTRY(MFVideoFormat_YVYU),
   164   GUID_TO_NAME_ENTRY(MFAudioFormat_PCM),
   165   GUID_TO_NAME_ENTRY(MFAudioFormat_Float),
   166   GUID_TO_NAME_ENTRY(MFAudioFormat_DTS),
   167   GUID_TO_NAME_ENTRY(MFAudioFormat_Dolby_AC3_SPDIF),
   168   GUID_TO_NAME_ENTRY(MFAudioFormat_DRM),
   169   GUID_TO_NAME_ENTRY(MFAudioFormat_WMAudioV8),
   170   GUID_TO_NAME_ENTRY(MFAudioFormat_WMAudioV9),
   171   GUID_TO_NAME_ENTRY(MFAudioFormat_WMAudio_Lossless),
   172   GUID_TO_NAME_ENTRY(MFAudioFormat_WMASPDIF),
   173   GUID_TO_NAME_ENTRY(MFAudioFormat_MSP1),
   174   GUID_TO_NAME_ENTRY(MFAudioFormat_MP3),
   175   GUID_TO_NAME_ENTRY(MFAudioFormat_MPEG),
   176   GUID_TO_NAME_ENTRY(MFAudioFormat_AAC),
   177   GUID_TO_NAME_ENTRY(MFAudioFormat_ADTS),
   179   // Interfaces which may be implemented by WMFByteStream.
   180   INTERFACE_TO_NAME_ENTRY(IUnknown),
   181   INTERFACE_TO_NAME_ENTRY(IMFByteStream),
   182   INTERFACE_TO_NAME_ENTRY(IMFMediaSource),
   183   INTERFACE_TO_NAME_ENTRY(IMFAttributes),
   184   INTERFACE_TO_NAME_ENTRY(IMFByteStreamBuffering),
   185 };
   187 nsCString GetGUIDName(const GUID& guid)
   188 {
   189   const unsigned numTypes = ArrayLength(GuidToNameTable);
   190   for (unsigned i = 0; i < numTypes; i++) {
   191     if (guid == GuidToNameTable[i].guid) {
   192       return nsDependentCString(GuidToNameTable[i].name);
   193     }
   194   }
   196   WCHAR* name = nullptr;
   197   HRESULT hr = StringFromCLSID(guid , &name);
   198   if (FAILED(hr)) {
   199     return nsDependentCString("GuidUnknown");
   200   }
   201   nsCString name_u8(NS_ConvertUTF16toUTF8(nsDependentString((char16_t*)(name))));
   202   CoTaskMemFree(name);
   203   return name_u8;
   204 }
   206 bool
   207 SourceReaderHasStream(IMFSourceReader* aReader, const DWORD aIndex)
   208 {
   209   RefPtr<IMFMediaType> nativeType;
   210   HRESULT hr = aReader->GetNativeMediaType(aIndex, 0, byRef(nativeType));
   211   return FAILED(hr) ? false : true;
   212 }
   214 HRESULT
   215 DoGetInterface(IUnknown* aUnknown, void** aInterface)
   216 {
   217   if (!aInterface)
   218     return E_POINTER;
   219   *aInterface = aUnknown;
   220   aUnknown->AddRef();
   221   return S_OK;
   222 }
   224 HRESULT
   225 HNsToFrames(int64_t aHNs, uint32_t aRate, int64_t* aOutFrames)
   226 {
   227   MOZ_ASSERT(aOutFrames);
   228   const int64_t HNS_PER_S = USECS_PER_S * 10;
   229   CheckedInt<int64_t> i = aHNs;
   230   i *= aRate;
   231   i /= HNS_PER_S;
   232   NS_ENSURE_TRUE(i.isValid(), E_FAIL);
   233   *aOutFrames = i.value();
   234   return S_OK;
   235 }
   237 HRESULT
   238 FramesToUsecs(int64_t aSamples, uint32_t aRate, int64_t* aOutUsecs)
   239 {
   240   MOZ_ASSERT(aOutUsecs);
   241   CheckedInt<int64_t> i = aSamples;
   242   i *= USECS_PER_S;
   243   i /= aRate;
   244   NS_ENSURE_TRUE(i.isValid(), E_FAIL);
   245   *aOutUsecs = i.value();
   246   return S_OK;
   247 }
   249 HRESULT
   250 GetDefaultStride(IMFMediaType *aType, uint32_t* aOutStride)
   251 {
   252   // Try to get the default stride from the media type.
   253   HRESULT hr = aType->GetUINT32(MF_MT_DEFAULT_STRIDE, aOutStride);
   254   if (SUCCEEDED(hr)) {
   255     return S_OK;
   256   }
   258   // Stride attribute not set, calculate it.
   259   GUID subtype = GUID_NULL;
   260   uint32_t width = 0;
   261   uint32_t height = 0;
   263   hr = aType->GetGUID(MF_MT_SUBTYPE, &subtype);
   264   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
   266   hr = MFGetAttributeSize(aType, MF_MT_FRAME_SIZE, &width, &height);
   267   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
   269   hr = wmf::MFGetStrideForBitmapInfoHeader(subtype.Data1, width, (LONG*)(aOutStride));
   270   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
   272   return hr;
   273 }
   275 int32_t
   276 MFOffsetToInt32(const MFOffset& aOffset)
   277 {
   278   return int32_t(aOffset.value + (aOffset.fract / 65536.0f));
   279 }
   281 int64_t
   282 GetSampleDuration(IMFSample* aSample)
   283 {
   284   NS_ENSURE_TRUE(aSample, -1);
   285   int64_t duration = 0;
   286   aSample->GetSampleDuration(&duration);
   287   return HNsToUsecs(duration);
   288 }
   290 int64_t
   291 GetSampleTime(IMFSample* aSample)
   292 {
   293   NS_ENSURE_TRUE(aSample, -1);
   294   LONGLONG timestampHns = 0;
   295   HRESULT hr = aSample->GetSampleTime(&timestampHns);
   296   NS_ENSURE_TRUE(SUCCEEDED(hr), -1);
   297   return HNsToUsecs(timestampHns);
   298 }
   300 // Gets the sub-region of the video frame that should be displayed.
   301 // See: http://msdn.microsoft.com/en-us/library/windows/desktop/bb530115(v=vs.85).aspx
   302 HRESULT
   303 GetPictureRegion(IMFMediaType* aMediaType, nsIntRect& aOutPictureRegion)
   304 {
   305   // Determine if "pan and scan" is enabled for this media. If it is, we
   306   // only display a region of the video frame, not the entire frame.
   307   BOOL panScan = MFGetAttributeUINT32(aMediaType, MF_MT_PAN_SCAN_ENABLED, FALSE);
   309   // If pan and scan mode is enabled. Try to get the display region.
   310   HRESULT hr = E_FAIL;
   311   MFVideoArea videoArea;
   312   memset(&videoArea, 0, sizeof(MFVideoArea));
   313   if (panScan) {
   314     hr = aMediaType->GetBlob(MF_MT_PAN_SCAN_APERTURE,
   315                              (UINT8*)&videoArea,
   316                              sizeof(MFVideoArea),
   317                              nullptr);
   318   }
   320   // If we're not in pan-and-scan mode, or the pan-and-scan region is not set,
   321   // check for a minimimum display aperture.
   322   if (!panScan || hr == MF_E_ATTRIBUTENOTFOUND) {
   323     hr = aMediaType->GetBlob(MF_MT_MINIMUM_DISPLAY_APERTURE,
   324                              (UINT8*)&videoArea,
   325                              sizeof(MFVideoArea),
   326                              nullptr);
   327   }
   329   if (hr == MF_E_ATTRIBUTENOTFOUND) {
   330     // Minimum display aperture is not set, for "backward compatibility with
   331     // some components", check for a geometric aperture.
   332     hr = aMediaType->GetBlob(MF_MT_GEOMETRIC_APERTURE,
   333                              (UINT8*)&videoArea,
   334                              sizeof(MFVideoArea),
   335                              nullptr);
   336   }
   338   if (SUCCEEDED(hr)) {
   339     // The media specified a picture region, return it.
   340     aOutPictureRegion = nsIntRect(MFOffsetToInt32(videoArea.OffsetX),
   341                                   MFOffsetToInt32(videoArea.OffsetY),
   342                                   videoArea.Area.cx,
   343                                   videoArea.Area.cy);
   344     return S_OK;
   345   }
   347   // No picture region defined, fall back to using the entire video area.
   348   UINT32 width = 0, height = 0;
   349   hr = MFGetAttributeSize(aMediaType, MF_MT_FRAME_SIZE, &width, &height);
   350   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
   351   aOutPictureRegion = nsIntRect(0, 0, width, height);
   352   return S_OK;
   353 }
   355 namespace wmf {
   357 static bool
   358 IsSupportedDecoder(const GUID& aDecoderGUID)
   359 {
   360   return aDecoderGUID == CLSID_CMSH264DecoderMFT ||
   361          aDecoderGUID == CLSID_CMSAACDecMFT ||
   362          aDecoderGUID == CLSID_CMP3DecMediaObject;
   363 }
   365 static HRESULT
   366 DisableBlockedDecoders(IMFPluginControl* aPluginControl,
   367                        const GUID& aCategory)
   368 {
   369   HRESULT hr = S_OK;
   371   UINT32 numMFTs = 0;
   372   IMFActivate **ppActivate = nullptr;
   373   hr = wmf::MFTEnumEx(aCategory,
   374                       MFT_ENUM_FLAG_ALL,
   375                       nullptr, // Input type, nullptr -> match all.
   376                       nullptr, // Output type, nullptr -> match all.
   377                       &ppActivate,
   378                       &numMFTs);
   380   if (SUCCEEDED(hr) && numMFTs == 0) {
   381     hr = MF_E_TOPO_CODEC_NOT_FOUND;
   382   }
   384   for (UINT32 i = 0; i < numMFTs; i++) {
   385     // Note: We must release all IMFActivate objects in the list, hence
   386     // we're putting individual IMFActivate objects in into a smart ptr.
   387     RefPtr<IMFActivate> activate = ppActivate[i];
   388     GUID guid = GUID_NULL;
   389     hr = activate->GetGUID(MFT_TRANSFORM_CLSID_Attribute, &guid);
   390     if (FAILED(hr)) {
   391       NS_WARNING("FAILED to get IMFActivate clsid");
   392       continue;
   393     }
   394     if (!IsSupportedDecoder(guid)) {
   395       hr = aPluginControl->SetDisabled(MF_Plugin_Type_MFT, guid, TRUE);
   396       NS_ASSERTION(SUCCEEDED(hr), "Failed to disable plugin!");
   397     }
   398   }
   399   CoTaskMemFree(ppActivate);
   401   return hr;
   402 }
   404 static HRESULT
   405 DisableBlockedDecoders()
   406 {
   407   RefPtr<IMFPluginControl> pluginControl;
   408   HRESULT hr = wmf::MFGetPluginControl(byRef(pluginControl));
   409   if (SUCCEEDED(hr) && pluginControl) {
   410     hr = DisableBlockedDecoders(pluginControl,
   411                                 MFT_CATEGORY_VIDEO_DECODER);
   412     NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
   414     hr = DisableBlockedDecoders(pluginControl,
   415                                 MFT_CATEGORY_AUDIO_DECODER);
   416     NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
   417   }
   419   return S_OK;
   420 }
   422 static bool sDLLsLoaded = false;
   423 static bool sFailedToLoadDlls = false;
   425 struct WMFModule {
   426   const wchar_t* name;
   427   HMODULE handle;
   428 };
   430 static WMFModule sDLLs[] = {
   431   { L"mfplat.dll", nullptr },
   432   { L"mfreadwrite.dll", nullptr },
   433   { L"propsys.dll", nullptr },
   434   { L"mf.dll", nullptr },
   435   { L"dxva2.dll", nullptr }
   436 };
   438 HRESULT
   439 LoadDLLs()
   440 {
   441   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
   443   if (sDLLsLoaded) {
   444     return S_OK;
   445   }
   446   if (sFailedToLoadDlls) {
   447     return E_FAIL;
   448   }
   450   // Try to load all the required DLLs.
   451   const uint32_t dllLength = ArrayLength(sDLLs);
   452   for (uint32_t i = 0; i < dllLength; i++) {
   453     sDLLs[i].handle = LoadLibrarySystem32(sDLLs[i].name);
   454     if (!sDLLs[i].handle) {
   455       sFailedToLoadDlls = true;
   456       NS_WARNING("Failed to load WMF DLLs");
   457       UnloadDLLs();
   458       return E_FAIL;
   459     }
   460   }
   462   // Enumerate all the decoders on the system, and disable the ones except
   463   // those which we expect to use, the MP3, AAC and H.264 decoders.
   464   if (FAILED(DisableBlockedDecoders())) {
   465     sFailedToLoadDlls = true;
   466     NS_WARNING("Failed to disable non whitelisted WMF decoders");
   467     UnloadDLLs();
   468     return E_FAIL;
   469   }
   471   sDLLsLoaded = true;
   473   return S_OK;
   474 }
   476 HRESULT
   477 UnloadDLLs()
   478 {
   479   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
   481   const uint32_t length = ArrayLength(sDLLs);
   482   for (uint32_t i = 0; i < length; i++) {
   483     if (sDLLs[i].handle) {
   484       FreeLibrary(sDLLs[i].handle);
   485       sDLLs[i].handle = nullptr;
   486     }
   487     sDLLsLoaded = false;
   488   }
   489   return S_OK;
   490 }
   492 #define ENSURE_FUNCTION_PTR_HELPER(FunctionType, FunctionName, DLL) \
   493   static FunctionType FunctionName##Ptr = nullptr; \
   494   if (!FunctionName##Ptr) { \
   495     FunctionName##Ptr = (FunctionType) GetProcAddress(GetModuleHandle(#DLL), #FunctionName); \
   496     if (!FunctionName##Ptr) { \
   497       NS_WARNING("Failed to get GetProcAddress of " #FunctionName " from " #DLL); \
   498       return E_FAIL; \
   499     } \
   500   }
   502 #define ENSURE_FUNCTION_PTR(FunctionName, DLL) \
   503   ENSURE_FUNCTION_PTR_HELPER(decltype(::FunctionName)*, FunctionName, DLL) \
   505 #define ENSURE_FUNCTION_PTR_(FunctionName, DLL) \
   506   ENSURE_FUNCTION_PTR_HELPER(FunctionName##Ptr_t, FunctionName, DLL) \
   508 #define DECL_FUNCTION_PTR(FunctionName, ...) \
   509   typedef HRESULT (STDMETHODCALLTYPE * FunctionName##Ptr_t)(__VA_ARGS__)
   511 HRESULT
   512 MFStartup()
   513 {
   514   const int MF_VISTA_VERSION = (0x0001 << 16 | MF_API_VERSION);
   515   const int MF_WIN7_VERSION = (0x0002 << 16 | MF_API_VERSION);
   517   // decltype is unusable for functions having default parameters
   518   DECL_FUNCTION_PTR(MFStartup, ULONG, DWORD);
   519   ENSURE_FUNCTION_PTR_(MFStartup, Mfplat.dll)
   520   if (!IsWin7OrLater())
   521     return MFStartupPtr(MF_VISTA_VERSION, MFSTARTUP_FULL);
   522   else
   523     return MFStartupPtr(MF_WIN7_VERSION, MFSTARTUP_FULL);
   524 }
   526 HRESULT
   527 MFShutdown()
   528 {
   529   ENSURE_FUNCTION_PTR(MFShutdown, Mfplat.dll)
   530   return (MFShutdownPtr)();
   531 }
   533 HRESULT
   534 MFCreateAsyncResult(IUnknown *aUnkObject,
   535                     IMFAsyncCallback *aCallback,
   536                     IUnknown *aUnkState,
   537                     IMFAsyncResult **aOutAsyncResult)
   538 {
   539   ENSURE_FUNCTION_PTR(MFCreateAsyncResult, Mfplat.dll)
   540   return (MFCreateAsyncResultPtr)(aUnkObject, aCallback, aUnkState, aOutAsyncResult);
   541 }
   543 HRESULT
   544 MFInvokeCallback(IMFAsyncResult *aAsyncResult)
   545 {
   546   ENSURE_FUNCTION_PTR(MFInvokeCallback, Mfplat.dll);
   547   return (MFInvokeCallbackPtr)(aAsyncResult);
   548 }
   550 HRESULT
   551 MFCreateMediaType(IMFMediaType **aOutMFType)
   552 {
   553   ENSURE_FUNCTION_PTR(MFCreateMediaType, Mfplat.dll)
   554   return (MFCreateMediaTypePtr)(aOutMFType);
   555 }
   557 HRESULT
   558 MFCreateSourceReaderFromByteStream(IMFByteStream *aByteStream,
   559                                    IMFAttributes *aAttributes,
   560                                    IMFSourceReader **aOutSourceReader)
   561 {
   562   ENSURE_FUNCTION_PTR(MFCreateSourceReaderFromByteStream, Mfreadwrite.dll)
   563   return (MFCreateSourceReaderFromByteStreamPtr)(aByteStream,
   564                                                  aAttributes,
   565                                                  aOutSourceReader);
   566 }
   568 HRESULT
   569 PropVariantToUInt32(REFPROPVARIANT aPropvar, ULONG *aOutUL)
   570 {
   571   // decltype is unusable for overloaded functions
   572   DECL_FUNCTION_PTR(PropVariantToUInt32, REFPROPVARIANT, ULONG *);
   573   ENSURE_FUNCTION_PTR_(PropVariantToUInt32, Propsys.dll)
   574   return (PropVariantToUInt32Ptr)(aPropvar, aOutUL);
   575 }
   577 HRESULT PropVariantToInt64(REFPROPVARIANT aPropVar, LONGLONG *aOutLL)
   578 {
   579   ENSURE_FUNCTION_PTR(PropVariantToInt64, Propsys.dll)
   580   return (PropVariantToInt64Ptr)(aPropVar, aOutLL);
   581 }
   583 HRESULT
   584 MFTGetInfo(CLSID aClsidMFT,
   585            LPWSTR *aOutName,
   586            MFT_REGISTER_TYPE_INFO **aOutInputTypes,
   587            UINT32 *aOutNumInputTypes,
   588            MFT_REGISTER_TYPE_INFO **aOutOutputTypes,
   589            UINT32 *aOutNumOutputTypes,
   590            IMFAttributes **aOutAttributes)
   591 {
   592   ENSURE_FUNCTION_PTR(MFTGetInfo, Mfplat.dll)
   593   return (MFTGetInfoPtr)(aClsidMFT,
   594                          aOutName,
   595                          aOutInputTypes,
   596                          aOutNumInputTypes,
   597                          aOutOutputTypes,
   598                          aOutNumOutputTypes,
   599                          aOutAttributes);
   600 }
   602 HRESULT
   603 MFGetStrideForBitmapInfoHeader(DWORD aFormat,
   604                                DWORD aWidth,
   605                                LONG *aOutStride)
   606 {
   607   ENSURE_FUNCTION_PTR(MFGetStrideForBitmapInfoHeader, Mfplat.dll)
   608   return (MFGetStrideForBitmapInfoHeaderPtr)(aFormat, aWidth, aOutStride);
   609 }
   611 HRESULT
   612 MFCreateSourceReaderFromURL(LPCWSTR aURL,
   613                             IMFAttributes *aAttributes,
   614                             IMFSourceReader **aSourceReader)
   615 {
   616   ENSURE_FUNCTION_PTR(MFCreateSourceReaderFromURL, Mfreadwrite.dll)
   617   return (MFCreateSourceReaderFromURLPtr)(aURL, aAttributes, aSourceReader);
   618 }
   620 HRESULT
   621 MFCreateAttributes(IMFAttributes **ppMFAttributes, UINT32 cInitialSize)
   622 {
   623   ENSURE_FUNCTION_PTR(MFCreateAttributes, mfplat.dll)
   624   return (MFCreateAttributesPtr)(ppMFAttributes, cInitialSize);
   625 }
   627 HRESULT
   628 MFGetPluginControl(IMFPluginControl **aOutPluginControl)
   629 {
   630   ENSURE_FUNCTION_PTR(MFGetPluginControl, mfplat.dll)
   631   return (MFGetPluginControlPtr)(aOutPluginControl);
   632 }
   634 HRESULT
   635 MFTEnumEx(GUID guidCategory,
   636           UINT32 Flags,
   637           const MFT_REGISTER_TYPE_INFO *pInputType,
   638           const MFT_REGISTER_TYPE_INFO *pOutputType,
   639           IMFActivate ***pppMFTActivate,
   640           UINT32 *pcMFTActivate)
   641 {
   642   ENSURE_FUNCTION_PTR(MFTEnumEx, mfplat.dll)
   643   return (MFTEnumExPtr)(guidCategory, Flags, pInputType, pOutputType, pppMFTActivate, pcMFTActivate);
   644 }
   646 HRESULT MFGetService(IUnknown *punkObject,
   647                      REFGUID guidService,
   648                      REFIID riid,
   649                      LPVOID *ppvObject)
   650 {
   651   ENSURE_FUNCTION_PTR(MFGetService, mf.dll)
   652   return (MFGetServicePtr)(punkObject, guidService, riid, ppvObject);
   653 }
   655 HRESULT
   656 DXVA2CreateDirect3DDeviceManager9(UINT *pResetToken,
   657                                   IDirect3DDeviceManager9 **ppDXVAManager)
   658 {
   659   ENSURE_FUNCTION_PTR(DXVA2CreateDirect3DDeviceManager9, dxva2.dll)
   660   return (DXVA2CreateDirect3DDeviceManager9Ptr)(pResetToken, ppDXVAManager);
   661 }
   663 HRESULT
   664 MFCreateSample(IMFSample **ppIMFSample)
   665 {
   666   ENSURE_FUNCTION_PTR(MFCreateSample, mfplat.dll)
   667   return (MFCreateSamplePtr)(ppIMFSample);
   668 }
   670 HRESULT
   671 MFCreateAlignedMemoryBuffer(DWORD cbMaxLength,
   672                             DWORD fAlignmentFlags,
   673                             IMFMediaBuffer **ppBuffer)
   674 {
   675   ENSURE_FUNCTION_PTR(MFCreateAlignedMemoryBuffer, mfplat.dll)
   676   return (MFCreateAlignedMemoryBufferPtr)(cbMaxLength, fAlignmentFlags, ppBuffer);
   677 }
   679 } // end namespace wmf
   680 } // end namespace mozilla

mercurial