1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/media/wmf/WMFUtils.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,680 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim:set ts=2 sw=2 sts=2 et cindent: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "WMFUtils.h" 1.11 +#include <stdint.h> 1.12 +#include "mozilla/ArrayUtils.h" 1.13 +#include "mozilla/RefPtr.h" 1.14 +#include "mozilla/WindowsVersion.h" 1.15 +#include "prlog.h" 1.16 +#include "nsThreadUtils.h" 1.17 +#include "nsWindowsHelpers.h" 1.18 +#include "mozilla/CheckedInt.h" 1.19 +#include "VideoUtils.h" 1.20 +#include <initguid.h> 1.21 + 1.22 +#ifdef WMF_MUST_DEFINE_AAC_MFT_CLSID 1.23 +// Some SDK versions don't define the AAC decoder CLSID. 1.24 +// {32D186A7-218F-4C75-8876-DD77273A8999} 1.25 +DEFINE_GUID(CLSID_CMSAACDecMFT, 0x32D186A7, 0x218F, 0x4C75, 0x88, 0x76, 0xDD, 0x77, 0x27, 0x3A, 0x89, 0x99); 1.26 +#endif 1.27 + 1.28 +namespace mozilla { 1.29 + 1.30 +struct GuidToName { 1.31 + GUID guid; 1.32 + const char* name; 1.33 +}; 1.34 + 1.35 +#define GUID_TO_NAME_ENTRY(g) { g, #g } 1.36 +#define INTERFACE_TO_NAME_ENTRY(i) {IID_##i, #i } 1.37 + 1.38 +GuidToName GuidToNameTable[] = { 1.39 + GUID_TO_NAME_ENTRY(MF_MT_MAJOR_TYPE), 1.40 + GUID_TO_NAME_ENTRY(MF_MT_MAJOR_TYPE), 1.41 + GUID_TO_NAME_ENTRY(MF_MT_SUBTYPE), 1.42 + GUID_TO_NAME_ENTRY(MF_MT_ALL_SAMPLES_INDEPENDENT), 1.43 + GUID_TO_NAME_ENTRY(MF_MT_FIXED_SIZE_SAMPLES), 1.44 + GUID_TO_NAME_ENTRY(MF_MT_COMPRESSED), 1.45 + GUID_TO_NAME_ENTRY(MF_MT_SAMPLE_SIZE), 1.46 + GUID_TO_NAME_ENTRY(MF_MT_WRAPPED_TYPE), 1.47 + GUID_TO_NAME_ENTRY(MF_MT_AUDIO_NUM_CHANNELS), 1.48 + GUID_TO_NAME_ENTRY(MF_MT_AUDIO_SAMPLES_PER_SECOND), 1.49 + GUID_TO_NAME_ENTRY(MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND), 1.50 + GUID_TO_NAME_ENTRY(MF_MT_AUDIO_AVG_BYTES_PER_SECOND), 1.51 + GUID_TO_NAME_ENTRY(MF_MT_AUDIO_BLOCK_ALIGNMENT), 1.52 + GUID_TO_NAME_ENTRY(MF_MT_AUDIO_BITS_PER_SAMPLE), 1.53 + GUID_TO_NAME_ENTRY(MF_MT_AUDIO_VALID_BITS_PER_SAMPLE), 1.54 + GUID_TO_NAME_ENTRY(MF_MT_AUDIO_SAMPLES_PER_BLOCK), 1.55 + GUID_TO_NAME_ENTRY(MF_MT_AUDIO_CHANNEL_MASK), 1.56 + GUID_TO_NAME_ENTRY(MF_MT_AUDIO_FOLDDOWN_MATRIX), 1.57 + GUID_TO_NAME_ENTRY(MF_MT_AUDIO_WMADRC_PEAKREF), 1.58 + GUID_TO_NAME_ENTRY(MF_MT_AUDIO_WMADRC_PEAKTARGET), 1.59 + GUID_TO_NAME_ENTRY(MF_MT_AUDIO_WMADRC_AVGREF), 1.60 + GUID_TO_NAME_ENTRY(MF_MT_AUDIO_WMADRC_AVGTARGET), 1.61 + GUID_TO_NAME_ENTRY(MF_MT_AUDIO_PREFER_WAVEFORMATEX), 1.62 + GUID_TO_NAME_ENTRY(MF_MT_AAC_PAYLOAD_TYPE), 1.63 + GUID_TO_NAME_ENTRY(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION), 1.64 + GUID_TO_NAME_ENTRY(MF_MT_FRAME_SIZE), 1.65 + GUID_TO_NAME_ENTRY(MF_MT_FRAME_RATE), 1.66 + GUID_TO_NAME_ENTRY(MF_MT_FRAME_RATE_RANGE_MAX), 1.67 + GUID_TO_NAME_ENTRY(MF_MT_FRAME_RATE_RANGE_MIN), 1.68 + GUID_TO_NAME_ENTRY(MF_MT_PIXEL_ASPECT_RATIO), 1.69 + GUID_TO_NAME_ENTRY(MF_MT_DRM_FLAGS), 1.70 + GUID_TO_NAME_ENTRY(MF_MT_PAD_CONTROL_FLAGS), 1.71 + GUID_TO_NAME_ENTRY(MF_MT_SOURCE_CONTENT_HINT), 1.72 + GUID_TO_NAME_ENTRY(MF_MT_VIDEO_CHROMA_SITING), 1.73 + GUID_TO_NAME_ENTRY(MF_MT_INTERLACE_MODE), 1.74 + GUID_TO_NAME_ENTRY(MF_MT_TRANSFER_FUNCTION), 1.75 + GUID_TO_NAME_ENTRY(MF_MT_VIDEO_PRIMARIES), 1.76 + GUID_TO_NAME_ENTRY(MF_MT_CUSTOM_VIDEO_PRIMARIES), 1.77 + GUID_TO_NAME_ENTRY(MF_MT_YUV_MATRIX), 1.78 + GUID_TO_NAME_ENTRY(MF_MT_VIDEO_LIGHTING), 1.79 + GUID_TO_NAME_ENTRY(MF_MT_VIDEO_NOMINAL_RANGE), 1.80 + GUID_TO_NAME_ENTRY(MF_MT_GEOMETRIC_APERTURE), 1.81 + GUID_TO_NAME_ENTRY(MF_MT_MINIMUM_DISPLAY_APERTURE), 1.82 + GUID_TO_NAME_ENTRY(MF_MT_PAN_SCAN_APERTURE), 1.83 + GUID_TO_NAME_ENTRY(MF_MT_PAN_SCAN_ENABLED), 1.84 + GUID_TO_NAME_ENTRY(MF_MT_AVG_BITRATE), 1.85 + GUID_TO_NAME_ENTRY(MF_MT_AVG_BIT_ERROR_RATE), 1.86 + GUID_TO_NAME_ENTRY(MF_MT_MAX_KEYFRAME_SPACING), 1.87 + GUID_TO_NAME_ENTRY(MF_MT_DEFAULT_STRIDE), 1.88 + GUID_TO_NAME_ENTRY(MF_MT_PALETTE), 1.89 + GUID_TO_NAME_ENTRY(MF_MT_USER_DATA), 1.90 + GUID_TO_NAME_ENTRY(MF_MT_AM_FORMAT_TYPE), 1.91 + GUID_TO_NAME_ENTRY(MF_MT_MPEG_START_TIME_CODE), 1.92 + GUID_TO_NAME_ENTRY(MF_MT_MPEG2_PROFILE), 1.93 + GUID_TO_NAME_ENTRY(MF_MT_MPEG2_LEVEL), 1.94 + GUID_TO_NAME_ENTRY(MF_MT_MPEG2_FLAGS), 1.95 + GUID_TO_NAME_ENTRY(MF_MT_MPEG_SEQUENCE_HEADER), 1.96 + GUID_TO_NAME_ENTRY(MF_MT_DV_AAUX_SRC_PACK_0), 1.97 + GUID_TO_NAME_ENTRY(MF_MT_DV_AAUX_CTRL_PACK_0), 1.98 + GUID_TO_NAME_ENTRY(MF_MT_DV_AAUX_SRC_PACK_1), 1.99 + GUID_TO_NAME_ENTRY(MF_MT_DV_AAUX_CTRL_PACK_1), 1.100 + GUID_TO_NAME_ENTRY(MF_MT_DV_VAUX_SRC_PACK), 1.101 + GUID_TO_NAME_ENTRY(MF_MT_DV_VAUX_CTRL_PACK), 1.102 + GUID_TO_NAME_ENTRY(MF_MT_ARBITRARY_HEADER), 1.103 + GUID_TO_NAME_ENTRY(MF_MT_ARBITRARY_FORMAT), 1.104 + GUID_TO_NAME_ENTRY(MF_MT_IMAGE_LOSS_TOLERANT), 1.105 + GUID_TO_NAME_ENTRY(MF_MT_MPEG4_SAMPLE_DESCRIPTION), 1.106 + GUID_TO_NAME_ENTRY(MF_MT_MPEG4_CURRENT_SAMPLE_ENTRY), 1.107 + GUID_TO_NAME_ENTRY(MF_MT_ORIGINAL_4CC), 1.108 + GUID_TO_NAME_ENTRY(MF_MT_ORIGINAL_WAVE_FORMAT_TAG), 1.109 + 1.110 + GUID_TO_NAME_ENTRY(MFMediaType_Audio), 1.111 + GUID_TO_NAME_ENTRY(MFMediaType_Video), 1.112 + GUID_TO_NAME_ENTRY(MFMediaType_Protected), 1.113 + GUID_TO_NAME_ENTRY(MFMediaType_SAMI), 1.114 + GUID_TO_NAME_ENTRY(MFMediaType_Script), 1.115 + GUID_TO_NAME_ENTRY(MFMediaType_Image), 1.116 + GUID_TO_NAME_ENTRY(MFMediaType_HTML), 1.117 + GUID_TO_NAME_ENTRY(MFMediaType_Binary), 1.118 + GUID_TO_NAME_ENTRY(MFMediaType_FileTransfer), 1.119 + 1.120 + GUID_TO_NAME_ENTRY(MFVideoFormat_AI44), 1.121 + GUID_TO_NAME_ENTRY(MFVideoFormat_ARGB32), 1.122 + GUID_TO_NAME_ENTRY(MFVideoFormat_AYUV), 1.123 + GUID_TO_NAME_ENTRY(MFVideoFormat_DV25), 1.124 + GUID_TO_NAME_ENTRY(MFVideoFormat_DV50), 1.125 + GUID_TO_NAME_ENTRY(MFVideoFormat_DVH1), 1.126 + GUID_TO_NAME_ENTRY(MFVideoFormat_DVSD), 1.127 + GUID_TO_NAME_ENTRY(MFVideoFormat_DVSL), 1.128 + GUID_TO_NAME_ENTRY(MFVideoFormat_H264), 1.129 + GUID_TO_NAME_ENTRY(MFVideoFormat_I420), 1.130 + GUID_TO_NAME_ENTRY(MFVideoFormat_IYUV), 1.131 + GUID_TO_NAME_ENTRY(MFVideoFormat_M4S2), 1.132 + GUID_TO_NAME_ENTRY(MFVideoFormat_MJPG), 1.133 + GUID_TO_NAME_ENTRY(MFVideoFormat_MP43), 1.134 + GUID_TO_NAME_ENTRY(MFVideoFormat_MP4S), 1.135 + GUID_TO_NAME_ENTRY(MFVideoFormat_MP4V), 1.136 + GUID_TO_NAME_ENTRY(MFVideoFormat_MPG1), 1.137 + GUID_TO_NAME_ENTRY(MFVideoFormat_MSS1), 1.138 + GUID_TO_NAME_ENTRY(MFVideoFormat_MSS2), 1.139 + GUID_TO_NAME_ENTRY(MFVideoFormat_NV11), 1.140 + GUID_TO_NAME_ENTRY(MFVideoFormat_NV12), 1.141 + GUID_TO_NAME_ENTRY(MFVideoFormat_P010), 1.142 + GUID_TO_NAME_ENTRY(MFVideoFormat_P016), 1.143 + GUID_TO_NAME_ENTRY(MFVideoFormat_P210), 1.144 + GUID_TO_NAME_ENTRY(MFVideoFormat_P216), 1.145 + GUID_TO_NAME_ENTRY(MFVideoFormat_RGB24), 1.146 + GUID_TO_NAME_ENTRY(MFVideoFormat_RGB32), 1.147 + GUID_TO_NAME_ENTRY(MFVideoFormat_RGB555), 1.148 + GUID_TO_NAME_ENTRY(MFVideoFormat_RGB565), 1.149 + GUID_TO_NAME_ENTRY(MFVideoFormat_RGB8), 1.150 + GUID_TO_NAME_ENTRY(MFVideoFormat_UYVY), 1.151 + GUID_TO_NAME_ENTRY(MFVideoFormat_v210), 1.152 + GUID_TO_NAME_ENTRY(MFVideoFormat_v410), 1.153 + GUID_TO_NAME_ENTRY(MFVideoFormat_WMV1), 1.154 + GUID_TO_NAME_ENTRY(MFVideoFormat_WMV2), 1.155 + GUID_TO_NAME_ENTRY(MFVideoFormat_WMV3), 1.156 + GUID_TO_NAME_ENTRY(MFVideoFormat_WVC1), 1.157 + GUID_TO_NAME_ENTRY(MFVideoFormat_Y210), 1.158 + GUID_TO_NAME_ENTRY(MFVideoFormat_Y216), 1.159 + GUID_TO_NAME_ENTRY(MFVideoFormat_Y410), 1.160 + GUID_TO_NAME_ENTRY(MFVideoFormat_Y416), 1.161 + GUID_TO_NAME_ENTRY(MFVideoFormat_Y41P), 1.162 + GUID_TO_NAME_ENTRY(MFVideoFormat_Y41T), 1.163 + GUID_TO_NAME_ENTRY(MFVideoFormat_YUY2), 1.164 + GUID_TO_NAME_ENTRY(MFVideoFormat_YV12), 1.165 + GUID_TO_NAME_ENTRY(MFVideoFormat_YVYU), 1.166 + 1.167 + GUID_TO_NAME_ENTRY(MFAudioFormat_PCM), 1.168 + GUID_TO_NAME_ENTRY(MFAudioFormat_Float), 1.169 + GUID_TO_NAME_ENTRY(MFAudioFormat_DTS), 1.170 + GUID_TO_NAME_ENTRY(MFAudioFormat_Dolby_AC3_SPDIF), 1.171 + GUID_TO_NAME_ENTRY(MFAudioFormat_DRM), 1.172 + GUID_TO_NAME_ENTRY(MFAudioFormat_WMAudioV8), 1.173 + GUID_TO_NAME_ENTRY(MFAudioFormat_WMAudioV9), 1.174 + GUID_TO_NAME_ENTRY(MFAudioFormat_WMAudio_Lossless), 1.175 + GUID_TO_NAME_ENTRY(MFAudioFormat_WMASPDIF), 1.176 + GUID_TO_NAME_ENTRY(MFAudioFormat_MSP1), 1.177 + GUID_TO_NAME_ENTRY(MFAudioFormat_MP3), 1.178 + GUID_TO_NAME_ENTRY(MFAudioFormat_MPEG), 1.179 + GUID_TO_NAME_ENTRY(MFAudioFormat_AAC), 1.180 + GUID_TO_NAME_ENTRY(MFAudioFormat_ADTS), 1.181 + 1.182 + // Interfaces which may be implemented by WMFByteStream. 1.183 + INTERFACE_TO_NAME_ENTRY(IUnknown), 1.184 + INTERFACE_TO_NAME_ENTRY(IMFByteStream), 1.185 + INTERFACE_TO_NAME_ENTRY(IMFMediaSource), 1.186 + INTERFACE_TO_NAME_ENTRY(IMFAttributes), 1.187 + INTERFACE_TO_NAME_ENTRY(IMFByteStreamBuffering), 1.188 +}; 1.189 + 1.190 +nsCString GetGUIDName(const GUID& guid) 1.191 +{ 1.192 + const unsigned numTypes = ArrayLength(GuidToNameTable); 1.193 + for (unsigned i = 0; i < numTypes; i++) { 1.194 + if (guid == GuidToNameTable[i].guid) { 1.195 + return nsDependentCString(GuidToNameTable[i].name); 1.196 + } 1.197 + } 1.198 + 1.199 + WCHAR* name = nullptr; 1.200 + HRESULT hr = StringFromCLSID(guid , &name); 1.201 + if (FAILED(hr)) { 1.202 + return nsDependentCString("GuidUnknown"); 1.203 + } 1.204 + nsCString name_u8(NS_ConvertUTF16toUTF8(nsDependentString((char16_t*)(name)))); 1.205 + CoTaskMemFree(name); 1.206 + return name_u8; 1.207 +} 1.208 + 1.209 +bool 1.210 +SourceReaderHasStream(IMFSourceReader* aReader, const DWORD aIndex) 1.211 +{ 1.212 + RefPtr<IMFMediaType> nativeType; 1.213 + HRESULT hr = aReader->GetNativeMediaType(aIndex, 0, byRef(nativeType)); 1.214 + return FAILED(hr) ? false : true; 1.215 +} 1.216 + 1.217 +HRESULT 1.218 +DoGetInterface(IUnknown* aUnknown, void** aInterface) 1.219 +{ 1.220 + if (!aInterface) 1.221 + return E_POINTER; 1.222 + *aInterface = aUnknown; 1.223 + aUnknown->AddRef(); 1.224 + return S_OK; 1.225 +} 1.226 + 1.227 +HRESULT 1.228 +HNsToFrames(int64_t aHNs, uint32_t aRate, int64_t* aOutFrames) 1.229 +{ 1.230 + MOZ_ASSERT(aOutFrames); 1.231 + const int64_t HNS_PER_S = USECS_PER_S * 10; 1.232 + CheckedInt<int64_t> i = aHNs; 1.233 + i *= aRate; 1.234 + i /= HNS_PER_S; 1.235 + NS_ENSURE_TRUE(i.isValid(), E_FAIL); 1.236 + *aOutFrames = i.value(); 1.237 + return S_OK; 1.238 +} 1.239 + 1.240 +HRESULT 1.241 +FramesToUsecs(int64_t aSamples, uint32_t aRate, int64_t* aOutUsecs) 1.242 +{ 1.243 + MOZ_ASSERT(aOutUsecs); 1.244 + CheckedInt<int64_t> i = aSamples; 1.245 + i *= USECS_PER_S; 1.246 + i /= aRate; 1.247 + NS_ENSURE_TRUE(i.isValid(), E_FAIL); 1.248 + *aOutUsecs = i.value(); 1.249 + return S_OK; 1.250 +} 1.251 + 1.252 +HRESULT 1.253 +GetDefaultStride(IMFMediaType *aType, uint32_t* aOutStride) 1.254 +{ 1.255 + // Try to get the default stride from the media type. 1.256 + HRESULT hr = aType->GetUINT32(MF_MT_DEFAULT_STRIDE, aOutStride); 1.257 + if (SUCCEEDED(hr)) { 1.258 + return S_OK; 1.259 + } 1.260 + 1.261 + // Stride attribute not set, calculate it. 1.262 + GUID subtype = GUID_NULL; 1.263 + uint32_t width = 0; 1.264 + uint32_t height = 0; 1.265 + 1.266 + hr = aType->GetGUID(MF_MT_SUBTYPE, &subtype); 1.267 + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); 1.268 + 1.269 + hr = MFGetAttributeSize(aType, MF_MT_FRAME_SIZE, &width, &height); 1.270 + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); 1.271 + 1.272 + hr = wmf::MFGetStrideForBitmapInfoHeader(subtype.Data1, width, (LONG*)(aOutStride)); 1.273 + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); 1.274 + 1.275 + return hr; 1.276 +} 1.277 + 1.278 +int32_t 1.279 +MFOffsetToInt32(const MFOffset& aOffset) 1.280 +{ 1.281 + return int32_t(aOffset.value + (aOffset.fract / 65536.0f)); 1.282 +} 1.283 + 1.284 +int64_t 1.285 +GetSampleDuration(IMFSample* aSample) 1.286 +{ 1.287 + NS_ENSURE_TRUE(aSample, -1); 1.288 + int64_t duration = 0; 1.289 + aSample->GetSampleDuration(&duration); 1.290 + return HNsToUsecs(duration); 1.291 +} 1.292 + 1.293 +int64_t 1.294 +GetSampleTime(IMFSample* aSample) 1.295 +{ 1.296 + NS_ENSURE_TRUE(aSample, -1); 1.297 + LONGLONG timestampHns = 0; 1.298 + HRESULT hr = aSample->GetSampleTime(×tampHns); 1.299 + NS_ENSURE_TRUE(SUCCEEDED(hr), -1); 1.300 + return HNsToUsecs(timestampHns); 1.301 +} 1.302 + 1.303 +// Gets the sub-region of the video frame that should be displayed. 1.304 +// See: http://msdn.microsoft.com/en-us/library/windows/desktop/bb530115(v=vs.85).aspx 1.305 +HRESULT 1.306 +GetPictureRegion(IMFMediaType* aMediaType, nsIntRect& aOutPictureRegion) 1.307 +{ 1.308 + // Determine if "pan and scan" is enabled for this media. If it is, we 1.309 + // only display a region of the video frame, not the entire frame. 1.310 + BOOL panScan = MFGetAttributeUINT32(aMediaType, MF_MT_PAN_SCAN_ENABLED, FALSE); 1.311 + 1.312 + // If pan and scan mode is enabled. Try to get the display region. 1.313 + HRESULT hr = E_FAIL; 1.314 + MFVideoArea videoArea; 1.315 + memset(&videoArea, 0, sizeof(MFVideoArea)); 1.316 + if (panScan) { 1.317 + hr = aMediaType->GetBlob(MF_MT_PAN_SCAN_APERTURE, 1.318 + (UINT8*)&videoArea, 1.319 + sizeof(MFVideoArea), 1.320 + nullptr); 1.321 + } 1.322 + 1.323 + // If we're not in pan-and-scan mode, or the pan-and-scan region is not set, 1.324 + // check for a minimimum display aperture. 1.325 + if (!panScan || hr == MF_E_ATTRIBUTENOTFOUND) { 1.326 + hr = aMediaType->GetBlob(MF_MT_MINIMUM_DISPLAY_APERTURE, 1.327 + (UINT8*)&videoArea, 1.328 + sizeof(MFVideoArea), 1.329 + nullptr); 1.330 + } 1.331 + 1.332 + if (hr == MF_E_ATTRIBUTENOTFOUND) { 1.333 + // Minimum display aperture is not set, for "backward compatibility with 1.334 + // some components", check for a geometric aperture. 1.335 + hr = aMediaType->GetBlob(MF_MT_GEOMETRIC_APERTURE, 1.336 + (UINT8*)&videoArea, 1.337 + sizeof(MFVideoArea), 1.338 + nullptr); 1.339 + } 1.340 + 1.341 + if (SUCCEEDED(hr)) { 1.342 + // The media specified a picture region, return it. 1.343 + aOutPictureRegion = nsIntRect(MFOffsetToInt32(videoArea.OffsetX), 1.344 + MFOffsetToInt32(videoArea.OffsetY), 1.345 + videoArea.Area.cx, 1.346 + videoArea.Area.cy); 1.347 + return S_OK; 1.348 + } 1.349 + 1.350 + // No picture region defined, fall back to using the entire video area. 1.351 + UINT32 width = 0, height = 0; 1.352 + hr = MFGetAttributeSize(aMediaType, MF_MT_FRAME_SIZE, &width, &height); 1.353 + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); 1.354 + aOutPictureRegion = nsIntRect(0, 0, width, height); 1.355 + return S_OK; 1.356 +} 1.357 + 1.358 +namespace wmf { 1.359 + 1.360 +static bool 1.361 +IsSupportedDecoder(const GUID& aDecoderGUID) 1.362 +{ 1.363 + return aDecoderGUID == CLSID_CMSH264DecoderMFT || 1.364 + aDecoderGUID == CLSID_CMSAACDecMFT || 1.365 + aDecoderGUID == CLSID_CMP3DecMediaObject; 1.366 +} 1.367 + 1.368 +static HRESULT 1.369 +DisableBlockedDecoders(IMFPluginControl* aPluginControl, 1.370 + const GUID& aCategory) 1.371 +{ 1.372 + HRESULT hr = S_OK; 1.373 + 1.374 + UINT32 numMFTs = 0; 1.375 + IMFActivate **ppActivate = nullptr; 1.376 + hr = wmf::MFTEnumEx(aCategory, 1.377 + MFT_ENUM_FLAG_ALL, 1.378 + nullptr, // Input type, nullptr -> match all. 1.379 + nullptr, // Output type, nullptr -> match all. 1.380 + &ppActivate, 1.381 + &numMFTs); 1.382 + 1.383 + if (SUCCEEDED(hr) && numMFTs == 0) { 1.384 + hr = MF_E_TOPO_CODEC_NOT_FOUND; 1.385 + } 1.386 + 1.387 + for (UINT32 i = 0; i < numMFTs; i++) { 1.388 + // Note: We must release all IMFActivate objects in the list, hence 1.389 + // we're putting individual IMFActivate objects in into a smart ptr. 1.390 + RefPtr<IMFActivate> activate = ppActivate[i]; 1.391 + GUID guid = GUID_NULL; 1.392 + hr = activate->GetGUID(MFT_TRANSFORM_CLSID_Attribute, &guid); 1.393 + if (FAILED(hr)) { 1.394 + NS_WARNING("FAILED to get IMFActivate clsid"); 1.395 + continue; 1.396 + } 1.397 + if (!IsSupportedDecoder(guid)) { 1.398 + hr = aPluginControl->SetDisabled(MF_Plugin_Type_MFT, guid, TRUE); 1.399 + NS_ASSERTION(SUCCEEDED(hr), "Failed to disable plugin!"); 1.400 + } 1.401 + } 1.402 + CoTaskMemFree(ppActivate); 1.403 + 1.404 + return hr; 1.405 +} 1.406 + 1.407 +static HRESULT 1.408 +DisableBlockedDecoders() 1.409 +{ 1.410 + RefPtr<IMFPluginControl> pluginControl; 1.411 + HRESULT hr = wmf::MFGetPluginControl(byRef(pluginControl)); 1.412 + if (SUCCEEDED(hr) && pluginControl) { 1.413 + hr = DisableBlockedDecoders(pluginControl, 1.414 + MFT_CATEGORY_VIDEO_DECODER); 1.415 + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); 1.416 + 1.417 + hr = DisableBlockedDecoders(pluginControl, 1.418 + MFT_CATEGORY_AUDIO_DECODER); 1.419 + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); 1.420 + } 1.421 + 1.422 + return S_OK; 1.423 +} 1.424 + 1.425 +static bool sDLLsLoaded = false; 1.426 +static bool sFailedToLoadDlls = false; 1.427 + 1.428 +struct WMFModule { 1.429 + const wchar_t* name; 1.430 + HMODULE handle; 1.431 +}; 1.432 + 1.433 +static WMFModule sDLLs[] = { 1.434 + { L"mfplat.dll", nullptr }, 1.435 + { L"mfreadwrite.dll", nullptr }, 1.436 + { L"propsys.dll", nullptr }, 1.437 + { L"mf.dll", nullptr }, 1.438 + { L"dxva2.dll", nullptr } 1.439 +}; 1.440 + 1.441 +HRESULT 1.442 +LoadDLLs() 1.443 +{ 1.444 + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); 1.445 + 1.446 + if (sDLLsLoaded) { 1.447 + return S_OK; 1.448 + } 1.449 + if (sFailedToLoadDlls) { 1.450 + return E_FAIL; 1.451 + } 1.452 + 1.453 + // Try to load all the required DLLs. 1.454 + const uint32_t dllLength = ArrayLength(sDLLs); 1.455 + for (uint32_t i = 0; i < dllLength; i++) { 1.456 + sDLLs[i].handle = LoadLibrarySystem32(sDLLs[i].name); 1.457 + if (!sDLLs[i].handle) { 1.458 + sFailedToLoadDlls = true; 1.459 + NS_WARNING("Failed to load WMF DLLs"); 1.460 + UnloadDLLs(); 1.461 + return E_FAIL; 1.462 + } 1.463 + } 1.464 + 1.465 + // Enumerate all the decoders on the system, and disable the ones except 1.466 + // those which we expect to use, the MP3, AAC and H.264 decoders. 1.467 + if (FAILED(DisableBlockedDecoders())) { 1.468 + sFailedToLoadDlls = true; 1.469 + NS_WARNING("Failed to disable non whitelisted WMF decoders"); 1.470 + UnloadDLLs(); 1.471 + return E_FAIL; 1.472 + } 1.473 + 1.474 + sDLLsLoaded = true; 1.475 + 1.476 + return S_OK; 1.477 +} 1.478 + 1.479 +HRESULT 1.480 +UnloadDLLs() 1.481 +{ 1.482 + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); 1.483 + 1.484 + const uint32_t length = ArrayLength(sDLLs); 1.485 + for (uint32_t i = 0; i < length; i++) { 1.486 + if (sDLLs[i].handle) { 1.487 + FreeLibrary(sDLLs[i].handle); 1.488 + sDLLs[i].handle = nullptr; 1.489 + } 1.490 + sDLLsLoaded = false; 1.491 + } 1.492 + return S_OK; 1.493 +} 1.494 + 1.495 +#define ENSURE_FUNCTION_PTR_HELPER(FunctionType, FunctionName, DLL) \ 1.496 + static FunctionType FunctionName##Ptr = nullptr; \ 1.497 + if (!FunctionName##Ptr) { \ 1.498 + FunctionName##Ptr = (FunctionType) GetProcAddress(GetModuleHandle(#DLL), #FunctionName); \ 1.499 + if (!FunctionName##Ptr) { \ 1.500 + NS_WARNING("Failed to get GetProcAddress of " #FunctionName " from " #DLL); \ 1.501 + return E_FAIL; \ 1.502 + } \ 1.503 + } 1.504 + 1.505 +#define ENSURE_FUNCTION_PTR(FunctionName, DLL) \ 1.506 + ENSURE_FUNCTION_PTR_HELPER(decltype(::FunctionName)*, FunctionName, DLL) \ 1.507 + 1.508 +#define ENSURE_FUNCTION_PTR_(FunctionName, DLL) \ 1.509 + ENSURE_FUNCTION_PTR_HELPER(FunctionName##Ptr_t, FunctionName, DLL) \ 1.510 + 1.511 +#define DECL_FUNCTION_PTR(FunctionName, ...) \ 1.512 + typedef HRESULT (STDMETHODCALLTYPE * FunctionName##Ptr_t)(__VA_ARGS__) 1.513 + 1.514 +HRESULT 1.515 +MFStartup() 1.516 +{ 1.517 + const int MF_VISTA_VERSION = (0x0001 << 16 | MF_API_VERSION); 1.518 + const int MF_WIN7_VERSION = (0x0002 << 16 | MF_API_VERSION); 1.519 + 1.520 + // decltype is unusable for functions having default parameters 1.521 + DECL_FUNCTION_PTR(MFStartup, ULONG, DWORD); 1.522 + ENSURE_FUNCTION_PTR_(MFStartup, Mfplat.dll) 1.523 + if (!IsWin7OrLater()) 1.524 + return MFStartupPtr(MF_VISTA_VERSION, MFSTARTUP_FULL); 1.525 + else 1.526 + return MFStartupPtr(MF_WIN7_VERSION, MFSTARTUP_FULL); 1.527 +} 1.528 + 1.529 +HRESULT 1.530 +MFShutdown() 1.531 +{ 1.532 + ENSURE_FUNCTION_PTR(MFShutdown, Mfplat.dll) 1.533 + return (MFShutdownPtr)(); 1.534 +} 1.535 + 1.536 +HRESULT 1.537 +MFCreateAsyncResult(IUnknown *aUnkObject, 1.538 + IMFAsyncCallback *aCallback, 1.539 + IUnknown *aUnkState, 1.540 + IMFAsyncResult **aOutAsyncResult) 1.541 +{ 1.542 + ENSURE_FUNCTION_PTR(MFCreateAsyncResult, Mfplat.dll) 1.543 + return (MFCreateAsyncResultPtr)(aUnkObject, aCallback, aUnkState, aOutAsyncResult); 1.544 +} 1.545 + 1.546 +HRESULT 1.547 +MFInvokeCallback(IMFAsyncResult *aAsyncResult) 1.548 +{ 1.549 + ENSURE_FUNCTION_PTR(MFInvokeCallback, Mfplat.dll); 1.550 + return (MFInvokeCallbackPtr)(aAsyncResult); 1.551 +} 1.552 + 1.553 +HRESULT 1.554 +MFCreateMediaType(IMFMediaType **aOutMFType) 1.555 +{ 1.556 + ENSURE_FUNCTION_PTR(MFCreateMediaType, Mfplat.dll) 1.557 + return (MFCreateMediaTypePtr)(aOutMFType); 1.558 +} 1.559 + 1.560 +HRESULT 1.561 +MFCreateSourceReaderFromByteStream(IMFByteStream *aByteStream, 1.562 + IMFAttributes *aAttributes, 1.563 + IMFSourceReader **aOutSourceReader) 1.564 +{ 1.565 + ENSURE_FUNCTION_PTR(MFCreateSourceReaderFromByteStream, Mfreadwrite.dll) 1.566 + return (MFCreateSourceReaderFromByteStreamPtr)(aByteStream, 1.567 + aAttributes, 1.568 + aOutSourceReader); 1.569 +} 1.570 + 1.571 +HRESULT 1.572 +PropVariantToUInt32(REFPROPVARIANT aPropvar, ULONG *aOutUL) 1.573 +{ 1.574 + // decltype is unusable for overloaded functions 1.575 + DECL_FUNCTION_PTR(PropVariantToUInt32, REFPROPVARIANT, ULONG *); 1.576 + ENSURE_FUNCTION_PTR_(PropVariantToUInt32, Propsys.dll) 1.577 + return (PropVariantToUInt32Ptr)(aPropvar, aOutUL); 1.578 +} 1.579 + 1.580 +HRESULT PropVariantToInt64(REFPROPVARIANT aPropVar, LONGLONG *aOutLL) 1.581 +{ 1.582 + ENSURE_FUNCTION_PTR(PropVariantToInt64, Propsys.dll) 1.583 + return (PropVariantToInt64Ptr)(aPropVar, aOutLL); 1.584 +} 1.585 + 1.586 +HRESULT 1.587 +MFTGetInfo(CLSID aClsidMFT, 1.588 + LPWSTR *aOutName, 1.589 + MFT_REGISTER_TYPE_INFO **aOutInputTypes, 1.590 + UINT32 *aOutNumInputTypes, 1.591 + MFT_REGISTER_TYPE_INFO **aOutOutputTypes, 1.592 + UINT32 *aOutNumOutputTypes, 1.593 + IMFAttributes **aOutAttributes) 1.594 +{ 1.595 + ENSURE_FUNCTION_PTR(MFTGetInfo, Mfplat.dll) 1.596 + return (MFTGetInfoPtr)(aClsidMFT, 1.597 + aOutName, 1.598 + aOutInputTypes, 1.599 + aOutNumInputTypes, 1.600 + aOutOutputTypes, 1.601 + aOutNumOutputTypes, 1.602 + aOutAttributes); 1.603 +} 1.604 + 1.605 +HRESULT 1.606 +MFGetStrideForBitmapInfoHeader(DWORD aFormat, 1.607 + DWORD aWidth, 1.608 + LONG *aOutStride) 1.609 +{ 1.610 + ENSURE_FUNCTION_PTR(MFGetStrideForBitmapInfoHeader, Mfplat.dll) 1.611 + return (MFGetStrideForBitmapInfoHeaderPtr)(aFormat, aWidth, aOutStride); 1.612 +} 1.613 + 1.614 +HRESULT 1.615 +MFCreateSourceReaderFromURL(LPCWSTR aURL, 1.616 + IMFAttributes *aAttributes, 1.617 + IMFSourceReader **aSourceReader) 1.618 +{ 1.619 + ENSURE_FUNCTION_PTR(MFCreateSourceReaderFromURL, Mfreadwrite.dll) 1.620 + return (MFCreateSourceReaderFromURLPtr)(aURL, aAttributes, aSourceReader); 1.621 +} 1.622 + 1.623 +HRESULT 1.624 +MFCreateAttributes(IMFAttributes **ppMFAttributes, UINT32 cInitialSize) 1.625 +{ 1.626 + ENSURE_FUNCTION_PTR(MFCreateAttributes, mfplat.dll) 1.627 + return (MFCreateAttributesPtr)(ppMFAttributes, cInitialSize); 1.628 +} 1.629 + 1.630 +HRESULT 1.631 +MFGetPluginControl(IMFPluginControl **aOutPluginControl) 1.632 +{ 1.633 + ENSURE_FUNCTION_PTR(MFGetPluginControl, mfplat.dll) 1.634 + return (MFGetPluginControlPtr)(aOutPluginControl); 1.635 +} 1.636 + 1.637 +HRESULT 1.638 +MFTEnumEx(GUID guidCategory, 1.639 + UINT32 Flags, 1.640 + const MFT_REGISTER_TYPE_INFO *pInputType, 1.641 + const MFT_REGISTER_TYPE_INFO *pOutputType, 1.642 + IMFActivate ***pppMFTActivate, 1.643 + UINT32 *pcMFTActivate) 1.644 +{ 1.645 + ENSURE_FUNCTION_PTR(MFTEnumEx, mfplat.dll) 1.646 + return (MFTEnumExPtr)(guidCategory, Flags, pInputType, pOutputType, pppMFTActivate, pcMFTActivate); 1.647 +} 1.648 + 1.649 +HRESULT MFGetService(IUnknown *punkObject, 1.650 + REFGUID guidService, 1.651 + REFIID riid, 1.652 + LPVOID *ppvObject) 1.653 +{ 1.654 + ENSURE_FUNCTION_PTR(MFGetService, mf.dll) 1.655 + return (MFGetServicePtr)(punkObject, guidService, riid, ppvObject); 1.656 +} 1.657 + 1.658 +HRESULT 1.659 +DXVA2CreateDirect3DDeviceManager9(UINT *pResetToken, 1.660 + IDirect3DDeviceManager9 **ppDXVAManager) 1.661 +{ 1.662 + ENSURE_FUNCTION_PTR(DXVA2CreateDirect3DDeviceManager9, dxva2.dll) 1.663 + return (DXVA2CreateDirect3DDeviceManager9Ptr)(pResetToken, ppDXVAManager); 1.664 +} 1.665 + 1.666 +HRESULT 1.667 +MFCreateSample(IMFSample **ppIMFSample) 1.668 +{ 1.669 + ENSURE_FUNCTION_PTR(MFCreateSample, mfplat.dll) 1.670 + return (MFCreateSamplePtr)(ppIMFSample); 1.671 +} 1.672 + 1.673 +HRESULT 1.674 +MFCreateAlignedMemoryBuffer(DWORD cbMaxLength, 1.675 + DWORD fAlignmentFlags, 1.676 + IMFMediaBuffer **ppBuffer) 1.677 +{ 1.678 + ENSURE_FUNCTION_PTR(MFCreateAlignedMemoryBuffer, mfplat.dll) 1.679 + return (MFCreateAlignedMemoryBufferPtr)(cbMaxLength, fAlignmentFlags, ppBuffer); 1.680 +} 1.681 + 1.682 +} // end namespace wmf 1.683 +} // end namespace mozilla