diff options
Diffstat (limited to 'dom/media/platforms/wmf/WMF.h')
-rw-r--r-- | dom/media/platforms/wmf/WMF.h | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/dom/media/platforms/wmf/WMF.h b/dom/media/platforms/wmf/WMF.h new file mode 100644 index 0000000000..740442ceda --- /dev/null +++ b/dom/media/platforms/wmf/WMF.h @@ -0,0 +1,198 @@ +/* -*- 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/. */ + +#ifndef WMF_H_ +#define WMF_H_ + +#include <windows.h> +#include <mfapi.h> +#include <mfidl.h> +#include <mfreadwrite.h> +#include <mfobjects.h> +#include <ks.h> +#include <stdio.h> +#include <mferror.h> +#include <propvarutil.h> +#include <wmcodecdsp.h> +#include <d3d9.h> +#include <dxva2api.h> +#include <wmcodecdsp.h> +#include <codecapi.h> + +#include "mozilla/Atomics.h" +#include "mozilla/ClearOnShutdown.h" +#include "mozilla/StaticMutex.h" +#include "nsThreadUtils.h" + +// The Windows headers helpfully declare min and max macros, which don't +// compile in the presence of std::min and std::max and unified builds. +// So undef them here. +#ifdef min +# undef min +#endif +#ifdef max +# undef max +#endif + +// https://stackoverflow.com/questions/25759700/ms-format-tag-for-opus-codec +#ifndef MFAudioFormat_Opus +DEFINE_GUID(MFAudioFormat_Opus, WAVE_FORMAT_OPUS, 0x000, 0x0010, 0x80, 0x00, + 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); +#endif + +const inline GUID CLSID_CMSVPXDecMFT = { + 0xe3aaf548, + 0xc9a4, + 0x4c6e, + {0x23, 0x4d, 0x5a, 0xda, 0x37, 0x4b, 0x00, 0x00}}; + +namespace mozilla::wmf { + +// A helper class for automatically starting and shuting down the Media +// Foundation. Prior to using Media Foundation in a process, users should call +// MediaFoundationInitializer::HasInitialized() to ensure Media Foundation is +// initialized. Users should also check the result of this call, in case the +// internal call to MFStartup fails. The first check to HasInitialized will +// cause the helper to start up Media Foundation and set up a runnable to handle +// Media Foundation shutdown at XPCOM shutdown. Calls after the first will not +// cause any extra startups or shutdowns, so it's safe to check multiple times +// in the same process. Users do not need to do any manual shutdown, the helper +// will handle this internally. +class MediaFoundationInitializer final { + public: + ~MediaFoundationInitializer() { + if (mHasInitialized) { + if (FAILED(MFShutdown())) { + NS_WARNING("MFShutdown failed"); + } + } + } + static bool HasInitialized() { + if (sIsShutdown) { + return false; + } + return Get()->mHasInitialized; + } + + private: + static MediaFoundationInitializer* Get() { + { + StaticMutexAutoLock lock(sCreateMutex); + if (!sInitializer) { + sInitializer.reset(new MediaFoundationInitializer()); + GetMainThreadSerialEventTarget()->Dispatch( + NS_NewRunnableFunction("MediaFoundationInitializer::Get", [&] { + // Need to run this before MTA thread gets destroyed. + RunOnShutdown( + [&] { + sInitializer.reset(); + sIsShutdown = true; + }, + ShutdownPhase::XPCOMShutdown); + })); + } + } + return sInitializer.get(); + } + + MediaFoundationInitializer() : mHasInitialized(SUCCEEDED(MFStartup())) { + if (!mHasInitialized) { + NS_WARNING("MFStartup failed"); + } + } + + // If successful, loads all required WMF DLLs and calls the WMF MFStartup() + // function. This delegates the WMF MFStartup() call to the MTA thread if + // the current thread is not MTA. This is to ensure we always interact with + // WMF from threads with the same COM compartment model. + HRESULT MFStartup(); + + // Calls the WMF MFShutdown() function. Call this once for every time + // wmf::MFStartup() succeeds. Note: does not unload the WMF DLLs loaded by + // MFStartup(); leaves them in memory to save I/O at next MFStartup() call. + // This delegates the WMF MFShutdown() call to the MTA thread if the current + // thread is not MTA. This is to ensure we always interact with + // WMF from threads with the same COM compartment model. + HRESULT MFShutdown(); + + static inline UniquePtr<MediaFoundationInitializer> sInitializer; + static inline StaticMutex sCreateMutex; + static inline Atomic<bool> sIsShutdown{false}; + const bool mHasInitialized; +}; + +// All functions below are wrappers around the corresponding WMF function, +// and automatically locate and call the corresponding function in the WMF DLLs. + +HRESULT MFCreateMediaType(IMFMediaType** aOutMFType); + +HRESULT MFGetStrideForBitmapInfoHeader(DWORD aFormat, DWORD aWidth, + LONG* aOutStride); + +HRESULT MFGetService(IUnknown* punkObject, REFGUID guidService, REFIID riid, + LPVOID* ppvObject); + +HRESULT DXVA2CreateDirect3DDeviceManager9( + UINT* pResetToken, IDirect3DDeviceManager9** ppDXVAManager); + +HRESULT MFCreateDXGIDeviceManager(UINT* pResetToken, + IMFDXGIDeviceManager** ppDXVAManager); + +HRESULT MFCreateSample(IMFSample** ppIMFSample); + +HRESULT MFCreateAlignedMemoryBuffer(DWORD cbMaxLength, DWORD fAlignmentFlags, + IMFMediaBuffer** ppBuffer); + +HRESULT MFCreateDXGISurfaceBuffer(REFIID riid, IUnknown* punkSurface, + UINT uSubresourceIndex, + BOOL fButtomUpWhenLinear, + IMFMediaBuffer** ppBuffer); + +HRESULT MFTEnumEx(GUID guidCategory, UINT32 Flags, + const MFT_REGISTER_TYPE_INFO* pInputType, + const MFT_REGISTER_TYPE_INFO* pOutputType, + IMFActivate*** pppMFTActivate, UINT32* pnumMFTActivate); + +HRESULT MFTGetInfo(CLSID clsidMFT, LPWSTR* pszName, + MFT_REGISTER_TYPE_INFO** ppInputTypes, UINT32* pcInputTypes, + MFT_REGISTER_TYPE_INFO** ppOutputTypes, + UINT32* pcOutputTypes, IMFAttributes** ppAttributes); + +HRESULT MFCreateAttributes(IMFAttributes** ppMFAttributes, UINT32 cInitialSize); + +HRESULT MFCreateEventQueue(IMFMediaEventQueue** ppMediaEventQueue); + +HRESULT MFCreateStreamDescriptor(DWORD dwStreamIdentifier, DWORD cMediaTypes, + IMFMediaType** apMediaTypes, + IMFStreamDescriptor** ppDescriptor); + +HRESULT MFCreateAsyncResult(IUnknown* punkObject, IMFAsyncCallback* pCallback, + IUnknown* punkState, + IMFAsyncResult** ppAsyncResult); + +HRESULT MFCreatePresentationDescriptor( + DWORD cStreamDescriptors, IMFStreamDescriptor** apStreamDescriptors, + IMFPresentationDescriptor** ppPresentationDescriptor); + +HRESULT MFCreateMemoryBuffer(DWORD cbMaxLength, IMFMediaBuffer** ppBuffer); + +HRESULT MFLockDXGIDeviceManager(UINT* pResetToken, + IMFDXGIDeviceManager** ppManager); + +HRESULT MFUnlockDXGIDeviceManager(); + +HRESULT MFPutWorkItem(DWORD dwQueue, IMFAsyncCallback* pCallback, + IUnknown* pState); + +HRESULT MFSerializeAttributesToStream(IMFAttributes* pAttr, DWORD dwOptions, + IStream* pStm); + +HRESULT MFWrapMediaType(IMFMediaType* pOrig, REFGUID MajorType, REFGUID SubType, + IMFMediaType** ppWrap); + +} // namespace mozilla::wmf + +#endif |