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

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

mercurial