tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

WMF.h (7983B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef WMF_H_
      8 #define WMF_H_
      9 
     10 // clang-format off
     11 #include <windows.h>
     12 #include <mfapi.h>
     13 #include <mfidl.h>
     14 #include <mfreadwrite.h>
     15 #include <mfobjects.h>
     16 #include <ks.h>
     17 #include <mferror.h>
     18 #include <propvarutil.h>
     19 #include <wmcodecdsp.h>
     20 #include <d3d9.h>
     21 #include <dxva2api.h>
     22 #include <wmcodecdsp.h>
     23 #include <codecapi.h>
     24 // clang-format on
     25 
     26 #include "mozilla/AppShutdown.h"
     27 #include "mozilla/Atomics.h"
     28 #include "mozilla/ClearOnShutdown.h"
     29 #include "mozilla/StaticMutex.h"
     30 #include "nsThreadUtils.h"
     31 
     32 // The Windows headers helpfully declare min and max macros, which don't
     33 // compile in the presence of std::min and std::max and unified builds.
     34 // So undef them here.
     35 #ifdef min
     36 #  undef min
     37 #endif
     38 #ifdef max
     39 #  undef max
     40 #endif
     41 
     42 // https://stackoverflow.com/questions/25759700/ms-format-tag-for-opus-codec
     43 #ifndef MFAudioFormat_Opus
     44 DEFINE_GUID(MFAudioFormat_Opus, WAVE_FORMAT_OPUS, 0x000, 0x0010, 0x80, 0x00,
     45            0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
     46 #endif
     47 
     48 const inline GUID CLSID_CMSVPXDecMFT = {
     49    0xe3aaf548,
     50    0xc9a4,
     51    0x4c6e,
     52    {0x23, 0x4d, 0x5a, 0xda, 0x37, 0x4b, 0x00, 0x00}};
     53 
     54 namespace mozilla::wmf {
     55 
     56 // A helper class for automatically starting and shuting down the Media
     57 // Foundation. Prior to using Media Foundation in a process, users should call
     58 // MediaFoundationInitializer::HasInitialized() to ensure Media Foundation is
     59 // initialized. Users should also check the result of this call, in case the
     60 // internal call to MFStartup fails. The first check to HasInitialized will
     61 // cause the helper to start up Media Foundation and set up a runnable to handle
     62 // Media Foundation shutdown at XPCOM shutdown. Calls after the first will not
     63 // cause any extra startups or shutdowns, so it's safe to check multiple times
     64 // in the same process. Users do not need to do any manual shutdown, the helper
     65 // will handle this internally.
     66 class MediaFoundationInitializer final {
     67 public:
     68  ~MediaFoundationInitializer() {
     69    if (mHasInitialized) {
     70      if (FAILED(MFShutdown())) {
     71        NS_WARNING("MFShutdown failed");
     72      }
     73    }
     74  }
     75  static bool HasInitialized() {
     76    if (sIsShutdown) {
     77      return false;
     78    }
     79    auto* rv = Get();
     80    return rv ? rv->mHasInitialized : false;
     81  }
     82 
     83 private:
     84  static MediaFoundationInitializer* Get() {
     85    {
     86      StaticMutexAutoLock lock(sCreateMutex);
     87      if (!sInitializer) {
     88        // Already in shutdown.
     89        if (AppShutdown::GetCurrentShutdownPhase() !=
     90            ShutdownPhase::NotInShutdown) {
     91          sIsShutdown = true;
     92          return nullptr;
     93        }
     94        sInitializer.reset(new MediaFoundationInitializer());
     95        auto shutdownCleanUp = [&] {
     96          if (AppShutdown::GetCurrentShutdownPhase() !=
     97              ShutdownPhase::NotInShutdown) {
     98            sInitializer.reset();
     99            sIsShutdown = true;
    100            return;
    101          }
    102          // As MFShutdown needs to run on the MTA thread that is destroyed
    103          // on XPCOMShutdownThreads, so we need to run cleanup before that
    104          // phase.
    105          RunOnShutdown(
    106              [&]() {
    107                sInitializer.reset();
    108                sIsShutdown = true;
    109              },
    110              ShutdownPhase::XPCOMShutdown);
    111        };
    112        if (NS_IsMainThread()) {
    113          shutdownCleanUp();
    114        } else {
    115          GetMainThreadSerialEventTarget()->Dispatch(NS_NewRunnableFunction(
    116              "MediaFoundationInitializer::Get", shutdownCleanUp));
    117        }
    118      }
    119    }
    120    return sInitializer.get();
    121  }
    122 
    123  MediaFoundationInitializer() : mHasInitialized(SUCCEEDED(MFStartup())) {
    124    if (!mHasInitialized) {
    125      NS_WARNING("MFStartup failed");
    126    }
    127  }
    128 
    129  // If successful, loads all required WMF DLLs and calls the WMF MFStartup()
    130  // function. This delegates the WMF MFStartup() call to the MTA thread if
    131  // the current thread is not MTA. This is to ensure we always interact with
    132  // WMF from threads with the same COM compartment model.
    133  HRESULT MFStartup();
    134 
    135  // Calls the WMF MFShutdown() function. Call this once for every time
    136  // wmf::MFStartup() succeeds. Note: does not unload the WMF DLLs loaded by
    137  // MFStartup(); leaves them in memory to save I/O at next MFStartup() call.
    138  // This delegates the WMF MFShutdown() call to the MTA thread if the current
    139  // thread is not MTA. This is to ensure we always interact with
    140  // WMF from threads with the same COM compartment model.
    141  HRESULT MFShutdown();
    142 
    143  constinit static inline UniquePtr<MediaFoundationInitializer> sInitializer;
    144  static inline StaticMutex sCreateMutex;
    145  static inline Atomic<bool> sIsShutdown{false};
    146  const bool mHasInitialized;
    147 };
    148 
    149 // All functions below are wrappers around the corresponding WMF function,
    150 // and automatically locate and call the corresponding function in the WMF DLLs.
    151 
    152 HRESULT MFCreateMediaType(IMFMediaType** aOutMFType);
    153 
    154 HRESULT MFGetStrideForBitmapInfoHeader(DWORD aFormat, DWORD aWidth,
    155                                       LONG* aOutStride);
    156 
    157 HRESULT MFGetService(IUnknown* punkObject, REFGUID guidService, REFIID riid,
    158                     LPVOID* ppvObject);
    159 
    160 HRESULT DXVA2CreateDirect3DDeviceManager9(
    161    UINT* pResetToken, IDirect3DDeviceManager9** ppDXVAManager);
    162 
    163 HRESULT MFCreateDXGIDeviceManager(UINT* pResetToken,
    164                                  IMFDXGIDeviceManager** ppDXVAManager);
    165 
    166 HRESULT MFCreateSample(IMFSample** ppIMFSample);
    167 
    168 HRESULT MFCreateAlignedMemoryBuffer(DWORD cbMaxLength, DWORD fAlignmentFlags,
    169                                    IMFMediaBuffer** ppBuffer);
    170 
    171 HRESULT MFCreateDXGISurfaceBuffer(REFIID riid, IUnknown* punkSurface,
    172                                  UINT uSubresourceIndex,
    173                                  BOOL fButtomUpWhenLinear,
    174                                  IMFMediaBuffer** ppBuffer);
    175 
    176 HRESULT MFTEnumEx(GUID guidCategory, UINT32 Flags,
    177                  const MFT_REGISTER_TYPE_INFO* pInputType,
    178                  const MFT_REGISTER_TYPE_INFO* pOutputType,
    179                  IMFActivate*** pppMFTActivate, UINT32* pnumMFTActivate);
    180 
    181 HRESULT MFTGetInfo(CLSID clsidMFT, LPWSTR* pszName,
    182                   MFT_REGISTER_TYPE_INFO** ppInputTypes, UINT32* pcInputTypes,
    183                   MFT_REGISTER_TYPE_INFO** ppOutputTypes,
    184                   UINT32* pcOutputTypes, IMFAttributes** ppAttributes);
    185 
    186 HRESULT MFCreateAttributes(IMFAttributes** ppMFAttributes, UINT32 cInitialSize);
    187 
    188 HRESULT MFCreateEventQueue(IMFMediaEventQueue** ppMediaEventQueue);
    189 
    190 HRESULT MFCreateStreamDescriptor(DWORD dwStreamIdentifier, DWORD cMediaTypes,
    191                                 IMFMediaType** apMediaTypes,
    192                                 IMFStreamDescriptor** ppDescriptor);
    193 
    194 HRESULT MFCreateAsyncResult(IUnknown* punkObject, IMFAsyncCallback* pCallback,
    195                            IUnknown* punkState,
    196                            IMFAsyncResult** ppAsyncResult);
    197 
    198 HRESULT MFCreatePresentationDescriptor(
    199    DWORD cStreamDescriptors, IMFStreamDescriptor** apStreamDescriptors,
    200    IMFPresentationDescriptor** ppPresentationDescriptor);
    201 
    202 HRESULT MFCreateMemoryBuffer(DWORD cbMaxLength, IMFMediaBuffer** ppBuffer);
    203 
    204 HRESULT MFLockDXGIDeviceManager(UINT* pResetToken,
    205                                IMFDXGIDeviceManager** ppManager);
    206 
    207 HRESULT MFUnlockDXGIDeviceManager();
    208 
    209 HRESULT MFPutWorkItem(DWORD dwQueue, IMFAsyncCallback* pCallback,
    210                      IUnknown* pState);
    211 
    212 HRESULT MFSerializeAttributesToStream(IMFAttributes* pAttr, DWORD dwOptions,
    213                                      IStream* pStm);
    214 
    215 HRESULT MFWrapMediaType(IMFMediaType* pOrig, REFGUID MajorType, REFGUID SubType,
    216                        IMFMediaType** ppWrap);
    217 
    218 }  // namespace mozilla::wmf
    219 
    220 #endif