content/media/wmf/WMFUtils.cpp

changeset 0
6474c204b198
     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(&timestampHns);
   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

mercurial