summaryrefslogtreecommitdiffstats
path: root/dom/media/platforms/wmf/WMFUtils.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dom/media/platforms/wmf/WMFUtils.cpp632
1 files changed, 632 insertions, 0 deletions
diff --git a/dom/media/platforms/wmf/WMFUtils.cpp b/dom/media/platforms/wmf/WMFUtils.cpp
new file mode 100644
index 0000000000..75888c12c3
--- /dev/null
+++ b/dom/media/platforms/wmf/WMFUtils.cpp
@@ -0,0 +1,632 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "WMFUtils.h"
+
+#include <mfidl.h>
+#include <shlobj.h>
+#include <shlwapi.h>
+#include <initguid.h>
+#include <stdint.h>
+
+#ifdef MOZ_AV1
+# include "AOMDecoder.h"
+#endif
+#include "MP4Decoder.h"
+#include "OpusDecoder.h"
+#include "VideoUtils.h"
+#include "VorbisDecoder.h"
+#include "VPXDecoder.h"
+#include "mozilla/ArrayUtils.h"
+#include "mozilla/CheckedInt.h"
+#include "mozilla/Logging.h"
+#include "mozilla/RefPtr.h"
+#include "nsTArray.h"
+#include "nsThreadUtils.h"
+#include "nsWindowsHelpers.h"
+#include "prenv.h"
+#include "mozilla/mscom/EnsureMTA.h"
+#include "mozilla/WindowsVersion.h"
+
+#ifndef WAVE_FORMAT_OPUS
+# define WAVE_FORMAT_OPUS 0x704F
+#endif
+DEFINE_GUID(MEDIASUBTYPE_OPUS, WAVE_FORMAT_OPUS, 0x000, 0x0010, 0x80, 0x00,
+ 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
+
+namespace mozilla {
+
+using media::TimeUnit;
+
+bool StreamTypeIsVideo(const WMFStreamType& aType) {
+ switch (aType) {
+ case WMFStreamType::H264:
+ case WMFStreamType::VP8:
+ case WMFStreamType::VP9:
+ case WMFStreamType::AV1:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool StreamTypeIsAudio(const WMFStreamType& aType) {
+ switch (aType) {
+ case WMFStreamType::MP3:
+ case WMFStreamType::AAC:
+ case WMFStreamType::OPUS:
+ case WMFStreamType::VORBIS:
+ return true;
+ default:
+ return false;
+ }
+}
+
+// Get a string representation of the stream type. Useful for logging.
+const char* StreamTypeToString(WMFStreamType aStreamType) {
+ switch (aStreamType) {
+ case WMFStreamType::H264:
+ return "H264";
+ case WMFStreamType::VP8:
+ return "VP8";
+ case WMFStreamType::VP9:
+ return "VP9";
+ case WMFStreamType::AV1:
+ return "AV1";
+ case WMFStreamType::MP3:
+ return "MP3";
+ case WMFStreamType::AAC:
+ return "AAC";
+ case WMFStreamType::OPUS:
+ return "OPUS";
+ case WMFStreamType::VORBIS:
+ return "VORBIS";
+ default:
+ MOZ_ASSERT(aStreamType == WMFStreamType::Unknown);
+ return "Unknown";
+ }
+}
+
+WMFStreamType GetStreamTypeFromMimeType(const nsCString& aMimeType) {
+ if (MP4Decoder::IsH264(aMimeType)) {
+ return WMFStreamType::H264;
+ }
+ if (VPXDecoder::IsVP8(aMimeType)) {
+ return WMFStreamType::VP8;
+ }
+ if (VPXDecoder::IsVP9(aMimeType)) {
+ return WMFStreamType::VP9;
+ }
+#ifdef MOZ_AV1
+ if (AOMDecoder::IsAV1(aMimeType)) {
+ return WMFStreamType::AV1;
+ }
+#endif
+ if (aMimeType.EqualsLiteral("audio/mp4a-latm") ||
+ aMimeType.EqualsLiteral("audio/mp4")) {
+ return WMFStreamType::AAC;
+ }
+ if (aMimeType.EqualsLiteral("audio/mpeg")) {
+ return WMFStreamType::MP3;
+ }
+ if (OpusDataDecoder::IsOpus(aMimeType)) {
+ return WMFStreamType::OPUS;
+ }
+ if (VorbisDataDecoder::IsVorbis(aMimeType)) {
+ return WMFStreamType::VORBIS;
+ }
+ return WMFStreamType::Unknown;
+}
+
+HRESULT
+HNsToFrames(int64_t aHNs, uint32_t aRate, int64_t* aOutFrames) {
+ MOZ_ASSERT(aOutFrames);
+ const int64_t HNS_PER_S = USECS_PER_S * 10;
+ CheckedInt<int64_t> i = aHNs;
+ i *= aRate;
+ i /= HNS_PER_S;
+ NS_ENSURE_TRUE(i.isValid(), E_FAIL);
+ *aOutFrames = i.value();
+ return S_OK;
+}
+
+HRESULT
+GetDefaultStride(IMFMediaType* aType, uint32_t aWidth, uint32_t* aOutStride) {
+ // Try to get the default stride from the media type.
+ HRESULT hr = aType->GetUINT32(MF_MT_DEFAULT_STRIDE, aOutStride);
+ if (SUCCEEDED(hr)) {
+ return S_OK;
+ }
+
+ // Stride attribute not set, calculate it.
+ GUID subtype = GUID_NULL;
+
+ hr = aType->GetGUID(MF_MT_SUBTYPE, &subtype);
+ NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
+
+ hr = wmf::MFGetStrideForBitmapInfoHeader(subtype.Data1, aWidth,
+ (LONG*)(aOutStride));
+ NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
+
+ return hr;
+}
+
+Maybe<gfx::YUVColorSpace> GetYUVColorSpace(IMFMediaType* aType) {
+ UINT32 yuvColorMatrix;
+ HRESULT hr = aType->GetUINT32(MF_MT_YUV_MATRIX, &yuvColorMatrix);
+ NS_ENSURE_TRUE(SUCCEEDED(hr), {});
+
+ switch (yuvColorMatrix) {
+ case MFVideoTransferMatrix_BT2020_10:
+ case MFVideoTransferMatrix_BT2020_12:
+ return Some(gfx::YUVColorSpace::BT2020);
+ case MFVideoTransferMatrix_BT709:
+ return Some(gfx::YUVColorSpace::BT709);
+ case MFVideoTransferMatrix_BT601:
+ return Some(gfx::YUVColorSpace::BT601);
+ default:
+ MOZ_ASSERT_UNREACHABLE("Unhandled MFVideoTransferMatrix_?");
+ return {};
+ }
+}
+
+int32_t MFOffsetToInt32(const MFOffset& aOffset) {
+ return int32_t(aOffset.value + (aOffset.fract / 65536.0f));
+}
+
+TimeUnit GetSampleDuration(IMFSample* aSample) {
+ NS_ENSURE_TRUE(aSample, TimeUnit::Invalid());
+ int64_t duration = 0;
+ HRESULT hr = aSample->GetSampleDuration(&duration);
+ NS_ENSURE_TRUE(SUCCEEDED(hr), TimeUnit::Invalid());
+ return TimeUnit::FromMicroseconds(HNsToUsecs(duration));
+}
+
+TimeUnit GetSampleTime(IMFSample* aSample) {
+ NS_ENSURE_TRUE(aSample, TimeUnit::Invalid());
+ LONGLONG timestampHns = 0;
+ HRESULT hr = aSample->GetSampleTime(&timestampHns);
+ NS_ENSURE_TRUE(SUCCEEDED(hr), TimeUnit::Invalid());
+ return TimeUnit::FromMicroseconds(HNsToUsecs(timestampHns));
+}
+
+// Gets the sub-region of the video frame that should be displayed.
+// See:
+// http://msdn.microsoft.com/en-us/library/windows/desktop/bb530115(v=vs.85).aspx
+HRESULT
+GetPictureRegion(IMFMediaType* aMediaType, gfx::IntRect& aOutPictureRegion) {
+ // Determine if "pan and scan" is enabled for this media. If it is, we
+ // only display a region of the video frame, not the entire frame.
+ BOOL panScan =
+ MFGetAttributeUINT32(aMediaType, MF_MT_PAN_SCAN_ENABLED, FALSE);
+
+ // If pan and scan mode is enabled. Try to get the display region.
+ HRESULT hr = E_FAIL;
+ MFVideoArea videoArea;
+ memset(&videoArea, 0, sizeof(MFVideoArea));
+ if (panScan) {
+ hr = aMediaType->GetBlob(MF_MT_PAN_SCAN_APERTURE, (UINT8*)&videoArea,
+ sizeof(MFVideoArea), nullptr);
+ }
+
+ // If we're not in pan-and-scan mode, or the pan-and-scan region is not set,
+ // check for a minimimum display aperture.
+ if (!panScan || hr == MF_E_ATTRIBUTENOTFOUND) {
+ hr = aMediaType->GetBlob(MF_MT_MINIMUM_DISPLAY_APERTURE, (UINT8*)&videoArea,
+ sizeof(MFVideoArea), nullptr);
+ }
+
+ if (hr == MF_E_ATTRIBUTENOTFOUND) {
+ // Minimum display aperture is not set, for "backward compatibility with
+ // some components", check for a geometric aperture.
+ hr = aMediaType->GetBlob(MF_MT_GEOMETRIC_APERTURE, (UINT8*)&videoArea,
+ sizeof(MFVideoArea), nullptr);
+ }
+
+ if (SUCCEEDED(hr)) {
+ // The media specified a picture region, return it.
+ aOutPictureRegion = gfx::IntRect(MFOffsetToInt32(videoArea.OffsetX),
+ MFOffsetToInt32(videoArea.OffsetY),
+ videoArea.Area.cx, videoArea.Area.cy);
+ return S_OK;
+ }
+
+ // No picture region defined, fall back to using the entire video area.
+ UINT32 width = 0, height = 0;
+ hr = MFGetAttributeSize(aMediaType, MF_MT_FRAME_SIZE, &width, &height);
+ NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
+ NS_ENSURE_TRUE(width <= MAX_VIDEO_WIDTH, E_FAIL);
+ NS_ENSURE_TRUE(height <= MAX_VIDEO_HEIGHT, E_FAIL);
+
+ aOutPictureRegion = gfx::IntRect(0, 0, width, height);
+ return S_OK;
+}
+
+nsString GetProgramW6432Path() {
+ char* programPath = PR_GetEnvSecure("ProgramW6432");
+ if (!programPath) {
+ programPath = PR_GetEnvSecure("ProgramFiles");
+ }
+
+ if (!programPath) {
+ return u"C:\\Program Files"_ns;
+ }
+ return NS_ConvertUTF8toUTF16(programPath);
+}
+
+const char* MFTMessageTypeToStr(MFT_MESSAGE_TYPE aMsg) {
+ switch (aMsg) {
+ case MFT_MESSAGE_COMMAND_FLUSH:
+ return "MFT_MESSAGE_COMMAND_FLUSH";
+ case MFT_MESSAGE_COMMAND_DRAIN:
+ return "MFT_MESSAGE_COMMAND_DRAIN";
+ case MFT_MESSAGE_COMMAND_MARKER:
+ return "MFT_MESSAGE_COMMAND_MARKER";
+ case MFT_MESSAGE_SET_D3D_MANAGER:
+ return "MFT_MESSAGE_SET_D3D_MANAGER";
+ case MFT_MESSAGE_NOTIFY_BEGIN_STREAMING:
+ return "MFT_MESSAGE_NOTIFY_BEGIN_STREAMING";
+ case MFT_MESSAGE_NOTIFY_END_STREAMING:
+ return "MFT_MESSAGE_NOTIFY_END_STREAMING";
+ case MFT_MESSAGE_NOTIFY_END_OF_STREAM:
+ return "MFT_MESSAGE_NOTIFY_END_OF_STREAM";
+ case MFT_MESSAGE_NOTIFY_START_OF_STREAM:
+ return "MFT_MESSAGE_NOTIFY_START_OF_STREAM";
+ case MFT_MESSAGE_DROP_SAMPLES:
+ return "MFT_MESSAGE_DROP_SAMPLES";
+ case MFT_MESSAGE_COMMAND_TICK:
+ return "MFT_MESSAGE_COMMAND_TICK";
+ case MFT_MESSAGE_NOTIFY_RELEASE_RESOURCES:
+ return "MFT_MESSAGE_NOTIFY_RELEASE_RESOURCES";
+ case MFT_MESSAGE_NOTIFY_REACQUIRE_RESOURCES:
+ return "MFT_MESSAGE_NOTIFY_REACQUIRE_RESOURCES";
+ case MFT_MESSAGE_NOTIFY_EVENT:
+ return "MFT_MESSAGE_NOTIFY_EVENT";
+ case MFT_MESSAGE_COMMAND_SET_OUTPUT_STREAM_STATE:
+ return "MFT_MESSAGE_COMMAND_SET_OUTPUT_STREAM_STATE";
+ case MFT_MESSAGE_COMMAND_FLUSH_OUTPUT_STREAM:
+ return "MFT_MESSAGE_COMMAND_FLUSH_OUTPUT_STREAM";
+ default:
+ return "Invalid message?";
+ }
+}
+
+GUID AudioMimeTypeToMediaFoundationSubtype(const nsACString& aMimeType) {
+ if (aMimeType.EqualsLiteral("audio/mpeg")) {
+ return MFAudioFormat_MP3;
+ } else if (MP4Decoder::IsAAC(aMimeType)) {
+ return MFAudioFormat_AAC;
+ } else if (VorbisDataDecoder::IsVorbis(aMimeType)) {
+ return MFAudioFormat_Vorbis;
+ } else if (OpusDataDecoder::IsOpus(aMimeType)) {
+ return MFAudioFormat_Opus;
+ }
+ NS_WARNING("Unsupport audio mimetype");
+ return GUID_NULL;
+}
+
+GUID VideoMimeTypeToMediaFoundationSubtype(const nsACString& aMimeType) {
+ if (MP4Decoder::IsH264(aMimeType)) {
+ return MFVideoFormat_H264;
+ } else if (VPXDecoder::IsVP8(aMimeType)) {
+ return MFVideoFormat_VP80;
+ } else if (VPXDecoder::IsVP9(aMimeType)) {
+ return MFVideoFormat_VP90;
+ }
+#ifdef MOZ_AV1
+ else if (AOMDecoder::IsAV1(aMimeType)) {
+ return MFVideoFormat_AV1;
+ }
+#endif
+ NS_WARNING("Unsupport video mimetype");
+ return GUID_NULL;
+}
+
+void AACAudioSpecificConfigToUserData(uint8_t aAACProfileLevelIndication,
+ const uint8_t* aAudioSpecConfig,
+ uint32_t aConfigLength,
+ nsTArray<BYTE>& aOutUserData) {
+ MOZ_ASSERT(aOutUserData.IsEmpty());
+
+ // The MF_MT_USER_DATA for AAC is defined here:
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/dd742784%28v=vs.85%29.aspx
+ //
+ // For MFAudioFormat_AAC, MF_MT_USER_DATA contains the portion of
+ // the HEAACWAVEINFO structure that appears after the WAVEFORMATEX
+ // structure (that is, after the wfx member). This is followed by
+ // the AudioSpecificConfig() data, as defined by ISO/IEC 14496-3.
+ // [...]
+ // The length of the AudioSpecificConfig() data is 2 bytes for AAC-LC
+ // or HE-AAC with implicit signaling of SBR/PS. It is more than 2 bytes
+ // for HE-AAC with explicit signaling of SBR/PS.
+ //
+ // The value of audioObjectType as defined in AudioSpecificConfig()
+ // must be 2, indicating AAC-LC. The value of extensionAudioObjectType
+ // must be 5 for SBR or 29 for PS.
+ //
+ // HEAACWAVEINFO structure:
+ // typedef struct heaacwaveinfo_tag {
+ // WAVEFORMATEX wfx;
+ // WORD wPayloadType;
+ // WORD wAudioProfileLevelIndication;
+ // WORD wStructType;
+ // WORD wReserved1;
+ // DWORD dwReserved2;
+ // }
+ const UINT32 heeInfoLen = 4 * sizeof(WORD) + sizeof(DWORD);
+
+ // The HEAACWAVEINFO must have payload and profile set,
+ // the rest can be all 0x00.
+ BYTE heeInfo[heeInfoLen] = {0};
+ WORD* w = (WORD*)heeInfo;
+ w[0] = 0x0; // Payload type raw AAC packet
+ w[1] = aAACProfileLevelIndication;
+
+ aOutUserData.AppendElements(heeInfo, heeInfoLen);
+
+ if (aAACProfileLevelIndication == 2 && aConfigLength > 2) {
+ // The AudioSpecificConfig is TTTTTFFF|FCCCCGGG
+ // (T=ObjectType, F=Frequency, C=Channel, G=GASpecificConfig)
+ // If frequency = 0xf, then the frequency is explicitly defined on 24 bits.
+ int8_t frequency =
+ (aAudioSpecConfig[0] & 0x7) << 1 | (aAudioSpecConfig[1] & 0x80) >> 7;
+ int8_t channels = (aAudioSpecConfig[1] & 0x78) >> 3;
+ int8_t gasc = aAudioSpecConfig[1] & 0x7;
+ if (frequency != 0xf && channels && !gasc) {
+ // We enter this condition if the AudioSpecificConfig should theorically
+ // be 2 bytes long but it's not.
+ // The WMF AAC decoder will error if unknown extensions are found,
+ // so remove them.
+ aConfigLength = 2;
+ }
+ }
+ aOutUserData.AppendElements(aAudioSpecConfig, aConfigLength);
+}
+
+namespace wmf {
+
+static const wchar_t* sDLLs[] = {
+ L"mfplat.dll",
+ L"mf.dll",
+ L"dxva2.dll",
+ L"evr.dll",
+};
+
+HRESULT
+LoadDLLs() {
+ static bool sDLLsLoaded = false;
+ static bool sFailedToLoadDlls = false;
+
+ if (sDLLsLoaded) {
+ return S_OK;
+ }
+ if (sFailedToLoadDlls) {
+ return E_FAIL;
+ }
+
+ // Try to load all the required DLLs. If we fail to load any dll,
+ // unload the dlls we succeeded in loading.
+ nsTArray<const wchar_t*> loadedDlls;
+ for (const wchar_t* dll : sDLLs) {
+ if (!LoadLibrarySystem32(dll)) {
+ NS_WARNING("Failed to load WMF DLLs");
+ for (const wchar_t* loadedDll : loadedDlls) {
+ FreeLibrary(GetModuleHandleW(loadedDll));
+ }
+ sFailedToLoadDlls = true;
+ return E_FAIL;
+ }
+ loadedDlls.AppendElement(dll);
+ }
+ sDLLsLoaded = true;
+
+ return S_OK;
+}
+
+#define ENSURE_FUNCTION_PTR_HELPER(FunctionType, FunctionName, DLL) \
+ static FunctionType FunctionName##Ptr = nullptr; \
+ if (!FunctionName##Ptr) { \
+ FunctionName##Ptr = (FunctionType)GetProcAddress( \
+ GetModuleHandleW(L## #DLL), #FunctionName); \
+ if (!FunctionName##Ptr) { \
+ NS_WARNING("Failed to get GetProcAddress of " #FunctionName \
+ " from " #DLL); \
+ return E_FAIL; \
+ } \
+ }
+
+#define ENSURE_FUNCTION_PTR(FunctionName, DLL) \
+ ENSURE_FUNCTION_PTR_HELPER(decltype(::FunctionName)*, FunctionName, DLL)
+
+#define ENSURE_FUNCTION_PTR_(FunctionName, DLL) \
+ ENSURE_FUNCTION_PTR_HELPER(FunctionName##Ptr_t, FunctionName, DLL)
+
+#define DECL_FUNCTION_PTR(FunctionName, ...) \
+ typedef HRESULT(STDMETHODCALLTYPE* FunctionName##Ptr_t)(__VA_ARGS__)
+
+HRESULT
+MediaFoundationInitializer::MFStartup() {
+ if (IsWin7AndPre2000Compatible()) {
+ /*
+ * Specific exclude the usage of WMF on Win 7 with compatibility mode
+ * prior to Win 2000 as we may crash while trying to startup WMF.
+ * Using GetVersionEx API which takes compatibility mode into account.
+ * See Bug 1279171.
+ */
+ return E_FAIL;
+ }
+
+ HRESULT hr = LoadDLLs();
+ if (FAILED(hr)) {
+ return hr;
+ }
+
+ const int MF_WIN7_VERSION = (0x0002 << 16 | MF_API_VERSION);
+
+ // decltype is unusable for functions having default parameters
+ DECL_FUNCTION_PTR(MFStartup, ULONG, DWORD);
+ ENSURE_FUNCTION_PTR_(MFStartup, Mfplat.dll)
+
+ hr = E_FAIL;
+ mozilla::mscom::EnsureMTA(
+ [&]() -> void { hr = MFStartupPtr(MF_WIN7_VERSION, MFSTARTUP_FULL); });
+ return hr;
+}
+
+HRESULT
+MediaFoundationInitializer::MFShutdown() {
+ ENSURE_FUNCTION_PTR(MFShutdown, Mfplat.dll)
+ HRESULT hr = E_FAIL;
+ mozilla::mscom::EnsureMTA([&]() -> void { hr = (MFShutdownPtr)(); });
+ return hr;
+}
+
+HRESULT
+MFCreateMediaType(IMFMediaType** aOutMFType) {
+ ENSURE_FUNCTION_PTR(MFCreateMediaType, Mfplat.dll)
+ return (MFCreateMediaTypePtr)(aOutMFType);
+}
+
+HRESULT
+MFGetStrideForBitmapInfoHeader(DWORD aFormat, DWORD aWidth, LONG* aOutStride) {
+ ENSURE_FUNCTION_PTR(MFGetStrideForBitmapInfoHeader, evr.dll)
+ return (MFGetStrideForBitmapInfoHeaderPtr)(aFormat, aWidth, aOutStride);
+}
+
+HRESULT MFGetService(IUnknown* punkObject, REFGUID guidService, REFIID riid,
+ LPVOID* ppvObject) {
+ ENSURE_FUNCTION_PTR(MFGetService, mf.dll)
+ return (MFGetServicePtr)(punkObject, guidService, riid, ppvObject);
+}
+
+HRESULT
+DXVA2CreateDirect3DDeviceManager9(UINT* pResetToken,
+ IDirect3DDeviceManager9** ppDXVAManager) {
+ ENSURE_FUNCTION_PTR(DXVA2CreateDirect3DDeviceManager9, dxva2.dll)
+ return (DXVA2CreateDirect3DDeviceManager9Ptr)(pResetToken, ppDXVAManager);
+}
+
+HRESULT
+MFCreateSample(IMFSample** ppIMFSample) {
+ ENSURE_FUNCTION_PTR(MFCreateSample, mfplat.dll)
+ return (MFCreateSamplePtr)(ppIMFSample);
+}
+
+HRESULT
+MFCreateAlignedMemoryBuffer(DWORD cbMaxLength, DWORD fAlignmentFlags,
+ IMFMediaBuffer** ppBuffer) {
+ ENSURE_FUNCTION_PTR(MFCreateAlignedMemoryBuffer, mfplat.dll)
+ return (MFCreateAlignedMemoryBufferPtr)(cbMaxLength, fAlignmentFlags,
+ ppBuffer);
+}
+
+HRESULT
+MFCreateDXGIDeviceManager(UINT* pResetToken,
+ IMFDXGIDeviceManager** ppDXVAManager) {
+ ENSURE_FUNCTION_PTR(MFCreateDXGIDeviceManager, mfplat.dll)
+ return (MFCreateDXGIDeviceManagerPtr)(pResetToken, ppDXVAManager);
+}
+
+HRESULT
+MFCreateDXGISurfaceBuffer(REFIID riid, IUnknown* punkSurface,
+ UINT uSubresourceIndex, BOOL fButtomUpWhenLinear,
+ IMFMediaBuffer** ppBuffer) {
+ ENSURE_FUNCTION_PTR(MFCreateDXGISurfaceBuffer, mfplat.dll)
+ return (MFCreateDXGISurfaceBufferPtr)(riid, punkSurface, uSubresourceIndex,
+ fButtomUpWhenLinear, ppBuffer);
+}
+
+HRESULT
+MFTEnumEx(GUID guidCategory, UINT32 Flags,
+ const MFT_REGISTER_TYPE_INFO* pInputType,
+ const MFT_REGISTER_TYPE_INFO* pOutputType,
+ IMFActivate*** pppMFTActivate, UINT32* pnumMFTActivate) {
+ ENSURE_FUNCTION_PTR(MFTEnumEx, mfplat.dll)
+ return (MFTEnumExPtr)(guidCategory, Flags, pInputType, pOutputType,
+ pppMFTActivate, pnumMFTActivate);
+}
+
+HRESULT MFTGetInfo(CLSID clsidMFT, LPWSTR* pszName,
+ MFT_REGISTER_TYPE_INFO** ppInputTypes, UINT32* pcInputTypes,
+ MFT_REGISTER_TYPE_INFO** ppOutputTypes,
+ UINT32* pcOutputTypes, IMFAttributes** ppAttributes) {
+ ENSURE_FUNCTION_PTR(MFTGetInfo, mfplat.dll)
+ return (MFTGetInfoPtr)(clsidMFT, pszName, ppInputTypes, pcInputTypes,
+ ppOutputTypes, pcOutputTypes, ppAttributes);
+}
+
+HRESULT
+MFCreateAttributes(IMFAttributes** ppMFAttributes, UINT32 cInitialSize) {
+ ENSURE_FUNCTION_PTR(MFCreateAttributes, mfplat.dll)
+ return (MFCreateAttributesPtr)(ppMFAttributes, cInitialSize);
+}
+
+HRESULT MFCreateEventQueue(IMFMediaEventQueue** ppMediaEventQueue) {
+ ENSURE_FUNCTION_PTR(MFCreateEventQueue, mfplat.dll)
+ return (MFCreateEventQueuePtr)(ppMediaEventQueue);
+}
+
+HRESULT MFCreateStreamDescriptor(DWORD dwStreamIdentifier, DWORD cMediaTypes,
+ IMFMediaType** apMediaTypes,
+ IMFStreamDescriptor** ppDescriptor) {
+ ENSURE_FUNCTION_PTR(MFCreateStreamDescriptor, mfplat.dll)
+ return (MFCreateStreamDescriptorPtr)(dwStreamIdentifier, cMediaTypes,
+ apMediaTypes, ppDescriptor);
+}
+
+HRESULT MFCreateAsyncResult(IUnknown* punkObject, IMFAsyncCallback* pCallback,
+ IUnknown* punkState,
+ IMFAsyncResult** ppAsyncResult) {
+ ENSURE_FUNCTION_PTR(MFCreateAsyncResult, mfplat.dll)
+ return (MFCreateAsyncResultPtr)(punkObject, pCallback, punkState,
+ ppAsyncResult);
+}
+
+HRESULT MFCreatePresentationDescriptor(
+ DWORD cStreamDescriptors, IMFStreamDescriptor** apStreamDescriptors,
+ IMFPresentationDescriptor** ppPresentationDescriptor) {
+ ENSURE_FUNCTION_PTR(MFCreatePresentationDescriptor, mfplat.dll)
+ return (MFCreatePresentationDescriptorPtr)(cStreamDescriptors,
+ apStreamDescriptors,
+ ppPresentationDescriptor);
+}
+
+HRESULT MFCreateMemoryBuffer(DWORD cbMaxLength, IMFMediaBuffer** ppBuffer) {
+ ENSURE_FUNCTION_PTR(MFCreateMemoryBuffer, mfplat.dll);
+ return (MFCreateMemoryBufferPtr)(cbMaxLength, ppBuffer);
+}
+
+HRESULT MFLockDXGIDeviceManager(UINT* pResetToken,
+ IMFDXGIDeviceManager** ppManager) {
+ ENSURE_FUNCTION_PTR(MFLockDXGIDeviceManager, mfplat.dll);
+ return (MFLockDXGIDeviceManagerPtr)(pResetToken, ppManager);
+}
+
+HRESULT MFUnlockDXGIDeviceManager() {
+ ENSURE_FUNCTION_PTR(MFUnlockDXGIDeviceManager, mfplat.dll);
+ return (MFUnlockDXGIDeviceManagerPtr)();
+}
+
+HRESULT MFPutWorkItem(DWORD dwQueue, IMFAsyncCallback* pCallback,
+ IUnknown* pState) {
+ ENSURE_FUNCTION_PTR(MFPutWorkItem, mfplat.dll);
+ return (MFPutWorkItemPtr)(dwQueue, pCallback, pState);
+}
+
+HRESULT MFSerializeAttributesToStream(IMFAttributes* pAttr, DWORD dwOptions,
+ IStream* pStm) {
+ ENSURE_FUNCTION_PTR(MFSerializeAttributesToStream, mfplat.dll);
+ return (MFSerializeAttributesToStreamPtr)(pAttr, dwOptions, pStm);
+}
+
+HRESULT MFWrapMediaType(IMFMediaType* pOrig, REFGUID MajorType, REFGUID SubType,
+ IMFMediaType** ppWrap) {
+ ENSURE_FUNCTION_PTR(MFWrapMediaType, mfplat.dll);
+ return (MFWrapMediaTypePtr)(pOrig, MajorType, SubType, ppWrap);
+}
+
+} // end namespace wmf
+} // end namespace mozilla