Revision control
++ // Copyright (C) 2021 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
++
++ #include "qwindowsmediafoundation_p.h"
++
++ #include <QtCore/qdebug.h>
++ #include <QtCore/qmutex.h>
++ #include <QtCore/private/qfunctions_win_p.h>
++
++ QT_BEGIN_NAMESPACE
++
++ namespace {
++
++ Q_GLOBAL_STATIC(QWindowsMediaFoundation, s_wmf);
++
++ template <typename T>
++ bool setProcAddress(QSystemLibrary &lib, T &f, const char name[])
++ {
++ f = reinterpret_cast<T>(lib.resolve(name));
++ return static_cast<bool>(f);
++ }
++
++ } // namespace
++
++ QWindowsMediaFoundation *QWindowsMediaFoundation::instance()
++ {
++ if (s_wmf->valid())
++ return s_wmf;
++
++ return nullptr;
++ }
++
++ QWindowsMediaFoundation::QWindowsMediaFoundation()
++ {
++ if (!m_mfplat.load(false))
++ return;
++
++ if (!m_mf.load(false))
++ return;
++
++ if (!m_mfreadwrite.load(false))
++ return;
++
++ m_valid = setProcAddress(m_mfplat, mfStartup, "MFStartup")
++ && setProcAddress(m_mfplat, mfShutdown, "MFShutdown")
++ && setProcAddress(m_mfplat, mfCreateMediaType, "MFCreateMediaType")
++ && setProcAddress(m_mfplat, mfCreateMemoryBuffer, "MFCreateMemoryBuffer")
++ && setProcAddress(m_mfplat, mfCreateSample, "MFCreateSample")
++ && setProcAddress(m_mfplat, mfCreateAttributes, "MFCreateAttributes")
++ && setProcAddress(m_mf, mfEnumDeviceSources, "MFEnumDeviceSources")
++ && setProcAddress(m_mfreadwrite, mfCreateSourceReaderFromMediaSource,
++ "MFCreateSourceReaderFromMediaSource");
++
++ Q_ASSERT(m_valid); // If it is not valid at this point, we have a programming bug
++ }
++
++ QWindowsMediaFoundation::~QWindowsMediaFoundation() = default;
++
++ bool QWindowsMediaFoundation::valid() const
++ {
++ return m_valid;
++ }
++
++ QMFRuntimeInit::QMFRuntimeInit()
++ : QMFRuntimeInit{
++ QWindowsMediaFoundation::instance(),
++ }
++ {
++ }
++
++ static HRESULT startupMediaFoundation(QWindowsMediaFoundation *wmf)
++ {
++ qt_win_ensureComInitializedOnThisThread();
++ return wmf ? wmf->mfStartup(MF_VERSION, MFSTARTUP_FULL) : E_FAIL;
++ }
++
++ QMFRuntimeInit::QMFRuntimeInit(QWindowsMediaFoundation *wmf)
++ : m_wmf{ wmf }, m_initResult{ startupMediaFoundation(wmf) }
++ {
++ if (m_initResult != S_OK)
++ qErrnoWarning(m_initResult, "Failed to initialize Windows Media Foundation");
++ }
++
++ QMFRuntimeInit::~QMFRuntimeInit()
++ {
++ // According to documentation MFShutdown should be called
++ // also when MFStartup failed. This is wrong.
++ if (FAILED(m_initResult))
++ return;
++
++ const HRESULT hr = m_wmf->mfShutdown();
++ if (hr != S_OK)
++ qErrnoWarning(hr, "Failed to shut down Windows Media Foundation");
++ }
++
++ QT_END_NAMESPACE