diff options
Diffstat (limited to 'src/plugins/wmf/player')
25 files changed, 0 insertions, 7901 deletions
diff --git a/src/plugins/wmf/player/mfactivate.cpp b/src/plugins/wmf/player/mfactivate.cpp deleted file mode 100644 index e06906584..000000000 --- a/src/plugins/wmf/player/mfactivate.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "mfactivate.h" - -#include <mfapi.h> - -MFAbstractActivate::MFAbstractActivate() - : m_attributes(0) - , m_cRef(1) -{ - MFCreateAttributes(&m_attributes, 0); -} - -MFAbstractActivate::~MFAbstractActivate() -{ - if (m_attributes) - m_attributes->Release(); -} - - -HRESULT MFAbstractActivate::QueryInterface(REFIID riid, LPVOID *ppvObject) -{ - if (!ppvObject) - return E_POINTER; - if (riid == IID_IMFActivate) { - *ppvObject = static_cast<IMFActivate*>(this); - } else if (riid == IID_IMFAttributes) { - *ppvObject = static_cast<IMFAttributes*>(this); - } else if (riid == IID_IUnknown) { - *ppvObject = static_cast<IUnknown*>(static_cast<IMFActivate*>(this)); - } else { - *ppvObject = NULL; - return E_NOINTERFACE; - } - AddRef(); - return S_OK; -} - -ULONG MFAbstractActivate::AddRef(void) -{ - return InterlockedIncrement(&m_cRef); -} - -ULONG MFAbstractActivate::Release(void) -{ - ULONG cRef = InterlockedDecrement(&m_cRef); - if (cRef == 0) - delete this; - return cRef; -} diff --git a/src/plugins/wmf/player/mfactivate.h b/src/plugins/wmf/player/mfactivate.h deleted file mode 100644 index 3243296e8..000000000 --- a/src/plugins/wmf/player/mfactivate.h +++ /dev/null @@ -1,212 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef MFACTIVATE_H -#define MFACTIVATE_H - -#include <mfidl.h> - -class MFAbstractActivate : public IMFActivate -{ -public: - explicit MFAbstractActivate(); - virtual ~MFAbstractActivate(); - - //from IUnknown - STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppvObject); - STDMETHODIMP_(ULONG) AddRef(void); - STDMETHODIMP_(ULONG) Release(void); - - //from IMFAttributes - STDMETHODIMP GetItem(REFGUID guidKey, PROPVARIANT *pValue) - { - return m_attributes->GetItem(guidKey, pValue); - } - - STDMETHODIMP GetItemType(REFGUID guidKey, MF_ATTRIBUTE_TYPE *pType) - { - return m_attributes->GetItemType(guidKey, pType); - } - - STDMETHODIMP CompareItem(REFGUID guidKey, REFPROPVARIANT Value, BOOL *pbResult) - { - return m_attributes->CompareItem(guidKey, Value, pbResult); - } - - STDMETHODIMP Compare(IMFAttributes *pTheirs, MF_ATTRIBUTES_MATCH_TYPE MatchType, BOOL *pbResult) - { - return m_attributes->Compare(pTheirs, MatchType, pbResult); - } - - STDMETHODIMP GetUINT32(REFGUID guidKey, UINT32 *punValue) - { - return m_attributes->GetUINT32(guidKey, punValue); - } - - STDMETHODIMP GetUINT64(REFGUID guidKey, UINT64 *punValue) - { - return m_attributes->GetUINT64(guidKey, punValue); - } - - STDMETHODIMP GetDouble(REFGUID guidKey, double *pfValue) - { - return m_attributes->GetDouble(guidKey, pfValue); - } - - STDMETHODIMP GetGUID(REFGUID guidKey, GUID *pguidValue) - { - return m_attributes->GetGUID(guidKey, pguidValue); - } - - STDMETHODIMP GetStringLength(REFGUID guidKey, UINT32 *pcchLength) - { - return m_attributes->GetStringLength(guidKey, pcchLength); - } - - STDMETHODIMP GetString(REFGUID guidKey, LPWSTR pwszValue, UINT32 cchBufSize, UINT32 *pcchLength) - { - return m_attributes->GetString(guidKey, pwszValue, cchBufSize, pcchLength); - } - - STDMETHODIMP GetAllocatedString(REFGUID guidKey, LPWSTR *ppwszValue, UINT32 *pcchLength) - { - return m_attributes->GetAllocatedString(guidKey, ppwszValue, pcchLength); - } - - STDMETHODIMP GetBlobSize(REFGUID guidKey, UINT32 *pcbBlobSize) - { - return m_attributes->GetBlobSize(guidKey, pcbBlobSize); - } - - STDMETHODIMP GetBlob(REFGUID guidKey, UINT8 *pBuf, UINT32 cbBufSize, UINT32 *pcbBlobSize) - { - return m_attributes->GetBlob(guidKey, pBuf, cbBufSize, pcbBlobSize); - } - - STDMETHODIMP GetAllocatedBlob(REFGUID guidKey, UINT8 **ppBuf, UINT32 *pcbSize) - { - return m_attributes->GetAllocatedBlob(guidKey, ppBuf, pcbSize); - } - - STDMETHODIMP GetUnknown(REFGUID guidKey, REFIID riid, LPVOID *ppv) - { - return m_attributes->GetUnknown(guidKey, riid, ppv); - } - - STDMETHODIMP SetItem(REFGUID guidKey, REFPROPVARIANT Value) - { - return m_attributes->SetItem(guidKey, Value); - } - - STDMETHODIMP DeleteItem(REFGUID guidKey) - { - return m_attributes->DeleteItem(guidKey); - } - - STDMETHODIMP DeleteAllItems() - { - return m_attributes->DeleteAllItems(); - } - - STDMETHODIMP SetUINT32(REFGUID guidKey, UINT32 unValue) - { - return m_attributes->SetUINT32(guidKey, unValue); - } - - STDMETHODIMP SetUINT64(REFGUID guidKey, UINT64 unValue) - { - return m_attributes->SetUINT64(guidKey, unValue); - } - - STDMETHODIMP SetDouble(REFGUID guidKey, double fValue) - { - return m_attributes->SetDouble(guidKey, fValue); - } - - STDMETHODIMP SetGUID(REFGUID guidKey, REFGUID guidValue) - { - return m_attributes->SetGUID(guidKey, guidValue); - } - - STDMETHODIMP SetString(REFGUID guidKey, LPCWSTR wszValue) - { - return m_attributes->SetString(guidKey, wszValue); - } - - STDMETHODIMP SetBlob(REFGUID guidKey, const UINT8 *pBuf, UINT32 cbBufSize) - { - return m_attributes->SetBlob(guidKey, pBuf, cbBufSize); - } - - STDMETHODIMP SetUnknown(REFGUID guidKey, IUnknown *pUnknown) - { - return m_attributes->SetUnknown(guidKey, pUnknown); - } - - STDMETHODIMP LockStore() - { - return m_attributes->LockStore(); - } - - STDMETHODIMP UnlockStore() - { - return m_attributes->UnlockStore(); - } - - STDMETHODIMP GetCount(UINT32 *pcItems) - { - return m_attributes->GetCount(pcItems); - } - - STDMETHODIMP GetItemByIndex(UINT32 unIndex, GUID *pguidKey, PROPVARIANT *pValue) - { - return m_attributes->GetItemByIndex(unIndex, pguidKey, pValue); - } - - STDMETHODIMP CopyAllItems(IMFAttributes *pDest) - { - return m_attributes->CopyAllItems(pDest); - } - -private: - IMFAttributes *m_attributes; - ULONG m_cRef; -}; - -#endif // MFACTIVATE_H diff --git a/src/plugins/wmf/player/mfaudioendpointcontrol.cpp b/src/plugins/wmf/player/mfaudioendpointcontrol.cpp deleted file mode 100644 index 3b86c52b7..000000000 --- a/src/plugins/wmf/player/mfaudioendpointcontrol.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Mobility Components. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "QtCore/qdebug.h" -#include "mfaudioendpointcontrol.h" - -#include <mmdeviceapi.h> - -MFAudioEndpointControl::MFAudioEndpointControl(QObject *parent) - : QAudioOutputSelectorControl(parent) - , m_currentActivate(0) -{ -} - -MFAudioEndpointControl::~MFAudioEndpointControl() -{ - clear(); -} - -void MFAudioEndpointControl::clear() -{ - m_activeEndpoint.clear(); - - for (auto it = m_devices.cbegin(), end = m_devices.cend(); it != end; ++it) - CoTaskMemFree(it.value()); - - m_devices.clear(); - - if (m_currentActivate) - m_currentActivate->Release(); - m_currentActivate = NULL; -} - -QList<QString> MFAudioEndpointControl::availableOutputs() const -{ - return m_devices.keys(); -} - -QString MFAudioEndpointControl::outputDescription(const QString &name) const -{ - return name.section(QLatin1Char('\\'), -1); -} - -QString MFAudioEndpointControl::defaultOutput() const -{ - return m_defaultEndpoint; -} - -QString MFAudioEndpointControl::activeOutput() const -{ - return m_activeEndpoint; -} - -void MFAudioEndpointControl::setActiveOutput(const QString &name) -{ - if (m_activeEndpoint == name) - return; - QMap<QString, LPWSTR>::iterator it = m_devices.find(name); - if (it == m_devices.end()) - return; - - LPWSTR wstrID = *it; - IMFActivate *activate = NULL; - HRESULT hr = MFCreateAudioRendererActivate(&activate); - if (FAILED(hr)) { - qWarning() << "Failed to create audio renderer activate"; - return; - } - - if (wstrID) { - hr = activate->SetString(MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID, wstrID); - } else { - //This is the default one that has been inserted in updateEndpoints(), - //so give the activate a hint that we want to use the device for multimedia playback - //then the media foundation will choose an appropriate one. - - //from MSDN: - //The ERole enumeration defines constants that indicate the role that the system has assigned to an audio endpoint device. - //eMultimedia: Music, movies, narration, and live music recording. - hr = activate->SetUINT32(MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE, eMultimedia); - } - - if (FAILED(hr)) { - qWarning() << "Failed to set attribute for audio device" << name; - return; - } - - if (m_currentActivate) - m_currentActivate->Release(); - m_currentActivate = activate; - m_activeEndpoint = name; -} - -IMFActivate* MFAudioEndpointControl::createActivate() -{ - clear(); - - updateEndpoints(); - - // Check if an endpoint is available ("Default" is always inserted) - if (m_devices.count() <= 1) - return NULL; - - setActiveOutput(m_defaultEndpoint); - - return m_currentActivate; -} - -void MFAudioEndpointControl::updateEndpoints() -{ - m_defaultEndpoint = QString::fromLatin1("Default"); - m_devices.insert(m_defaultEndpoint, NULL); - - IMMDeviceEnumerator *pEnum = NULL; - HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), - NULL, CLSCTX_ALL, - __uuidof(IMMDeviceEnumerator), - (void**)&pEnum); - if (SUCCEEDED(hr)) { - IMMDeviceCollection *pDevices = NULL; - hr = pEnum->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pDevices); - if (SUCCEEDED(hr)) { - UINT count; - hr = pDevices->GetCount(&count); - if (SUCCEEDED(hr)) { - for (UINT i = 0; i < count; ++i) { - IMMDevice *pDevice = NULL; - hr = pDevices->Item(i, &pDevice); - if (SUCCEEDED(hr)) { - LPWSTR wstrID = NULL; - hr = pDevice->GetId(&wstrID); - if (SUCCEEDED(hr)) { - QString deviceId = QString::fromWCharArray(wstrID); - m_devices.insert(deviceId, wstrID); - } - pDevice->Release(); - } - } - } - pDevices->Release(); - } - pEnum->Release(); - } -} diff --git a/src/plugins/wmf/player/mfaudioendpointcontrol.h b/src/plugins/wmf/player/mfaudioendpointcontrol.h deleted file mode 100644 index a439c31a5..000000000 --- a/src/plugins/wmf/player/mfaudioendpointcontrol.h +++ /dev/null @@ -1,82 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Mobility Components. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef MFAUDIOENDPOINTCONTROL_H -#define MFAUDIOENDPOINTCONTROL_H - -#include <mfapi.h> -#include <mfidl.h> - -#include "qaudiooutputselectorcontrol.h" - -class MFPlayerService; - -QT_USE_NAMESPACE - -class MFAudioEndpointControl : public QAudioOutputSelectorControl -{ - Q_OBJECT -public: - MFAudioEndpointControl(QObject *parent = 0); - ~MFAudioEndpointControl(); - - QList<QString> availableOutputs() const; - - QString outputDescription(const QString &name) const; - - QString defaultOutput() const; - QString activeOutput() const; - - void setActiveOutput(const QString& name); - - IMFActivate* createActivate(); - -private: - void clear(); - void updateEndpoints(); - - QString m_defaultEndpoint; - QString m_activeEndpoint; - QMap<QString, LPWSTR> m_devices; - IMFActivate *m_currentActivate; - -}; - -#endif - diff --git a/src/plugins/wmf/player/mfaudioprobecontrol.cpp b/src/plugins/wmf/player/mfaudioprobecontrol.cpp deleted file mode 100644 index c703922c8..000000000 --- a/src/plugins/wmf/player/mfaudioprobecontrol.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "mfaudioprobecontrol.h" - -MFAudioProbeControl::MFAudioProbeControl(QObject *parent): - QMediaAudioProbeControl(parent) -{ -} - -MFAudioProbeControl::~MFAudioProbeControl() -{ -} - -void MFAudioProbeControl::bufferProbed(const char *data, quint32 size, const QAudioFormat& format, qint64 startTime) -{ - if (!format.isValid()) - return; - - QAudioBuffer audioBuffer = QAudioBuffer(QByteArray(data, size), format, startTime); - - { - QMutexLocker locker(&m_bufferMutex); - m_pendingBuffer = audioBuffer; - QMetaObject::invokeMethod(this, "bufferProbed", Qt::QueuedConnection); - } -} - -void MFAudioProbeControl::bufferProbed() -{ - QAudioBuffer audioBuffer; - { - QMutexLocker locker(&m_bufferMutex); - if (!m_pendingBuffer.isValid()) - return; - audioBuffer = m_pendingBuffer; - } - emit audioBufferProbed(audioBuffer); -} diff --git a/src/plugins/wmf/player/mfaudioprobecontrol.h b/src/plugins/wmf/player/mfaudioprobecontrol.h deleted file mode 100644 index c8a06148f..000000000 --- a/src/plugins/wmf/player/mfaudioprobecontrol.h +++ /dev/null @@ -1,66 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef MFAUDIOPROBECONTROL_H -#define MFAUDIOPROBECONTROL_H - -#include <qmediaaudioprobecontrol.h> -#include <QtCore/qmutex.h> -#include <qaudiobuffer.h> - -QT_USE_NAMESPACE - -class MFAudioProbeControl : public QMediaAudioProbeControl -{ - Q_OBJECT -public: - explicit MFAudioProbeControl(QObject *parent); - virtual ~MFAudioProbeControl(); - - void bufferProbed(const char *data, quint32 size, const QAudioFormat& format, qint64 startTime); - -private slots: - void bufferProbed(); - -private: - QAudioBuffer m_pendingBuffer; - QMutex m_bufferMutex; -}; - -#endif diff --git a/src/plugins/wmf/player/mfevrvideowindowcontrol.cpp b/src/plugins/wmf/player/mfevrvideowindowcontrol.cpp deleted file mode 100644 index 4b3e0f303..000000000 --- a/src/plugins/wmf/player/mfevrvideowindowcontrol.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "mfevrvideowindowcontrol.h" - -#include <qdebug.h> - -MFEvrVideoWindowControl::MFEvrVideoWindowControl(QObject *parent) - : EvrVideoWindowControl(parent) - , m_currentActivate(NULL) - , m_evrSink(NULL) -{ -} - -MFEvrVideoWindowControl::~MFEvrVideoWindowControl() -{ - clear(); -} - -void MFEvrVideoWindowControl::clear() -{ - setEvr(NULL); - - if (m_evrSink) - m_evrSink->Release(); - if (m_currentActivate) { - m_currentActivate->ShutdownObject(); - m_currentActivate->Release(); - } - m_evrSink = NULL; - m_currentActivate = NULL; -} - -IMFActivate* MFEvrVideoWindowControl::createActivate() -{ - clear(); - - if (FAILED(MFCreateVideoRendererActivate(0, &m_currentActivate))) { - qWarning() << "Failed to create evr video renderer activate!"; - return NULL; - } - if (FAILED(m_currentActivate->ActivateObject(IID_IMFMediaSink, (LPVOID*)(&m_evrSink)))) { - qWarning() << "Failed to activate evr media sink!"; - return NULL; - } - if (!setEvr(m_evrSink)) - return NULL; - - return m_currentActivate; -} - -void MFEvrVideoWindowControl::releaseActivate() -{ - clear(); -} diff --git a/src/plugins/wmf/player/mfevrvideowindowcontrol.h b/src/plugins/wmf/player/mfevrvideowindowcontrol.h deleted file mode 100644 index 96634e6d8..000000000 --- a/src/plugins/wmf/player/mfevrvideowindowcontrol.h +++ /dev/null @@ -1,63 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef MFEVRVIDEOWINDOWCONTROL_H -#define MFEVRVIDEOWINDOWCONTROL_H - -#include "evrvideowindowcontrol.h" - -QT_USE_NAMESPACE - -class MFEvrVideoWindowControl : public EvrVideoWindowControl -{ -public: - MFEvrVideoWindowControl(QObject *parent = 0); - ~MFEvrVideoWindowControl(); - - IMFActivate* createActivate(); - void releaseActivate(); - -private: - void clear(); - - IMFActivate *m_currentActivate; - IMFMediaSink *m_evrSink; -}; - -#endif // MFEVRVIDEOWINDOWCONTROL_H diff --git a/src/plugins/wmf/player/mfmetadatacontrol.cpp b/src/plugins/wmf/player/mfmetadatacontrol.cpp deleted file mode 100644 index 74063f7d1..000000000 --- a/src/plugins/wmf/player/mfmetadatacontrol.cpp +++ /dev/null @@ -1,431 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Mobility Components. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <qmediametadata.h> -#include <qdatetime.h> -#include <qimage.h> - -#include "mfmetadatacontrol.h" -#include "mfplayerservice.h" -#include "Propkey.h" - -//#define DEBUG_MEDIAFOUNDATION - -static QString nameForGUID(GUID guid) -{ - // Audio formats - if (guid == MFAudioFormat_AAC) - return QStringLiteral("MPEG AAC Audio"); - else if (guid == MFAudioFormat_ADTS) - return QStringLiteral("MPEG ADTS AAC Audio"); - else if (guid == MFAudioFormat_Dolby_AC3_SPDIF) - return QStringLiteral("Dolby AC-3 SPDIF"); - else if (guid == MFAudioFormat_DRM) - return QStringLiteral("DRM"); - else if (guid == MFAudioFormat_DTS) - return QStringLiteral("Digital Theater Systems Audio (DTS)"); - else if (guid == MFAudioFormat_Float) - return QStringLiteral("IEEE Float Audio"); - else if (guid == MFAudioFormat_MP3) - return QStringLiteral("MPEG Audio Layer-3 (MP3)"); - else if (guid == MFAudioFormat_MPEG) - return QStringLiteral("MPEG-1 Audio"); - else if (guid == MFAudioFormat_MSP1) - return QStringLiteral("Windows Media Audio Voice"); - else if (guid == MFAudioFormat_PCM) - return QStringLiteral("Uncompressed PCM Audio"); - else if (guid == MFAudioFormat_WMASPDIF) - return QStringLiteral("Windows Media Audio 9 SPDIF"); - else if (guid == MFAudioFormat_WMAudioV8) - return QStringLiteral("Windows Media Audio 8 (WMA2)"); - else if (guid == MFAudioFormat_WMAudioV9) - return QStringLiteral("Windows Media Audio 9 (WMA3"); - else if (guid == MFAudioFormat_WMAudio_Lossless) - return QStringLiteral("Windows Media Audio 9 Lossless"); - - // Video formats - if (guid == MFVideoFormat_DV25) - return QStringLiteral("DVCPRO 25 (DV25)"); - else if (guid == MFVideoFormat_DV50) - return QStringLiteral("DVCPRO 50 (DV50)"); - else if (guid == MFVideoFormat_DVC) - return QStringLiteral("DVC/DV Video"); - else if (guid == MFVideoFormat_DVH1) - return QStringLiteral("DVCPRO 100 (DVH1)"); - else if (guid == MFVideoFormat_DVHD) - return QStringLiteral("HD-DVCR (DVHD)"); - else if (guid == MFVideoFormat_DVSD) - return QStringLiteral("SDL-DVCR (DVSD)"); - else if (guid == MFVideoFormat_DVSL) - return QStringLiteral("SD-DVCR (DVSL)"); - else if (guid == MFVideoFormat_H264) - return QStringLiteral("H.264 Video"); - else if (guid == MFVideoFormat_M4S2) - return QStringLiteral("MPEG-4 part 2 Video (M4S2)"); - else if (guid == MFVideoFormat_MJPG) - return QStringLiteral("Motion JPEG (MJPG)"); - else if (guid == MFVideoFormat_MP43) - return QStringLiteral("Microsoft MPEG 4 version 3 (MP43)"); - else if (guid == MFVideoFormat_MP4S) - return QStringLiteral("ISO MPEG 4 version 1 (MP4S)"); - else if (guid == MFVideoFormat_MP4V) - return QStringLiteral("MPEG-4 part 2 Video (MP4V)"); - else if (guid == MFVideoFormat_MPEG2) - return QStringLiteral("MPEG-2 Video"); - else if (guid == MFVideoFormat_MPG1) - return QStringLiteral("MPEG-1 Video"); - else if (guid == MFVideoFormat_MSS1) - return QStringLiteral("Windows Media Screen 1 (MSS1)"); - else if (guid == MFVideoFormat_MSS2) - return QStringLiteral("Windows Media Video 9 Screen (MSS2)"); - else if (guid == MFVideoFormat_WMV1) - return QStringLiteral("Windows Media Video 7 (WMV1)"); - else if (guid == MFVideoFormat_WMV2) - return QStringLiteral("Windows Media Video 8 (WMV2)"); - else if (guid == MFVideoFormat_WMV3) - return QStringLiteral("Windows Media Video 9 (WMV3)"); - else if (guid == MFVideoFormat_WVC1) - return QStringLiteral("Windows Media Video VC1 (WVC1)"); - - else - return QStringLiteral("Unknown codec"); -} - -MFMetaDataControl::MFMetaDataControl(QObject *parent) - : QMetaDataReaderControl(parent) - , m_metaData(0) - , m_content(0) -{ -} - -MFMetaDataControl::~MFMetaDataControl() -{ - if (m_metaData) - m_metaData->Release(); - if (m_content) - m_content->Release(); -} - -bool MFMetaDataControl::isMetaDataAvailable() const -{ - return m_content || m_metaData; -} - -QVariant MFMetaDataControl::metaData(const QString &key) const -{ - QVariant value; - if (!isMetaDataAvailable()) - return value; - - int index = m_availableMetaDatas.indexOf(key); - if (index < 0) - return value; - - PROPVARIANT var; - PropVariantInit(&var); - HRESULT hr = S_FALSE; - if (m_content) - hr = m_content->GetValue(m_commonKeys[index], &var); - else if (m_metaData) - hr = m_metaData->GetProperty(reinterpret_cast<LPCWSTR>(m_commonNames[index].utf16()), &var); - - if (SUCCEEDED(hr)) { - value = convertValue(var); - - // some metadata needs to be reformatted - if (value.isValid() && m_content) { - if (key == QMediaMetaData::MediaType) { - QString v = value.toString(); - if (v == QLatin1String("{D1607DBC-E323-4BE2-86A1-48A42A28441E}")) - value = QStringLiteral("Music"); - else if (v == QLatin1String("{DB9830BD-3AB3-4FAB-8A37-1A995F7FF74B}")) - value = QStringLiteral("Video"); - else if (v == QLatin1String("{01CD0F29-DA4E-4157-897B-6275D50C4F11}")) - value = QStringLiteral("Audio"); - else if (v == QLatin1String("{FCF24A76-9A57-4036-990D-E35DD8B244E1}")) - value = QStringLiteral("Other"); - } else if (key == QMediaMetaData::Duration) { - // duration is provided in 100-nanosecond units, convert to milliseconds - value = (value.toLongLong() + 10000) / 10000; - } else if (key == QMediaMetaData::AudioCodec || key == QMediaMetaData::VideoCodec) { - GUID guid; - if (SUCCEEDED(CLSIDFromString((const WCHAR*)value.toString().utf16(), &guid))) - value = nameForGUID(guid); - } else if (key == QMediaMetaData::Resolution) { - QSize res; - res.setHeight(value.toUInt()); - if (m_content && SUCCEEDED(m_content->GetValue(PKEY_Video_FrameWidth, &var))) - res.setWidth(convertValue(var).toUInt()); - value = res; - } else if (key == QMediaMetaData::Orientation) { - uint orientation = 0; - if (m_content && SUCCEEDED(m_content->GetValue(PKEY_Video_Orientation, &var))) - orientation = convertValue(var).toUInt(); - value = orientation; - } else if (key == QMediaMetaData::PixelAspectRatio) { - QSize aspectRatio; - aspectRatio.setWidth(value.toUInt()); - if (m_content && SUCCEEDED(m_content->GetValue(PKEY_Video_VerticalAspectRatio, &var))) - aspectRatio.setHeight(convertValue(var).toUInt()); - value = aspectRatio; - } else if (key == QMediaMetaData::VideoFrameRate) { - value = value.toReal() / 1000.f; - } - } - } - - PropVariantClear(&var); - return value; -} - -QVariant MFMetaDataControl::convertValue(const PROPVARIANT& var) const -{ - QVariant value; - switch (var.vt) { - case VT_LPWSTR: - value = QString::fromUtf16(reinterpret_cast<const ushort*>(var.pwszVal)); - break; - case VT_UI4: - value = uint(var.ulVal); - break; - case VT_UI8: - value = qulonglong(var.uhVal.QuadPart); - break; - case VT_BOOL: - value = bool(var.boolVal); - break; - case VT_FILETIME: - SYSTEMTIME sysDate; - if (!FileTimeToSystemTime(&var.filetime, &sysDate)) - break; - value = QDate(sysDate.wYear, sysDate.wMonth, sysDate.wDay); - break; - case VT_STREAM: - { - STATSTG stat; - if (FAILED(var.pStream->Stat(&stat, STATFLAG_NONAME))) - break; - void *data = malloc(stat.cbSize.QuadPart); - ULONG read = 0; - if (FAILED(var.pStream->Read(data, stat.cbSize.QuadPart, &read))) { - free(data); - break; - } - value = QImage::fromData((const uchar*)data, read); - free(data); - } - break; - case VT_VECTOR | VT_LPWSTR: - QStringList vList; - for (ULONG i = 0; i < var.calpwstr.cElems; ++i) - vList.append(QString::fromUtf16(reinterpret_cast<const ushort*>(var.calpwstr.pElems[i]))); - value = vList; - break; - } - return value; -} - -QStringList MFMetaDataControl::availableMetaData() const -{ - return m_availableMetaDatas; -} - -void MFMetaDataControl::updateSource(IMFPresentationDescriptor* sourcePD, IMFMediaSource* mediaSource) -{ - if (m_metaData) { - m_metaData->Release(); - m_metaData = 0; - } - - if (m_content) { - m_content->Release(); - m_content = 0; - } - - m_availableMetaDatas.clear(); - m_commonKeys.clear(); - m_commonNames.clear(); - - if (SUCCEEDED(MFGetService(mediaSource, MF_PROPERTY_HANDLER_SERVICE, IID_PPV_ARGS(&m_content)))) { - DWORD cProps; - if (SUCCEEDED(m_content->GetCount(&cProps))) { - for (DWORD i = 0; i < cProps; i++) - { - PROPERTYKEY key; - if (FAILED(m_content->GetAt(i, &key))) - continue; - bool common = true; - if (key == PKEY_Author) { - m_availableMetaDatas.push_back(QMediaMetaData::Author); - } else if (key == PKEY_Title) { - m_availableMetaDatas.push_back(QMediaMetaData::Title); - } else if (key == PKEY_Media_SubTitle) { - m_availableMetaDatas.push_back(QMediaMetaData::SubTitle); - } else if (key == PKEY_ParentalRating) { - m_availableMetaDatas.push_back(QMediaMetaData::ParentalRating); - } else if (key == PKEY_Media_EncodingSettings) { - m_availableMetaDatas.push_back(QMediaMetaData::Description); - } else if (key == PKEY_Copyright) { - m_availableMetaDatas.push_back(QMediaMetaData::Copyright); - } else if (key == PKEY_Comment) { - m_availableMetaDatas.push_back(QMediaMetaData::Comment); - } else if (key == PKEY_Media_ProviderStyle) { - m_availableMetaDatas.push_back(QMediaMetaData::Genre); - } else if (key == PKEY_Media_Year) { - m_availableMetaDatas.push_back(QMediaMetaData::Year); - } else if (key == PKEY_Media_DateEncoded) { - m_availableMetaDatas.push_back(QMediaMetaData::Date); - } else if (key == PKEY_Rating) { - m_availableMetaDatas.push_back(QMediaMetaData::UserRating); - } else if (key == PKEY_Keywords) { - m_availableMetaDatas.push_back(QMediaMetaData::Keywords); - } else if (key == PKEY_Language) { - m_availableMetaDatas.push_back(QMediaMetaData::Language); - } else if (key == PKEY_Media_Publisher) { - m_availableMetaDatas.push_back(QMediaMetaData::Publisher); - } else if (key == PKEY_Media_ClassPrimaryID) { - m_availableMetaDatas.push_back(QMediaMetaData::MediaType); - } else if (key == PKEY_Media_Duration) { - m_availableMetaDatas.push_back(QMediaMetaData::Duration); - } else if (key == PKEY_Audio_EncodingBitrate) { - m_availableMetaDatas.push_back(QMediaMetaData::AudioBitRate); - } else if (key == PKEY_Audio_Format) { - m_availableMetaDatas.push_back(QMediaMetaData::AudioCodec); - } else if (key == PKEY_Media_AverageLevel) { - m_availableMetaDatas.push_back(QMediaMetaData::AverageLevel); - } else if (key == PKEY_Audio_ChannelCount) { - m_availableMetaDatas.push_back(QMediaMetaData::ChannelCount); - } else if (key == PKEY_Audio_PeakValue) { - m_availableMetaDatas.push_back(QMediaMetaData::PeakValue); - } else if (key == PKEY_Audio_SampleRate) { - m_availableMetaDatas.push_back(QMediaMetaData::SampleRate); - } else if (key == PKEY_Music_AlbumTitle) { - m_availableMetaDatas.push_back(QMediaMetaData::AlbumTitle); - } else if (key == PKEY_Music_AlbumArtist) { - m_availableMetaDatas.push_back(QMediaMetaData::AlbumArtist); - } else if (key == PKEY_Music_Artist) { - m_availableMetaDatas.push_back(QMediaMetaData::ContributingArtist); - } else if (key == PKEY_Music_Composer) { - m_availableMetaDatas.push_back(QMediaMetaData::Composer); - } else if (key == PKEY_Music_Conductor) { - m_availableMetaDatas.push_back(QMediaMetaData::Conductor); - } else if (key == PKEY_Music_Lyrics) { - m_availableMetaDatas.push_back(QMediaMetaData::Lyrics); - } else if (key == PKEY_Music_Mood) { - m_availableMetaDatas.push_back(QMediaMetaData::Mood); - } else if (key == PKEY_Music_TrackNumber) { - m_availableMetaDatas.push_back(QMediaMetaData::TrackNumber); - } else if (key == PKEY_Music_Genre) { - m_availableMetaDatas.push_back(QMediaMetaData::Genre); - } else if (key == PKEY_ThumbnailStream) { - m_availableMetaDatas.push_back(QMediaMetaData::ThumbnailImage); - } else if (key == PKEY_Video_FrameHeight) { - m_availableMetaDatas.push_back(QMediaMetaData::Resolution); - } else if (key == PKEY_Video_Orientation) { - m_availableMetaDatas.push_back(QMediaMetaData::Orientation); - } else if (key == PKEY_Video_HorizontalAspectRatio) { - m_availableMetaDatas.push_back(QMediaMetaData::PixelAspectRatio); - } else if (key == PKEY_Video_FrameRate) { - m_availableMetaDatas.push_back(QMediaMetaData::VideoFrameRate); - } else if (key == PKEY_Video_EncodingBitrate) { - m_availableMetaDatas.push_back(QMediaMetaData::VideoBitRate); - } else if (key == PKEY_Video_Compression) { - m_availableMetaDatas.push_back(QMediaMetaData::VideoCodec); - } else if (key == PKEY_Video_Director) { - m_availableMetaDatas.push_back(QMediaMetaData::Director); - } else if (key == PKEY_Media_Writer) { - m_availableMetaDatas.push_back(QMediaMetaData::Writer); - } else { - common = false; - //TODO: add more extended keys - } - if (common) - m_commonKeys.push_back(key); - } - } else { - m_content->Release(); - m_content = NULL; - } - } - - if (!m_content) { - //fallback to Vista approach - IMFMetadataProvider *provider = NULL; - if (SUCCEEDED(MFGetService(mediaSource, MF_METADATA_PROVIDER_SERVICE, IID_PPV_ARGS(&provider)))) { - if (SUCCEEDED(provider->GetMFMetadata(sourcePD, 0, 0, &m_metaData))) { - PROPVARIANT varNames; - PropVariantInit(&varNames); - if (SUCCEEDED(m_metaData->GetAllPropertyNames(&varNames)) && varNames.vt == (VT_VECTOR | VT_LPWSTR)) { - ULONG cElements = varNames.calpwstr.cElems; - for (ULONG i = 0; i < cElements; i++) - { - const WCHAR* sName = varNames.calpwstr.pElems[i]; -#ifdef DEBUG_MEDIAFOUNDATION - qDebug() << "metadata: " << QString::fromUtf16(sName); -#endif - if (wcscmp(sName, L"Author") == 0) { - m_availableMetaDatas.push_back(QMediaMetaData::Author); - } else if (wcscmp(sName, L"Title") == 0) { - m_availableMetaDatas.push_back(QMediaMetaData::Title); - } else if (wcscmp(sName, L"Rating") == 0) { - m_availableMetaDatas.push_back(QMediaMetaData::ParentalRating); - } else if (wcscmp(sName, L"Description") == 0) { - m_availableMetaDatas.push_back(QMediaMetaData::Description); - } else if (wcscmp(sName, L"Copyright") == 0) { - m_availableMetaDatas.push_back(QMediaMetaData::Copyright); - //TODO: add more common keys - } else { - m_availableMetaDatas.push_back(QString::fromUtf16(reinterpret_cast<const ushort*>(sName))); - } - m_commonNames.push_back(QString::fromUtf16(reinterpret_cast<const ushort*>(sName))); - } - } - PropVariantClear(&varNames); - } else { - qWarning("Failed to get IMFMetadata"); - } - provider->Release(); - } else { - qWarning("Failed to get IMFMetadataProvider from source"); - } - } - - emit metaDataChanged(); - emit metaDataAvailableChanged(m_metaData || m_content); -} diff --git a/src/plugins/wmf/player/mfmetadatacontrol.h b/src/plugins/wmf/player/mfmetadatacontrol.h deleted file mode 100644 index 7ae06cedb..000000000 --- a/src/plugins/wmf/player/mfmetadatacontrol.h +++ /dev/null @@ -1,72 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Mobility Components. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef MFMETADATACONTROL_H -#define MFMETADATACONTROL_H - -#include <qmetadatareadercontrol.h> -#include "Mfidl.h" - -QT_USE_NAMESPACE - -class MFMetaDataControl : public QMetaDataReaderControl -{ - Q_OBJECT -public: - MFMetaDataControl(QObject *parent = 0); - ~MFMetaDataControl(); - - bool isMetaDataAvailable() const; - - QVariant metaData(const QString &key) const; - QStringList availableMetaData() const; - - void updateSource(IMFPresentationDescriptor* sourcePD, IMFMediaSource* mediaSource); - -private: - QVariant convertValue(const PROPVARIANT& var) const; - IPropertyStore *m_content; //for Windows7 - IMFMetadata *m_metaData; //for Vista - - QStringList m_availableMetaDatas; - QList<PROPERTYKEY> m_commonKeys; //for Windows7 - QStringList m_commonNames; //for Vista -}; - -#endif diff --git a/src/plugins/wmf/player/mfplayercontrol.cpp b/src/plugins/wmf/player/mfplayercontrol.cpp deleted file mode 100644 index b070ce482..000000000 --- a/src/plugins/wmf/player/mfplayercontrol.cpp +++ /dev/null @@ -1,316 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Mobility Components. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "mfplayercontrol.h" -#include <qtcore/qdebug.h> - -//#define DEBUG_MEDIAFOUNDATION - -MFPlayerControl::MFPlayerControl(MFPlayerSession *session) -: QMediaPlayerControl(session) -, m_state(QMediaPlayer::StoppedState) -, m_stateDirty(false) -, m_videoAvailable(false) -, m_audioAvailable(false) -, m_duration(-1) -, m_seekable(false) -, m_session(session) -{ - QObject::connect(m_session, SIGNAL(statusChanged()), this, SLOT(handleStatusChanged())); - QObject::connect(m_session, SIGNAL(videoAvailable()), this, SLOT(handleVideoAvailable())); - QObject::connect(m_session, SIGNAL(audioAvailable()), this, SLOT(handleAudioAvailable())); - QObject::connect(m_session, SIGNAL(durationUpdate(qint64)), this, SLOT(handleDurationUpdate(qint64))); - QObject::connect(m_session, SIGNAL(seekableUpdate(bool)), this, SLOT(handleSeekableUpdate(bool))); - QObject::connect(m_session, SIGNAL(error(QMediaPlayer::Error,QString,bool)), this, SLOT(handleError(QMediaPlayer::Error,QString,bool))); - QObject::connect(m_session, SIGNAL(positionChanged(qint64)), this, SIGNAL(positionChanged(qint64))); - QObject::connect(m_session, SIGNAL(volumeChanged(int)), this, SIGNAL(volumeChanged(int))); - QObject::connect(m_session, SIGNAL(mutedChanged(bool)), this, SIGNAL(mutedChanged(bool))); - QObject::connect(m_session, SIGNAL(playbackRateChanged(qreal)), this, SIGNAL(playbackRateChanged(qreal))); - QObject::connect(m_session, SIGNAL(bufferStatusChanged(int)), this, SIGNAL(bufferStatusChanged(int))); -} - -MFPlayerControl::~MFPlayerControl() -{ -} - -void MFPlayerControl::setMedia(const QMediaContent &media, QIODevice *stream) -{ - if (m_state != QMediaPlayer::StoppedState) { - changeState(QMediaPlayer::StoppedState); - m_session->stop(true); - refreshState(); - } - - m_media = media; - m_stream = stream; - resetAudioVideoAvailable(); - handleDurationUpdate(-1); - handleSeekableUpdate(false); - m_session->load(media, stream); - emit mediaChanged(m_media); -} - -void MFPlayerControl::play() -{ - if (m_state == QMediaPlayer::PlayingState) - return; - if (QMediaPlayer::InvalidMedia == m_session->status()) - m_session->load(m_media, m_stream); - - switch (m_session->status()) { - case QMediaPlayer::UnknownMediaStatus: - case QMediaPlayer::NoMedia: - case QMediaPlayer::InvalidMedia: - return; - case QMediaPlayer::LoadedMedia: - case QMediaPlayer::BufferingMedia: - case QMediaPlayer::BufferedMedia: - case QMediaPlayer::EndOfMedia: - changeState(QMediaPlayer::PlayingState); - m_session->start(); - break; - default: //Loading/Stalled - changeState(QMediaPlayer::PlayingState); - break; - } - refreshState(); -} - -void MFPlayerControl::pause() -{ - if (m_state != QMediaPlayer::PlayingState) - return; - changeState(QMediaPlayer::PausedState); - m_session->pause(); - refreshState(); -} - -void MFPlayerControl::stop() -{ - if (m_state == QMediaPlayer::StoppedState) - return; - changeState(QMediaPlayer::StoppedState); - m_session->stop(); - refreshState(); -} - -void MFPlayerControl::changeState(QMediaPlayer::State state) -{ - if (m_state == state) - return; - m_state = state; - m_stateDirty = true; -} - -void MFPlayerControl::refreshState() -{ - if (!m_stateDirty) - return; - m_stateDirty = false; -#ifdef DEBUG_MEDIAFOUNDATION - qDebug() << "MFPlayerControl::emit stateChanged" << m_state; -#endif - emit stateChanged(m_state); -} - -void MFPlayerControl::handleStatusChanged() -{ - QMediaPlayer::MediaStatus status = m_session->status(); - switch (status) { - case QMediaPlayer::EndOfMedia: - changeState(QMediaPlayer::StoppedState); - break; - case QMediaPlayer::InvalidMedia: - break; - case QMediaPlayer::LoadedMedia: - case QMediaPlayer::BufferingMedia: - case QMediaPlayer::BufferedMedia: - if (m_state == QMediaPlayer::PlayingState) - m_session->start(); - break; - } - emit mediaStatusChanged(m_session->status()); - refreshState(); -} - -void MFPlayerControl::handleVideoAvailable() -{ - if (m_videoAvailable) - return; - m_videoAvailable = true; - emit videoAvailableChanged(m_videoAvailable); -} - -void MFPlayerControl::handleAudioAvailable() -{ - if (m_audioAvailable) - return; - m_audioAvailable = true; - emit audioAvailableChanged(m_audioAvailable); -} - -void MFPlayerControl::resetAudioVideoAvailable() -{ - bool videoDirty = false; - if (m_videoAvailable) { - m_videoAvailable = false; - videoDirty = true; - } - if (m_audioAvailable) { - m_audioAvailable = false; - emit audioAvailableChanged(m_audioAvailable); - } - if (videoDirty) - emit videoAvailableChanged(m_videoAvailable); -} - -void MFPlayerControl::handleDurationUpdate(qint64 duration) -{ - if (m_duration == duration) - return; - m_duration = duration; - emit durationChanged(m_duration); -} - -void MFPlayerControl::handleSeekableUpdate(bool seekable) -{ - if (m_seekable == seekable) - return; - m_seekable = seekable; - emit seekableChanged(m_seekable); -} - -QMediaPlayer::State MFPlayerControl::state() const -{ - return m_state; -} - -QMediaPlayer::MediaStatus MFPlayerControl::mediaStatus() const -{ - return m_session->status(); -} - -qint64 MFPlayerControl::duration() const -{ - return m_duration; -} - -qint64 MFPlayerControl::position() const -{ - return m_session->position(); -} - -void MFPlayerControl::setPosition(qint64 position) -{ - if (!m_seekable || position == m_session->position()) - return; - m_session->setPosition(position); -} - -int MFPlayerControl::volume() const -{ - return m_session->volume(); -} - -void MFPlayerControl::setVolume(int volume) -{ - m_session->setVolume(volume); -} - -bool MFPlayerControl::isMuted() const -{ - return m_session->isMuted(); -} - -void MFPlayerControl::setMuted(bool muted) -{ - m_session->setMuted(muted); -} - -int MFPlayerControl::bufferStatus() const -{ - return m_session->bufferStatus(); -} - -bool MFPlayerControl::isAudioAvailable() const -{ - return m_audioAvailable; -} - -bool MFPlayerControl::isVideoAvailable() const -{ - return m_videoAvailable; -} - -bool MFPlayerControl::isSeekable() const -{ - return m_seekable; -} - -QMediaTimeRange MFPlayerControl::availablePlaybackRanges() const -{ - return m_session->availablePlaybackRanges(); -} - -qreal MFPlayerControl::playbackRate() const -{ - return m_session->playbackRate(); -} - -void MFPlayerControl::setPlaybackRate(qreal rate) -{ - m_session->setPlaybackRate(rate); -} - -QMediaContent MFPlayerControl::media() const -{ - return m_media; -} - -const QIODevice* MFPlayerControl::mediaStream() const -{ - return m_stream; -} - -void MFPlayerControl::handleError(QMediaPlayer::Error errorCode, const QString& errorString, bool isFatal) -{ - if (isFatal) - stop(); - emit error(int(errorCode), errorString); -} diff --git a/src/plugins/wmf/player/mfplayercontrol.h b/src/plugins/wmf/player/mfplayercontrol.h deleted file mode 100644 index a75fac493..000000000 --- a/src/plugins/wmf/player/mfplayercontrol.h +++ /dev/null @@ -1,122 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Mobility Components. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef MFPLAYERCONTROL_H -#define MFPLAYERCONTROL_H - -#include "qmediacontent.h" -#include "qmediaplayercontrol.h" - -#include <QtCore/qcoreevent.h> - -#include "mfplayersession.h" - -QT_USE_NAMESPACE - -class MFPlayerControl : public QMediaPlayerControl -{ - Q_OBJECT -public: - MFPlayerControl(MFPlayerSession *session); - ~MFPlayerControl(); - - QMediaPlayer::State state() const; - - QMediaPlayer::MediaStatus mediaStatus() const; - - qint64 duration() const; - - qint64 position() const; - void setPosition(qint64 position); - - int volume() const; - void setVolume(int volume); - - bool isMuted() const; - void setMuted(bool muted); - - int bufferStatus() const; - - bool isAudioAvailable() const; - bool isVideoAvailable() const; - - bool isSeekable() const; - - QMediaTimeRange availablePlaybackRanges() const; - - qreal playbackRate() const; - void setPlaybackRate(qreal rate); - - QMediaContent media() const; - const QIODevice *mediaStream() const; - void setMedia(const QMediaContent &media, QIODevice *stream); - - void play(); - void pause(); - void stop(); - -private Q_SLOTS: - void handleStatusChanged(); - void handleVideoAvailable(); - void handleAudioAvailable(); - void handleDurationUpdate(qint64 duration); - void handleSeekableUpdate(bool seekable); - void handleError(QMediaPlayer::Error errorCode, const QString& errorString, bool isFatal); - -private: - void changeState(QMediaPlayer::State state); - void resetAudioVideoAvailable(); - void refreshState(); - - QMediaPlayer::State m_state; - bool m_stateDirty; - QMediaPlayer::MediaStatus m_status; - QMediaPlayer::Error m_error; - - bool m_videoAvailable; - bool m_audioAvailable; - qint64 m_duration; - bool m_seekable; - - QIODevice *m_stream; - QMediaContent m_media; - MFPlayerSession *m_session; -}; - -#endif diff --git a/src/plugins/wmf/player/mfplayerservice.cpp b/src/plugins/wmf/player/mfplayerservice.cpp deleted file mode 100644 index b73390ac7..000000000 --- a/src/plugins/wmf/player/mfplayerservice.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Mobility Components. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qmediacontent.h" - -#include <QtCore/qdebug.h> - -#include "mfplayercontrol.h" -#include "mfevrvideowindowcontrol.h" -#include "mfvideorenderercontrol.h" -#include "mfaudioendpointcontrol.h" -#include "mfaudioprobecontrol.h" -#include "mfvideoprobecontrol.h" -#include "mfplayerservice.h" -#include "mfplayersession.h" -#include "mfmetadatacontrol.h" - -MFPlayerService::MFPlayerService(QObject *parent) - : QMediaService(parent) - , m_session(0) - , m_videoWindowControl(0) - , m_videoRendererControl(0) -{ - m_audioEndpointControl = new MFAudioEndpointControl(this); - m_session = new MFPlayerSession(this); - m_player = new MFPlayerControl(m_session); - m_metaDataControl = new MFMetaDataControl(this); -} - -MFPlayerService::~MFPlayerService() -{ - m_session->close(); - - if (m_videoWindowControl) - delete m_videoWindowControl; - - if (m_videoRendererControl) - delete m_videoRendererControl; - - m_session->Release(); -} - -QMediaControl* MFPlayerService::requestControl(const char *name) -{ - if (qstrcmp(name, QMediaPlayerControl_iid) == 0) { - return m_player; - } else if (qstrcmp(name, QAudioOutputSelectorControl_iid) == 0) { - return m_audioEndpointControl; - } else if (qstrcmp(name, QMetaDataReaderControl_iid) == 0) { - return m_metaDataControl; - } else if (qstrcmp(name, QVideoRendererControl_iid) == 0) { - if (!m_videoRendererControl && !m_videoWindowControl) { - m_videoRendererControl = new MFVideoRendererControl; - return m_videoRendererControl; - } - } else if (qstrcmp(name, QVideoWindowControl_iid) == 0) { - if (!m_videoRendererControl && !m_videoWindowControl) { - m_videoWindowControl = new MFEvrVideoWindowControl; - return m_videoWindowControl; - } - } else if (qstrcmp(name,QMediaAudioProbeControl_iid) == 0) { - if (m_session) { - MFAudioProbeControl *probe = new MFAudioProbeControl(this); - m_session->addProbe(probe); - return probe; - } - return 0; - } else if (qstrcmp(name,QMediaVideoProbeControl_iid) == 0) { - if (m_session) { - MFVideoProbeControl *probe = new MFVideoProbeControl(this); - m_session->addProbe(probe); - return probe; - } - return 0; - } - - return 0; -} - -void MFPlayerService::releaseControl(QMediaControl *control) -{ - if (!control) { - qWarning("QMediaService::releaseControl():" - " Attempted release of null control"); - } else if (control == m_videoRendererControl) { - m_videoRendererControl->setSurface(0); - delete m_videoRendererControl; - m_videoRendererControl = 0; - return; - } else if (control == m_videoWindowControl) { - delete m_videoWindowControl; - m_videoWindowControl = 0; - return; - } - - MFAudioProbeControl* audioProbe = qobject_cast<MFAudioProbeControl*>(control); - if (audioProbe) { - if (m_session) - m_session->removeProbe(audioProbe); - delete audioProbe; - return; - } - - MFVideoProbeControl* videoProbe = qobject_cast<MFVideoProbeControl*>(control); - if (videoProbe) { - if (m_session) - m_session->removeProbe(videoProbe); - delete videoProbe; - return; - } -} - -MFAudioEndpointControl* MFPlayerService::audioEndpointControl() const -{ - return m_audioEndpointControl; -} - -MFVideoRendererControl* MFPlayerService::videoRendererControl() const -{ - return m_videoRendererControl; -} - -MFEvrVideoWindowControl* MFPlayerService::videoWindowControl() const -{ - return m_videoWindowControl; -} - -MFMetaDataControl* MFPlayerService::metaDataControl() const -{ - return m_metaDataControl; -} diff --git a/src/plugins/wmf/player/mfplayerservice.h b/src/plugins/wmf/player/mfplayerservice.h deleted file mode 100644 index 78423c0b1..000000000 --- a/src/plugins/wmf/player/mfplayerservice.h +++ /dev/null @@ -1,87 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Mobility Components. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef MFPLAYERSERVICE_H -#define MFPLAYERSERVICE_H - -#include <mfapi.h> -#include <mfidl.h> - -#include "qmediaplayer.h" -#include "qmediaservice.h" -#include "qmediatimerange.h" - -QT_BEGIN_NAMESPACE -class QMediaContent; -QT_END_NAMESPACE - -QT_USE_NAMESPACE - -class MFEvrVideoWindowControl; -class MFAudioEndpointControl; -class MFVideoRendererControl; -class MFPlayerControl; -class MFMetaDataControl; -class MFPlayerSession; - -class MFPlayerService : public QMediaService -{ - Q_OBJECT -public: - MFPlayerService(QObject *parent = 0); - ~MFPlayerService(); - - QMediaControl* requestControl(const char *name); - void releaseControl(QMediaControl *control); - - MFAudioEndpointControl* audioEndpointControl() const; - MFVideoRendererControl* videoRendererControl() const; - MFEvrVideoWindowControl* videoWindowControl() const; - MFMetaDataControl* metaDataControl() const; - -private: - MFPlayerSession *m_session; - MFVideoRendererControl *m_videoRendererControl; - MFAudioEndpointControl *m_audioEndpointControl; - MFEvrVideoWindowControl *m_videoWindowControl; - MFPlayerControl *m_player; - MFMetaDataControl *m_metaDataControl; -}; - -#endif diff --git a/src/plugins/wmf/player/mfplayersession.cpp b/src/plugins/wmf/player/mfplayersession.cpp deleted file mode 100644 index 1d145edc4..000000000 --- a/src/plugins/wmf/player/mfplayersession.cpp +++ /dev/null @@ -1,1818 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Mobility Components. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qmediacontent.h" -#include "qmediaplayercontrol.h" - -#include <QtCore/qcoreapplication.h> -#include <QtCore/qdatetime.h> -#include <QtCore/qthread.h> -#include <QtCore/qvarlengtharray.h> -#include <QtCore/qdebug.h> -#include <QtCore/qfile.h> -#include <QtCore/qbuffer.h> - -#include "mfplayercontrol.h" -#include "mfevrvideowindowcontrol.h" -#include "mfvideorenderercontrol.h" -#include "mfaudioendpointcontrol.h" - -#include "mfplayersession.h" -#include "mfplayerservice.h" -#include "mfmetadatacontrol.h" -#include <mferror.h> -#include <nserror.h> -#include "sourceresolver.h" -#include "samplegrabber.h" -#include "mftvideo.h" -#include <wmcodecdsp.h> - -//#define DEBUG_MEDIAFOUNDATION - -MFPlayerSession::MFPlayerSession(MFPlayerService *playerService) - : m_playerService(playerService) - , m_cRef(1) - , m_session(0) - , m_presentationClock(0) - , m_rateControl(0) - , m_rateSupport(0) - , m_volumeControl(0) - , m_netsourceStatistics(0) - , m_duration(0) - , m_sourceResolver(0) - , m_hCloseEvent(0) - , m_closing(false) - , m_pendingRate(1) - , m_volume(100) - , m_muted(false) - , m_status(QMediaPlayer::NoMedia) - , m_scrubbing(false) - , m_restoreRate(1) - , m_mediaTypes(0) - , m_audioSampleGrabber(0) - , m_audioSampleGrabberNode(0) - , m_videoProbeMFT(0) -{ - QObject::connect(this, SIGNAL(sessionEvent(IMFMediaEvent*)), this, SLOT(handleSessionEvent(IMFMediaEvent*))); - - m_pendingState = NoPending; - ZeroMemory(&m_state, sizeof(m_state)); - m_state.command = CmdStop; - m_state.prevCmd = CmdNone; - m_state.rate = 1.0f; - ZeroMemory(&m_request, sizeof(m_request)); - m_request.command = CmdNone; - m_request.prevCmd = CmdNone; - m_request.rate = 1.0f; - - m_audioSampleGrabber = new AudioSampleGrabberCallback; -} - -void MFPlayerSession::close() -{ -#ifdef DEBUG_MEDIAFOUNDATION - qDebug() << "close"; -#endif - - clear(); - if (!m_session) - return; - - HRESULT hr = S_OK; - if (m_session) { - m_closing = true; - hr = m_session->Close(); - if (SUCCEEDED(hr)) { - DWORD dwWaitResult = WaitForSingleObject(m_hCloseEvent, 100); - if (dwWaitResult == WAIT_TIMEOUT) { - qWarning() << "session close time out!"; - } - } - m_closing = false; - } - - if (SUCCEEDED(hr)) { - if (m_session) - m_session->Shutdown(); - if (m_sourceResolver) - m_sourceResolver->shutdown(); - } - if (m_sourceResolver) { - m_sourceResolver->Release(); - m_sourceResolver = 0; - } - if (m_videoProbeMFT) { - m_videoProbeMFT->Release(); - m_videoProbeMFT = 0; - } - - if (m_playerService->videoRendererControl()) { - m_playerService->videoRendererControl()->releaseActivate(); - } else if (m_playerService->videoWindowControl()) { - m_playerService->videoWindowControl()->releaseActivate(); - } - - if (m_session) - m_session->Release(); - m_session = 0; - if (m_hCloseEvent) - CloseHandle(m_hCloseEvent); - m_hCloseEvent = 0; -} - -void MFPlayerSession::addProbe(MFAudioProbeControl *probe) -{ - m_audioSampleGrabber->addProbe(probe); -} - -void MFPlayerSession::removeProbe(MFAudioProbeControl *probe) -{ - m_audioSampleGrabber->removeProbe(probe); -} - -void MFPlayerSession::addProbe(MFVideoProbeControl* probe) -{ - if (m_videoProbes.contains(probe)) - return; - - m_videoProbes.append(probe); - - if (m_videoProbeMFT) - m_videoProbeMFT->addProbe(probe); -} - -void MFPlayerSession::removeProbe(MFVideoProbeControl* probe) -{ - m_videoProbes.removeOne(probe); - - if (m_videoProbeMFT) - m_videoProbeMFT->removeProbe(probe); -} - -MFPlayerSession::~MFPlayerSession() -{ - m_audioSampleGrabber->Release(); -} - - -void MFPlayerSession::load(const QMediaContent &media, QIODevice *stream) -{ -#ifdef DEBUG_MEDIAFOUNDATION - qDebug() << "load"; -#endif - clear(); - QUrl url = media.request().url(); - - if (m_status == QMediaPlayer::LoadingMedia && m_sourceResolver) - m_sourceResolver->cancel(); - - if (url.isEmpty() && !stream) { - changeStatus(QMediaPlayer::NoMedia); - } else if (stream && (!stream->isReadable())) { - changeStatus(QMediaPlayer::InvalidMedia); - emit error(QMediaPlayer::ResourceError, tr("Invalid stream source."), true); - } else { - createSession(); - changeStatus(QMediaPlayer::LoadingMedia); - m_sourceResolver->load(url, stream); - } - emit positionChanged(position()); -} - -void MFPlayerSession::handleSourceError(long hr) -{ - QString errorString; - QMediaPlayer::Error errorCode = QMediaPlayer::ResourceError; - switch (hr) { - case QMediaPlayer::FormatError: - errorCode = QMediaPlayer::FormatError; - errorString = tr("Attempting to play invalid Qt resource."); - break; - case NS_E_FILE_NOT_FOUND: - errorString = tr("The system cannot find the file specified."); - break; - case NS_E_SERVER_NOT_FOUND: - errorString = tr("The specified server could not be found."); - break; - case MF_E_UNSUPPORTED_BYTESTREAM_TYPE: - errorCode = QMediaPlayer::FormatError; - errorString = tr("Unsupported media type."); - break; - default: - errorString = tr("Failed to load source."); - break; - } - changeStatus(QMediaPlayer::InvalidMedia); - emit error(errorCode, errorString, true); -} - -void MFPlayerSession::handleMediaSourceReady() -{ - if (QMediaPlayer::LoadingMedia != m_status || !m_sourceResolver || m_sourceResolver != sender()) - return; -#ifdef DEBUG_MEDIAFOUNDATION - qDebug() << "handleMediaSourceReady"; -#endif - HRESULT hr = S_OK; - IMFMediaSource* mediaSource = m_sourceResolver->mediaSource(); - - DWORD dwCharacteristics = 0; - mediaSource->GetCharacteristics(&dwCharacteristics); - emit seekableUpdate(MFMEDIASOURCE_CAN_SEEK & dwCharacteristics); - - IMFPresentationDescriptor* sourcePD; - hr = mediaSource->CreatePresentationDescriptor(&sourcePD); - if (SUCCEEDED(hr)) { - m_duration = 0; - m_playerService->metaDataControl()->updateSource(sourcePD, mediaSource); - sourcePD->GetUINT64(MF_PD_DURATION, &m_duration); - //convert from 100 nanosecond to milisecond - emit durationUpdate(qint64(m_duration / 10000)); - setupPlaybackTopology(mediaSource, sourcePD); - sourcePD->Release(); - } else { - changeStatus(QMediaPlayer::InvalidMedia); - emit error(QMediaPlayer::ResourceError, tr("Cannot create presentation descriptor."), true); - } -} - -MFPlayerSession::MediaType MFPlayerSession::getStreamType(IMFStreamDescriptor *stream) const -{ - if (!stream) - return Unknown; - - struct SafeRelease { - IMFMediaTypeHandler *ptr = nullptr; - ~SafeRelease() { if (ptr) ptr->Release(); } - } typeHandler; - if (SUCCEEDED(stream->GetMediaTypeHandler(&typeHandler.ptr))) { - GUID guidMajorType; - if (SUCCEEDED(typeHandler.ptr->GetMajorType(&guidMajorType))) { - if (guidMajorType == MFMediaType_Audio) - return Audio; - else if (guidMajorType == MFMediaType_Video) - return Video; - } - } - - return Unknown; -} - -void MFPlayerSession::setupPlaybackTopology(IMFMediaSource *source, IMFPresentationDescriptor *sourcePD) -{ - HRESULT hr = S_OK; - // Get the number of streams in the media source. - DWORD cSourceStreams = 0; - hr = sourcePD->GetStreamDescriptorCount(&cSourceStreams); - if (FAILED(hr)) { - changeStatus(QMediaPlayer::UnknownMediaStatus); - emit error(QMediaPlayer::ResourceError, tr("Failed to get stream count."), true); - return; - } - - IMFTopology *topology; - hr = MFCreateTopology(&topology); - if (FAILED(hr)) { - changeStatus(QMediaPlayer::UnknownMediaStatus); - emit error(QMediaPlayer::ResourceError, tr("Failed to create topology."), true); - return; - } - - // Remember output node id for a first video stream - TOPOID outputNodeId = -1; - - // For each stream, create the topology nodes and add them to the topology. - DWORD succeededCount = 0; - for (DWORD i = 0; i < cSourceStreams; i++) - { - BOOL fSelected = FALSE; - bool streamAdded = false; - IMFStreamDescriptor *streamDesc = NULL; - - HRESULT hr = sourcePD->GetStreamDescriptorByIndex(i, &fSelected, &streamDesc); - if (SUCCEEDED(hr)) { - // The media might have multiple audio and video streams, - // only use one of each kind, and only if it is selected by default. - MediaType mediaType = getStreamType(streamDesc); - if (mediaType != Unknown - && ((m_mediaTypes & mediaType) == 0) // Check if this type isn't already added - && fSelected) { - - IMFTopologyNode *sourceNode = addSourceNode(topology, source, sourcePD, streamDesc); - if (sourceNode) { - IMFTopologyNode *outputNode = addOutputNode(mediaType, topology, 0); - if (outputNode) { - bool connected = false; - if (mediaType == Audio) { - if (!m_audioSampleGrabberNode) - connected = setupAudioSampleGrabber(topology, sourceNode, outputNode); - } else if (mediaType == Video && outputNodeId == -1) { - // Remember video output node ID. - outputNode->GetTopoNodeID(&outputNodeId); - } - - if (!connected) - hr = sourceNode->ConnectOutput(0, outputNode, 0); - - if (FAILED(hr)) { - emit error(QMediaPlayer::FormatError, tr("Unable to play any stream."), false); - } else { - streamAdded = true; - succeededCount++; - m_mediaTypes |= mediaType; - switch (mediaType) { - case Audio: - emit audioAvailable(); - break; - case Video: - emit videoAvailable(); - break; - } - } - outputNode->Release(); - } - sourceNode->Release(); - } - } - - if (fSelected && !streamAdded) - sourcePD->DeselectStream(i); - - streamDesc->Release(); - } - } - - if (succeededCount == 0) { - changeStatus(QMediaPlayer::InvalidMedia); - emit error(QMediaPlayer::ResourceError, tr("Unable to play."), true); - } else { - if (outputNodeId != -1) { - topology = insertMFT(topology, outputNodeId); - } - - hr = m_session->SetTopology(MFSESSION_SETTOPOLOGY_IMMEDIATE, topology); - if (FAILED(hr)) { - changeStatus(QMediaPlayer::UnknownMediaStatus); - emit error(QMediaPlayer::ResourceError, tr("Failed to set topology."), true); - } - } - topology->Release(); -} - -IMFTopologyNode* MFPlayerSession::addSourceNode(IMFTopology* topology, IMFMediaSource* source, - IMFPresentationDescriptor* presentationDesc, IMFStreamDescriptor *streamDesc) -{ - IMFTopologyNode *node = NULL; - HRESULT hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node); - if (SUCCEEDED(hr)) { - hr = node->SetUnknown(MF_TOPONODE_SOURCE, source); - if (SUCCEEDED(hr)) { - hr = node->SetUnknown(MF_TOPONODE_PRESENTATION_DESCRIPTOR, presentationDesc); - if (SUCCEEDED(hr)) { - hr = node->SetUnknown(MF_TOPONODE_STREAM_DESCRIPTOR, streamDesc); - if (SUCCEEDED(hr)) { - hr = topology->AddNode(node); - if (SUCCEEDED(hr)) - return node; - } - } - } - node->Release(); - } - return NULL; -} - -IMFTopologyNode* MFPlayerSession::addOutputNode(MediaType mediaType, IMFTopology* topology, DWORD sinkID) -{ - IMFTopologyNode *node = NULL; - if (FAILED(MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node))) - return NULL; - - IMFActivate *activate = NULL; - if (mediaType == Audio) { - activate = m_playerService->audioEndpointControl()->createActivate(); - } else if (mediaType == Video) { - if (m_playerService->videoRendererControl()) { - activate = m_playerService->videoRendererControl()->createActivate(); - } else if (m_playerService->videoWindowControl()) { - activate = m_playerService->videoWindowControl()->createActivate(); - } else { - qWarning() << "no videoWindowControl or videoRendererControl, unable to add output node for video data"; - } - } else { - // Unknown stream type. - emit error(QMediaPlayer::FormatError, tr("Unknown stream type."), false); - } - - if (!activate - || FAILED(node->SetObject(activate)) - || FAILED(node->SetUINT32(MF_TOPONODE_STREAMID, sinkID)) - || FAILED(node->SetUINT32(MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, FALSE)) - || FAILED(topology->AddNode(node))) { - node->Release(); - node = NULL; - } - - return node; -} - -bool MFPlayerSession::addAudioSampleGrabberNode(IMFTopology *topology) -{ - HRESULT hr = S_OK; - IMFMediaType *pType = 0; - IMFActivate *sinkActivate = 0; - do { - hr = MFCreateMediaType(&pType); - if (FAILED(hr)) - break; - - hr = pType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio); - if (FAILED(hr)) - break; - - hr = pType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM); - if (FAILED(hr)) - break; - - hr = MFCreateSampleGrabberSinkActivate(pType, m_audioSampleGrabber, &sinkActivate); - if (FAILED(hr)) - break; - - // Note: Data is distorted if this attribute is enabled - hr = sinkActivate->SetUINT32(MF_SAMPLEGRABBERSINK_IGNORE_CLOCK, FALSE); - if (FAILED(hr)) - break; - - hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &m_audioSampleGrabberNode); - if (FAILED(hr)) - break; - - hr = m_audioSampleGrabberNode->SetObject(sinkActivate); - if (FAILED(hr)) - break; - - hr = m_audioSampleGrabberNode->SetUINT32(MF_TOPONODE_STREAMID, 0); // Identifier of the stream sink. - if (FAILED(hr)) - break; - - hr = m_audioSampleGrabberNode->SetUINT32(MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, FALSE); - if (FAILED(hr)) - break; - - hr = topology->AddNode(m_audioSampleGrabberNode); - if (FAILED(hr)) - break; - - pType->Release(); - sinkActivate->Release(); - return true; - } while (false); - - if (pType) - pType->Release(); - if (sinkActivate) - sinkActivate->Release(); - if (m_audioSampleGrabberNode) { - m_audioSampleGrabberNode->Release(); - m_audioSampleGrabberNode = NULL; - } - return false; -} - -bool MFPlayerSession::setupAudioSampleGrabber(IMFTopology *topology, IMFTopologyNode *sourceNode, IMFTopologyNode *outputNode) -{ - if (!addAudioSampleGrabberNode(topology)) - return false; - - HRESULT hr = S_OK; - IMFTopologyNode *pTeeNode = NULL; - - IMFMediaTypeHandler *typeHandler = NULL; - IMFMediaType *mediaType = NULL; - do { - hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &pTeeNode); - if (FAILED(hr)) - break; - hr = sourceNode->ConnectOutput(0, pTeeNode, 0); - if (FAILED(hr)) - break; - hr = pTeeNode->ConnectOutput(0, outputNode, 0); - if (FAILED(hr)) - break; - hr = pTeeNode->ConnectOutput(1, m_audioSampleGrabberNode, 0); - if (FAILED(hr)) - break; - } while (false); - - if (pTeeNode) - pTeeNode->Release(); - if (mediaType) - mediaType->Release(); - if (typeHandler) - typeHandler->Release(); - return hr == S_OK; -} - -QAudioFormat MFPlayerSession::audioFormatForMFMediaType(IMFMediaType *mediaType) const -{ - WAVEFORMATEX *wfx = 0; - UINT32 size; - HRESULT hr = MFCreateWaveFormatExFromMFMediaType(mediaType, &wfx, &size, MFWaveFormatExConvertFlag_Normal); - if (FAILED(hr)) - return QAudioFormat(); - - if (size < sizeof(WAVEFORMATEX)) { - CoTaskMemFree(wfx); - return QAudioFormat(); - } - - if (wfx->wFormatTag != WAVE_FORMAT_PCM) { - CoTaskMemFree(wfx); - return QAudioFormat(); - } - - QAudioFormat format; - format.setSampleRate(wfx->nSamplesPerSec); - format.setChannelCount(wfx->nChannels); - format.setSampleSize(wfx->wBitsPerSample); - format.setCodec("audio/pcm"); - format.setByteOrder(QAudioFormat::LittleEndian); - if (format.sampleSize() == 8) - format.setSampleType(QAudioFormat::UnSignedInt); - else - format.setSampleType(QAudioFormat::SignedInt); - - CoTaskMemFree(wfx); - return format; -} - -// BindOutputNode -// Sets the IMFStreamSink pointer on an output node. -// IMFActivate pointer in the output node must be converted to an -// IMFStreamSink pointer before the topology loader resolves the topology. -HRESULT BindOutputNode(IMFTopologyNode *pNode) -{ - IUnknown *nodeObject = NULL; - IMFActivate *activate = NULL; - IMFStreamSink *stream = NULL; - IMFMediaSink *sink = NULL; - - HRESULT hr = pNode->GetObject(&nodeObject); - if (FAILED(hr)) - return hr; - - hr = nodeObject->QueryInterface(IID_PPV_ARGS(&activate)); - if (SUCCEEDED(hr)) { - DWORD dwStreamID = 0; - - // Try to create the media sink. - hr = activate->ActivateObject(IID_PPV_ARGS(&sink)); - if (SUCCEEDED(hr)) - dwStreamID = MFGetAttributeUINT32(pNode, MF_TOPONODE_STREAMID, 0); - - if (SUCCEEDED(hr)) { - // First check if the media sink already has a stream sink with the requested ID. - hr = sink->GetStreamSinkById(dwStreamID, &stream); - if (FAILED(hr)) { - // Create the stream sink. - hr = sink->AddStreamSink(dwStreamID, NULL, &stream); - } - } - - // Replace the node's object pointer with the stream sink. - if (SUCCEEDED(hr)) { - hr = pNode->SetObject(stream); - } - } else { - hr = nodeObject->QueryInterface(IID_PPV_ARGS(&stream)); - } - - if (nodeObject) - nodeObject->Release(); - if (activate) - activate->Release(); - if (stream) - stream->Release(); - if (sink) - sink->Release(); - return hr; -} - -// BindOutputNodes -// Sets the IMFStreamSink pointers on all of the output nodes in a topology. -HRESULT BindOutputNodes(IMFTopology *pTopology) -{ - IMFCollection *collection; - - // Get the collection of output nodes. - HRESULT hr = pTopology->GetOutputNodeCollection(&collection); - - // Enumerate all of the nodes in the collection. - if (SUCCEEDED(hr)) { - DWORD cNodes; - hr = collection->GetElementCount(&cNodes); - - if (SUCCEEDED(hr)) { - for (DWORD i = 0; i < cNodes; i++) { - IUnknown *element; - hr = collection->GetElement(i, &element); - if (FAILED(hr)) - break; - - IMFTopologyNode *node; - hr = element->QueryInterface(IID_IMFTopologyNode, (void**)&node); - element->Release(); - if (FAILED(hr)) - break; - - // Bind this node. - hr = BindOutputNode(node); - node->Release(); - if (FAILED(hr)) - break; - } - } - collection->Release(); - } - - return hr; -} - -// This method binds output nodes to complete the topology, -// then loads the topology and inserts MFT between the output node -// and a filter connected to the output node. -IMFTopology *MFPlayerSession::insertMFT(IMFTopology *topology, TOPOID outputNodeId) -{ - bool isNewTopology = false; - - IMFTopoLoader *topoLoader = 0; - IMFTopology *resolvedTopology = 0; - IMFCollection *outputNodes = 0; - - do { - if (FAILED(BindOutputNodes(topology))) - break; - - if (FAILED(MFCreateTopoLoader(&topoLoader))) - break; - - if (FAILED(topoLoader->Load(topology, &resolvedTopology, NULL))) { - // Topology could not be resolved, adding ourselves a color converter - // to the topology might solve the problem - insertColorConverter(topology, outputNodeId); - if (FAILED(topoLoader->Load(topology, &resolvedTopology, NULL))) - break; - } - - if (insertResizer(resolvedTopology)) - isNewTopology = true; - - // Get all output nodes and search for video output node. - if (FAILED(resolvedTopology->GetOutputNodeCollection(&outputNodes))) - break; - - DWORD elementCount = 0; - if (FAILED(outputNodes->GetElementCount(&elementCount))) - break; - - for (DWORD n = 0; n < elementCount; n++) { - IUnknown *element = 0; - IMFTopologyNode *node = 0; - IUnknown *outputObject = 0; - IMFTopologyNode *inputNode = 0; - IMFTopologyNode *mftNode = 0; - bool mftAdded = false; - - do { - if (FAILED(outputNodes->GetElement(n, &element))) - break; - - if (FAILED(element->QueryInterface(IID_IMFTopologyNode, (void**)&node))) - break; - - TOPOID id; - if (FAILED(node->GetTopoNodeID(&id))) - break; - - if (id != outputNodeId) - break; - - if (FAILED(node->GetObject(&outputObject))) - break; - - m_videoProbeMFT->setVideoSink(outputObject); - - // Insert MFT between the output node and the node connected to it. - DWORD outputIndex = 0; - if (FAILED(node->GetInput(0, &inputNode, &outputIndex))) - break; - - if (FAILED(MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &mftNode))) - break; - - if (FAILED(mftNode->SetObject(m_videoProbeMFT))) - break; - - if (FAILED(resolvedTopology->AddNode(mftNode))) - break; - - if (FAILED(inputNode->ConnectOutput(0, mftNode, 0))) - break; - - if (FAILED(mftNode->ConnectOutput(0, node, 0))) - break; - - mftAdded = true; - isNewTopology = true; - } while (false); - - if (mftNode) - mftNode->Release(); - if (inputNode) - inputNode->Release(); - if (node) - node->Release(); - if (element) - element->Release(); - if (outputObject) - outputObject->Release(); - - if (mftAdded) - break; - else - m_videoProbeMFT->setVideoSink(NULL); - } - } while (false); - - if (outputNodes) - outputNodes->Release(); - - if (topoLoader) - topoLoader->Release(); - - if (isNewTopology) { - topology->Release(); - return resolvedTopology; - } - - if (resolvedTopology) - resolvedTopology->Release(); - - return topology; -} - -// This method checks if the topology contains a color converter transform (CColorConvertDMO), -// if it does it inserts a resizer transform (CResizerDMO) to handle dynamic frame size change -// of the video stream. -// Returns true if it inserted a resizer -bool MFPlayerSession::insertResizer(IMFTopology *topology) -{ - bool inserted = false; - WORD elementCount = 0; - IMFTopologyNode *node = 0; - IUnknown *object = 0; - IWMColorConvProps *colorConv = 0; - IMFTransform *resizer = 0; - IMFTopologyNode *resizerNode = 0; - IMFTopologyNode *inputNode = 0; - - HRESULT hr = topology->GetNodeCount(&elementCount); - if (FAILED(hr)) - return false; - - for (WORD i = 0; i < elementCount; ++i) { - if (node) { - node->Release(); - node = 0; - } - if (object) { - object->Release(); - object = 0; - } - - if (FAILED(topology->GetNode(i, &node))) - break; - - MF_TOPOLOGY_TYPE nodeType; - if (FAILED(node->GetNodeType(&nodeType))) - break; - - if (nodeType != MF_TOPOLOGY_TRANSFORM_NODE) - continue; - - if (FAILED(node->GetObject(&object))) - break; - - if (FAILED(object->QueryInterface(&colorConv))) - continue; - - if (FAILED(CoCreateInstance(CLSID_CResizerDMO, NULL, CLSCTX_INPROC_SERVER, IID_IMFTransform, (void**)&resizer))) - break; - - if (FAILED(MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &resizerNode))) - break; - - if (FAILED(resizerNode->SetObject(resizer))) - break; - - if (FAILED(topology->AddNode(resizerNode))) - break; - - DWORD outputIndex = 0; - if (FAILED(node->GetInput(0, &inputNode, &outputIndex))) { - topology->RemoveNode(resizerNode); - break; - } - - if (FAILED(inputNode->ConnectOutput(0, resizerNode, 0))) { - topology->RemoveNode(resizerNode); - break; - } - - if (FAILED(resizerNode->ConnectOutput(0, node, 0))) { - inputNode->ConnectOutput(0, node, 0); - topology->RemoveNode(resizerNode); - break; - } - - inserted = true; - break; - } - - if (node) - node->Release(); - if (object) - object->Release(); - if (colorConv) - colorConv->Release(); - if (resizer) - resizer->Release(); - if (resizerNode) - resizerNode->Release(); - if (inputNode) - inputNode->Release(); - - return inserted; -} - -// This method inserts a color converter (CColorConvertDMO) in the topology, -// typically to convert to RGB format. -// Usually this converter is automatically inserted when the topology is resolved but -// for some reason it fails to do so in some cases, we then do it ourselves. -void MFPlayerSession::insertColorConverter(IMFTopology *topology, TOPOID outputNodeId) -{ - IMFCollection *outputNodes = 0; - - if (FAILED(topology->GetOutputNodeCollection(&outputNodes))) - return; - - DWORD elementCount = 0; - if (FAILED(outputNodes->GetElementCount(&elementCount))) - goto done; - - for (DWORD n = 0; n < elementCount; n++) { - IUnknown *element = 0; - IMFTopologyNode *node = 0; - IMFTopologyNode *inputNode = 0; - IMFTopologyNode *mftNode = 0; - IMFTransform *converter = 0; - - do { - if (FAILED(outputNodes->GetElement(n, &element))) - break; - - if (FAILED(element->QueryInterface(IID_IMFTopologyNode, (void**)&node))) - break; - - TOPOID id; - if (FAILED(node->GetTopoNodeID(&id))) - break; - - if (id != outputNodeId) - break; - - DWORD outputIndex = 0; - if (FAILED(node->GetInput(0, &inputNode, &outputIndex))) - break; - - if (FAILED(MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &mftNode))) - break; - - if (FAILED(CoCreateInstance(CLSID_CColorConvertDMO, NULL, CLSCTX_INPROC_SERVER, IID_IMFTransform, (void**)&converter))) - break; - - if (FAILED(mftNode->SetObject(converter))) - break; - - if (FAILED(topology->AddNode(mftNode))) - break; - - if (FAILED(inputNode->ConnectOutput(0, mftNode, 0))) - break; - - if (FAILED(mftNode->ConnectOutput(0, node, 0))) - break; - - } while (false); - - if (mftNode) - mftNode->Release(); - if (inputNode) - inputNode->Release(); - if (node) - node->Release(); - if (element) - element->Release(); - if (converter) - converter->Release(); - } - -done: - if (outputNodes) - outputNodes->Release(); -} - -void MFPlayerSession::stop(bool immediate) -{ -#ifdef DEBUG_MEDIAFOUNDATION - qDebug() << "stop"; -#endif - if (!immediate && m_pendingState != NoPending) { - m_request.setCommand(CmdStop); - } else { - if (m_state.command == CmdStop) - return; - - if (m_scrubbing) - scrub(false); - - if (SUCCEEDED(m_session->Stop())) { - m_state.setCommand(CmdStop); - m_pendingState = CmdPending; - if (m_status != QMediaPlayer::EndOfMedia) { - m_varStart.vt = VT_I8; - m_varStart.hVal.QuadPart = 0; - } - } else { - emit error(QMediaPlayer::ResourceError, tr("Failed to stop."), true); - } - } -} - -void MFPlayerSession::start() -{ - if (m_status == QMediaPlayer::EndOfMedia) - m_varStart.hVal.QuadPart = 0; // restart from the beginning - -#ifdef DEBUG_MEDIAFOUNDATION - qDebug() << "start"; -#endif - - if (m_pendingState != NoPending) { - m_request.setCommand(CmdStart); - } else { - if (m_state.command == CmdStart) - return; - - if (m_scrubbing) - scrub(false); - - if (SUCCEEDED(m_session->Start(&GUID_NULL, &m_varStart))) { - m_state.setCommand(CmdStart); - m_pendingState = CmdPending; - PropVariantInit(&m_varStart); - } else { - emit error(QMediaPlayer::ResourceError, tr("failed to start playback"), true); - } - } -} - -void MFPlayerSession::pause() -{ -#ifdef DEBUG_MEDIAFOUNDATION - qDebug() << "pause"; -#endif - if (m_pendingState != NoPending) { - m_request.setCommand(CmdPause); - } else { - if (m_state.command == CmdPause) - return; - - if (SUCCEEDED(m_session->Pause())) { - m_state.setCommand(CmdPause); - m_pendingState = CmdPending; - } else { - emit error(QMediaPlayer::ResourceError, tr("Failed to pause."), false); - } - } -} - -void MFPlayerSession::changeStatus(QMediaPlayer::MediaStatus newStatus) -{ - if (m_status == newStatus) - return; -#ifdef DEBUG_MEDIAFOUNDATION - qDebug() << "MFPlayerSession::changeStatus" << newStatus; -#endif - m_status = newStatus; - emit statusChanged(); -} - -QMediaPlayer::MediaStatus MFPlayerSession::status() const -{ - return m_status; -} - -void MFPlayerSession::createSession() -{ - close(); - - m_hCloseEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - - m_sourceResolver = new SourceResolver(); - QObject::connect(m_sourceResolver, SIGNAL(mediaSourceReady()), this, SLOT(handleMediaSourceReady())); - QObject::connect(m_sourceResolver, SIGNAL(error(long)), this, SLOT(handleSourceError(long))); - - m_videoProbeMFT = new MFTransform; - for (int i = 0; i < m_videoProbes.size(); ++i) - m_videoProbeMFT->addProbe(m_videoProbes.at(i)); - - Q_ASSERT(m_session == NULL); - HRESULT hr = MFCreateMediaSession(NULL, &m_session); - if (FAILED(hr)) { - changeStatus(QMediaPlayer::UnknownMediaStatus); - emit error(QMediaPlayer::ResourceError, tr("Unable to create mediasession."), true); - } - - hr = m_session->BeginGetEvent(this, m_session); - - if (FAILED(hr)) { - changeStatus(QMediaPlayer::UnknownMediaStatus); - emit error(QMediaPlayer::ResourceError, tr("Unable to pull session events."), false); - } - - PropVariantInit(&m_varStart); - m_varStart.vt = VT_I8; - m_varStart.hVal.QuadPart = 0; -} - -qint64 MFPlayerSession::position() -{ - if (m_request.command == CmdSeek || m_request.command == CmdSeekResume) - return m_request.start; - - if (m_pendingState == SeekPending) - return m_state.start; - - if (m_state.command == CmdStop) - return qint64(m_varStart.hVal.QuadPart / 10000); - - if (m_presentationClock) { - MFTIME time, sysTime; - if (FAILED(m_presentationClock->GetCorrelatedTime(0, &time, &sysTime))) - return 0; - return qint64(time / 10000); - } - return 0; -} - -void MFPlayerSession::setPosition(qint64 position) -{ -#ifdef DEBUG_MEDIAFOUNDATION - qDebug() << "setPosition"; -#endif - if (m_pendingState != NoPending) { - m_request.setCommand(CmdSeek); - m_request.start = position; - } else { - setPositionInternal(position, CmdNone); - } -} - -void MFPlayerSession::setPositionInternal(qint64 position, Command requestCmd) -{ - if (m_status == QMediaPlayer::EndOfMedia) - changeStatus(QMediaPlayer::LoadedMedia); - if (m_state.command == CmdStop && requestCmd != CmdSeekResume) { - m_varStart.vt = VT_I8; - m_varStart.hVal.QuadPart = LONGLONG(position * 10000); - // Even though the position is not actually set on the session yet, - // report it to have changed anyway for UI controls to be updated - emit positionChanged(this->position()); - return; - } - - if (m_state.command == CmdPause) - scrub(true); - -#ifdef DEBUG_MEDIAFOUNDATION - qDebug() << "setPositionInternal"; -#endif - - PROPVARIANT varStart; - varStart.vt = VT_I8; - varStart.hVal.QuadPart = LONGLONG(position * 10000); - if (SUCCEEDED(m_session->Start(NULL, &varStart))) - { - PropVariantInit(&m_varStart); - // Store the pending state. - m_state.setCommand(CmdStart); - m_state.start = position; - m_pendingState = SeekPending; - } else { - emit error(QMediaPlayer::ResourceError, tr("Failed to seek."), true); - } -} - -qreal MFPlayerSession::playbackRate() const -{ - if (m_scrubbing) - return m_restoreRate; - return m_state.rate; -} - -void MFPlayerSession::setPlaybackRate(qreal rate) -{ - if (m_scrubbing) { - m_restoreRate = rate; - emit playbackRateChanged(rate); - return; - } - setPlaybackRateInternal(rate); -} - -void MFPlayerSession::setPlaybackRateInternal(qreal rate) -{ - if (rate == m_request.rate) - return; - - m_pendingRate = rate; - if (!m_rateSupport) - return; - -#ifdef DEBUG_MEDIAFOUNDATION - qDebug() << "setPlaybackRate"; -#endif - BOOL isThin = FALSE; - - //from MSDN http://msdn.microsoft.com/en-us/library/aa965220%28v=vs.85%29.aspx - //Thinning applies primarily to video streams. - //In thinned mode, the source drops delta frames and deliver only key frames. - //At very high playback rates, the source might skip some key frames (for example, deliver every other key frame). - - if (FAILED(m_rateSupport->IsRateSupported(FALSE, rate, NULL))) { - isThin = TRUE; - if (FAILED(m_rateSupport->IsRateSupported(isThin, rate, NULL))) { - qWarning() << "unable to set playbackrate = " << rate; - m_pendingRate = m_request.rate = m_state.rate; - return; - } - } - if (m_pendingState != NoPending) { - m_request.rate = rate; - m_request.isThin = isThin; - // Remember the current transport state (play, paused, etc), so that we - // can restore it after the rate change, if necessary. However, if - // anothercommand is already pending, that one takes precedent. - if (m_request.command == CmdNone) - m_request.setCommand(m_state.command); - } else { - //No pending operation. Commit the new rate. - commitRateChange(rate, isThin); - } -} - -void MFPlayerSession::commitRateChange(qreal rate, BOOL isThin) -{ -#ifdef DEBUG_MEDIAFOUNDATION - qDebug() << "commitRateChange"; -#endif - Q_ASSERT(m_pendingState == NoPending); - MFTIME hnsSystemTime = 0; - MFTIME hnsClockTime = 0; - Command cmdNow = m_state.command; - bool resetPosition = false; - // Allowed rate transitions: - // Positive <-> negative: Stopped - // Negative <-> zero: Stopped - // Postive <-> zero: Paused or stopped - if ((rate > 0 && m_state.rate <= 0) || (rate < 0 && m_state.rate >= 0)) { - if (cmdNow == CmdStart) { - // Get the current clock position. This will be the restart time. - m_presentationClock->GetCorrelatedTime(0, &hnsClockTime, &hnsSystemTime); - Q_ASSERT(hnsSystemTime != 0); - - if (rate < 0 || m_state.rate < 0) - m_request.setCommand(CmdSeekResume); - else if (isThin || m_state.isThin) - m_request.setCommand(CmdStartAndSeek); - else - m_request.setCommand(CmdStart); - - // We need to stop only when dealing with negative rates - if (rate >= 0 && m_state.rate >= 0) - pause(); - else - stop(); - - // If we deal with negative rates, we stopped the session and consequently - // reset the position to zero. We then need to resume to the current position. - m_request.start = hnsClockTime / 10000; - } else if (cmdNow == CmdPause) { - if (rate < 0 || m_state.rate < 0) { - // The current state is paused. - // For this rate change, the session must be stopped. However, the - // session cannot transition back from stopped to paused. - // Therefore, this rate transition is not supported while paused. - qWarning() << "Unable to change rate from positive to negative or vice versa in paused state"; - rate = m_state.rate; - isThin = m_state.isThin; - goto done; - } - - // This happens when resuming playback after scrubbing in pause mode. - // This transition requires the session to be paused. Even though our - // internal state is set to paused, the session might not be so we need - // to enforce it - if (rate > 0 && m_state.rate == 0) { - m_state.setCommand(CmdNone); - pause(); - } - } - } else if (rate == 0 && m_state.rate > 0) { - if (cmdNow != CmdPause) { - // Transition to paused. - // This transisition requires the paused state. - // Pause and set the rate. - pause(); - - // Request: Switch back to current state. - m_request.setCommand(cmdNow); - } - } else if (rate == 0 && m_state.rate < 0) { - // Changing rate from negative to zero requires to stop the session - m_presentationClock->GetCorrelatedTime(0, &hnsClockTime, &hnsSystemTime); - - m_request.setCommand(CmdSeekResume); - - stop(); - - // Resume to the current position (stop() will reset the position to 0) - m_request.start = hnsClockTime / 10000; - } else if (!isThin && m_state.isThin) { - if (cmdNow == CmdStart) { - // When thinning, only key frames are read and presented. Going back - // to normal playback requires to reset the current position to force - // the pipeline to decode the actual frame at the current position - // (which might be earlier than the last decoded key frame) - resetPosition = true; - } else if (cmdNow == CmdPause) { - // If paused, don't reset the position until we resume, otherwise - // a new frame will be rendered - m_presentationClock->GetCorrelatedTime(0, &hnsClockTime, &hnsSystemTime); - m_request.setCommand(CmdSeekResume); - m_request.start = hnsClockTime / 10000; - } - - } - - // Set the rate. - if (FAILED(m_rateControl->SetRate(isThin, rate))) { - qWarning() << "failed to set playbackrate = " << rate; - rate = m_state.rate; - isThin = m_state.isThin; - goto done; - } - - if (resetPosition) { - m_presentationClock->GetCorrelatedTime(0, &hnsClockTime, &hnsSystemTime); - setPosition(hnsClockTime / 10000); - } - -done: - // Adjust our current rate and requested rate. - m_pendingRate = m_request.rate = m_state.rate = rate; - if (rate != 0) - m_state.isThin = isThin; - emit playbackRateChanged(rate); -} - -void MFPlayerSession::scrub(bool enableScrub) -{ - if (m_scrubbing == enableScrub) - return; - - m_scrubbing = enableScrub; - - if (!canScrub()) { - if (!enableScrub) - m_pendingRate = m_restoreRate; - return; - } - - if (enableScrub) { - // Enter scrubbing mode. Cache the rate. - m_restoreRate = m_request.rate; - setPlaybackRateInternal(0.0f); - } else { - // Leaving scrubbing mode. Restore the old rate. - setPlaybackRateInternal(m_restoreRate); - } -} - -int MFPlayerSession::volume() const -{ - return m_volume; -} - -void MFPlayerSession::setVolume(int volume) -{ - if (m_volume == volume) - return; - m_volume = volume; - - if (!m_muted) - setVolumeInternal(volume); - - emit volumeChanged(m_volume); -} - -bool MFPlayerSession::isMuted() const -{ - return m_muted; -} - -void MFPlayerSession::setMuted(bool muted) -{ - if (m_muted == muted) - return; - m_muted = muted; - - setVolumeInternal(muted ? 0 : m_volume); - - emit mutedChanged(m_muted); -} - -void MFPlayerSession::setVolumeInternal(int volume) -{ - if (m_volumeControl) { - quint32 channelCount = 0; - if (!SUCCEEDED(m_volumeControl->GetChannelCount(&channelCount)) - || channelCount == 0) - return; - - float scaled = volume * 0.01f; - for (quint32 i = 0; i < channelCount; ++i) - m_volumeControl->SetChannelVolume(i, scaled); - } -} - -int MFPlayerSession::bufferStatus() -{ - if (!m_netsourceStatistics) - return 0; - PROPVARIANT var; - PropVariantInit(&var); - PROPERTYKEY key; - key.fmtid = MFNETSOURCE_STATISTICS; - key.pid = MFNETSOURCE_BUFFERPROGRESS_ID; - int progress = -1; - // GetValue returns S_FALSE if the property is not available, which has - // a value > 0. We therefore can't use the SUCCEEDED macro here. - if (m_netsourceStatistics->GetValue(key, &var) == S_OK) { - progress = var.lVal; - PropVariantClear(&var); - } - -#ifdef DEBUG_MEDIAFOUNDATION - qDebug() << "bufferStatus: progress = " << progress; -#endif - - return progress; -} - -QMediaTimeRange MFPlayerSession::availablePlaybackRanges() -{ - // defaults to the whole media - qint64 start = 0; - qint64 end = qint64(m_duration / 10000); - - if (m_netsourceStatistics) { - PROPVARIANT var; - PropVariantInit(&var); - PROPERTYKEY key; - key.fmtid = MFNETSOURCE_STATISTICS; - key.pid = MFNETSOURCE_SEEKRANGESTART_ID; - // GetValue returns S_FALSE if the property is not available, which has - // a value > 0. We therefore can't use the SUCCEEDED macro here. - if (m_netsourceStatistics->GetValue(key, &var) == S_OK) { - start = qint64(var.uhVal.QuadPart / 10000); - PropVariantClear(&var); - PropVariantInit(&var); - key.pid = MFNETSOURCE_SEEKRANGEEND_ID; - if (m_netsourceStatistics->GetValue(key, &var) == S_OK) { - end = qint64(var.uhVal.QuadPart / 10000); - PropVariantClear(&var); - } - } - } - - return QMediaTimeRange(start, end); -} - -HRESULT MFPlayerSession::QueryInterface(REFIID riid, void** ppvObject) -{ - if (!ppvObject) - return E_POINTER; - if (riid == IID_IMFAsyncCallback) { - *ppvObject = static_cast<IMFAsyncCallback*>(this); - } else if (riid == IID_IUnknown) { - *ppvObject = static_cast<IUnknown*>(this); - } else { - *ppvObject = NULL; - return E_NOINTERFACE; - } - return S_OK; -} - -ULONG MFPlayerSession::AddRef(void) -{ - return InterlockedIncrement(&m_cRef); -} - -ULONG MFPlayerSession::Release(void) -{ - LONG cRef = InterlockedDecrement(&m_cRef); - if (cRef == 0) - this->deleteLater(); - return cRef; -} - -HRESULT MFPlayerSession::Invoke(IMFAsyncResult *pResult) -{ - if (pResult->GetStateNoAddRef() != m_session) - return S_OK; - - IMFMediaEvent *pEvent = NULL; - // Get the event from the event queue. - HRESULT hr = m_session->EndGetEvent(pResult, &pEvent); - if (FAILED(hr)) { - return S_OK; - } - - MediaEventType meType = MEUnknown; - hr = pEvent->GetType(&meType); - if (FAILED(hr)) { - pEvent->Release(); - return S_OK; - } - - if (meType == MESessionClosed) { - SetEvent(m_hCloseEvent); - pEvent->Release(); - return S_OK; - } else { - hr = m_session->BeginGetEvent(this, m_session); - if (FAILED(hr)) { - pEvent->Release(); - return S_OK; - } - } - - if (!m_closing) { - emit sessionEvent(pEvent); - } else { - pEvent->Release(); - } - return S_OK; -} - -void MFPlayerSession::handleSessionEvent(IMFMediaEvent *sessionEvent) -{ - HRESULT hrStatus = S_OK; - HRESULT hr = sessionEvent->GetStatus(&hrStatus); - if (FAILED(hr) || !m_session) { - sessionEvent->Release(); - return; - } - - MediaEventType meType = MEUnknown; - hr = sessionEvent->GetType(&meType); - -#ifdef DEBUG_MEDIAFOUNDATION - if (FAILED(hrStatus)) - qDebug() << "handleSessionEvent: MediaEventType = " << meType << "Failed"; - else - qDebug() << "handleSessionEvent: MediaEventType = " << meType; -#endif - - switch (meType) { - case MENonFatalError: { - PROPVARIANT var; - PropVariantInit(&var); - sessionEvent->GetValue(&var); - qWarning() << "handleSessionEvent: non fatal error = " << var.ulVal; - PropVariantClear(&var); - emit error(QMediaPlayer::ResourceError, tr("Media session non-fatal error."), false); - } - break; - case MESourceUnknown: - changeStatus(QMediaPlayer::InvalidMedia); - break; - case MEError: - changeStatus(QMediaPlayer::UnknownMediaStatus); - qWarning() << "handleSessionEvent: serious error = " << hrStatus; - emit error(QMediaPlayer::ResourceError, tr("Media session serious error."), true); - break; - case MESessionRateChanged: - // If the rate change succeeded, we've already got the rate - // cached. If it failed, try to get the actual rate. - if (FAILED(hrStatus)) { - PROPVARIANT var; - PropVariantInit(&var); - if (SUCCEEDED(sessionEvent->GetValue(&var)) && (var.vt == VT_R4)) { - m_state.rate = var.fltVal; - } - emit playbackRateChanged(playbackRate()); - } - break; - case MESessionScrubSampleComplete : - if (m_scrubbing) - updatePendingCommands(CmdStart); - break; - case MESessionStarted: - if (m_status == QMediaPlayer::EndOfMedia - || m_status == QMediaPlayer::LoadedMedia) { - // If the session started, then enough data is buffered to play - changeStatus(QMediaPlayer::BufferedMedia); - } - - updatePendingCommands(CmdStart); - // playback started, we can now set again the procAmpValues if they have been - // changed previously (these are lost when loading a new media) - if (m_playerService->videoWindowControl()) { - m_playerService->videoWindowControl()->applyImageControls(); - } - break; - case MESessionStopped: - if (m_status != QMediaPlayer::EndOfMedia) { - m_varStart.vt = VT_I8; - m_varStart.hVal.QuadPart = 0; - - // Reset to Loaded status unless we are loading a new media - // or changing the playback rate to negative values (stop required) - if (m_status != QMediaPlayer::LoadingMedia && m_request.command != CmdSeekResume) - changeStatus(QMediaPlayer::LoadedMedia); - } - updatePendingCommands(CmdStop); - break; - case MESessionPaused: - updatePendingCommands(CmdPause); - break; - case MEReconnectStart: -#ifdef DEBUG_MEDIAFOUNDATION - qDebug() << "MEReconnectStart" << ((hrStatus == S_OK) ? "OK" : "Failed"); -#endif - break; - case MEReconnectEnd: -#ifdef DEBUG_MEDIAFOUNDATION - qDebug() << "MEReconnectEnd" << ((hrStatus == S_OK) ? "OK" : "Failed"); -#endif - break; - case MESessionTopologySet: - if (FAILED(hrStatus)) { - changeStatus(QMediaPlayer::InvalidMedia); - emit error(QMediaPlayer::FormatError, tr("Unsupported media, a codec is missing."), true); - } else { - if (m_audioSampleGrabberNode) { - IUnknown *obj = 0; - if (SUCCEEDED(m_audioSampleGrabberNode->GetObject(&obj))) { - IMFStreamSink *streamSink = 0; - if (SUCCEEDED(obj->QueryInterface(IID_PPV_ARGS(&streamSink)))) { - IMFMediaTypeHandler *typeHandler = 0; - if (SUCCEEDED(streamSink->GetMediaTypeHandler((&typeHandler)))) { - IMFMediaType *mediaType = 0; - if (SUCCEEDED(typeHandler->GetCurrentMediaType(&mediaType))) { - m_audioSampleGrabber->setFormat(audioFormatForMFMediaType(mediaType)); - mediaType->Release(); - } - typeHandler->Release(); - } - streamSink->Release(); - } - obj->Release(); - } - } - - // Topology is resolved and successfuly set, this happens only after loading a new media. - // Make sure we always start the media from the beginning - m_varStart.vt = VT_I8; - m_varStart.hVal.QuadPart = 0; - - changeStatus(QMediaPlayer::LoadedMedia); - } - break; - } - - if (FAILED(hrStatus)) { - sessionEvent->Release(); - return; - } - - switch (meType) { - case MEBufferingStarted: - changeStatus(QMediaPlayer::StalledMedia); - emit bufferStatusChanged(bufferStatus()); - break; - case MEBufferingStopped: - changeStatus(QMediaPlayer::BufferedMedia); - emit bufferStatusChanged(bufferStatus()); - break; - case MESessionEnded: - m_pendingState = NoPending; - m_state.command = CmdStop; - m_state.prevCmd = CmdNone; - m_request.command = CmdNone; - m_request.prevCmd = CmdNone; - - m_varStart.vt = VT_I8; - //keep reporting the final position after end of media - m_varStart.hVal.QuadPart = m_duration; - emit positionChanged(position()); - - changeStatus(QMediaPlayer::EndOfMedia); - break; - case MEEndOfPresentationSegment: - break; - case MESessionTopologyStatus: { - UINT32 status; - if (SUCCEEDED(sessionEvent->GetUINT32(MF_EVENT_TOPOLOGY_STATUS, &status))) { - if (status == MF_TOPOSTATUS_READY) { - IMFClock* clock; - if (SUCCEEDED(m_session->GetClock(&clock))) { - clock->QueryInterface(IID_IMFPresentationClock, (void**)(&m_presentationClock)); - clock->Release(); - } - - if (SUCCEEDED(MFGetService(m_session, MF_RATE_CONTROL_SERVICE, IID_PPV_ARGS(&m_rateControl)))) { - if (SUCCEEDED(MFGetService(m_session, MF_RATE_CONTROL_SERVICE, IID_PPV_ARGS(&m_rateSupport)))) { - if ((m_mediaTypes & Video) == Video - && SUCCEEDED(m_rateSupport->IsRateSupported(TRUE, 0, NULL))) - m_canScrub = true; - } - BOOL isThin = FALSE; - float rate = 1; - if (SUCCEEDED(m_rateControl->GetRate(&isThin, &rate))) { - if (m_pendingRate != rate) { - m_state.rate = m_request.rate = rate; - setPlaybackRate(m_pendingRate); - } - } - } - MFGetService(m_session, MFNETSOURCE_STATISTICS_SERVICE, IID_PPV_ARGS(&m_netsourceStatistics)); - - if (SUCCEEDED(MFGetService(m_session, MR_STREAM_VOLUME_SERVICE, IID_PPV_ARGS(&m_volumeControl)))) - setVolumeInternal(m_muted ? 0 : m_volume); - } - } - } - break; - default: - break; - } - - sessionEvent->Release(); -} - -void MFPlayerSession::updatePendingCommands(Command command) -{ - emit positionChanged(position()); - if (m_state.command != command || m_pendingState == NoPending) - return; - - // Seek while paused completed - if (m_pendingState == SeekPending && m_state.prevCmd == CmdPause) { - m_pendingState = NoPending; - // A seek operation actually restarts playback. If scrubbing is possible, playback rate - // is set to 0.0 at this point and we just need to reset the current state to Pause. - // If scrubbing is not possible, the playback rate was not changed and we explicitly need - // to re-pause playback. - if (!canScrub()) - pause(); - else - m_state.setCommand(CmdPause); - } - - m_pendingState = NoPending; - - //First look for rate changes. - if (m_request.rate != m_state.rate) { - commitRateChange(m_request.rate, m_request.isThin); - } - - // Now look for new requests. - if (m_pendingState == NoPending) { - switch (m_request.command) { - case CmdStart: - start(); - break; - case CmdPause: - pause(); - break; - case CmdStop: - stop(); - break; - case CmdSeek: - case CmdSeekResume: - setPositionInternal(m_request.start, m_request.command); - break; - case CmdStartAndSeek: - start(); - setPositionInternal(m_request.start, m_request.command); - break; - } - m_request.setCommand(CmdNone); - } - -} - -bool MFPlayerSession::canScrub() const -{ - return m_canScrub && m_rateSupport && m_rateControl; -} - -void MFPlayerSession::clear() -{ -#ifdef DEBUG_MEDIAFOUNDATION - qDebug() << "MFPlayerSession::clear"; -#endif - m_mediaTypes = 0; - m_canScrub = false; - - m_pendingState = NoPending; - m_state.command = CmdStop; - m_state.prevCmd = CmdNone; - m_request.command = CmdNone; - m_request.prevCmd = CmdNone; - - if (m_presentationClock) { - m_presentationClock->Release(); - m_presentationClock = NULL; - } - if (m_rateControl) { - m_rateControl->Release(); - m_rateControl = NULL; - } - if (m_rateSupport) { - m_rateSupport->Release(); - m_rateSupport = NULL; - } - if (m_volumeControl) { - m_volumeControl->Release(); - m_volumeControl = NULL; - } - if (m_netsourceStatistics) { - m_netsourceStatistics->Release(); - m_netsourceStatistics = NULL; - } - if (m_audioSampleGrabberNode) { - m_audioSampleGrabberNode->Release(); - m_audioSampleGrabberNode = NULL; - } -} diff --git a/src/plugins/wmf/player/mfplayersession.h b/src/plugins/wmf/player/mfplayersession.h deleted file mode 100644 index c6ffba91f..000000000 --- a/src/plugins/wmf/player/mfplayersession.h +++ /dev/null @@ -1,239 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Mobility Components. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef MFPLAYERSESSION_H -#define MFPLAYERSESSION_H - -#include <mfapi.h> -#include <mfidl.h> - -#include "qmediaplayer.h" -#include "qmediaservice.h" -#include "qmediatimerange.h" - -#include <QtCore/qcoreevent.h> -#include <QtCore/qmutex.h> -#include <QtCore/qurl.h> -#include <QtCore/qwaitcondition.h> -#include <QtMultimedia/qaudioformat.h> -#include <QtMultimedia/qvideosurfaceformat.h> - -QT_BEGIN_NAMESPACE -class QMediaContent; -QT_END_NAMESPACE - -QT_USE_NAMESPACE - -class SourceResolver; -class MFAudioEndpointControl; -class MFVideoRendererControl; -class MFPlayerControl; -class MFMetaDataControl; -class MFPlayerService; -class AudioSampleGrabberCallback; -class MFTransform; -class MFAudioProbeControl; -class MFVideoProbeControl; - -class MFPlayerSession : public QObject, public IMFAsyncCallback -{ - Q_OBJECT - friend class SourceResolver; -public: - MFPlayerSession(MFPlayerService *playerService = 0); - ~MFPlayerSession(); - - STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppvObject); - - STDMETHODIMP_(ULONG) AddRef(void); - - STDMETHODIMP_(ULONG) Release(void); - - STDMETHODIMP Invoke(IMFAsyncResult *pResult); - - STDMETHODIMP GetParameters(DWORD *pdwFlags, DWORD *pdwQueue) - { - Q_UNUSED(pdwFlags); - Q_UNUSED(pdwQueue); - return E_NOTIMPL; - } - - void load(const QMediaContent &media, QIODevice *stream); - void stop(bool immediate = false); - void start(); - void pause(); - - QMediaPlayer::MediaStatus status() const; - qint64 position(); - void setPosition(qint64 position); - qreal playbackRate() const; - void setPlaybackRate(qreal rate); - int volume() const; - void setVolume(int volume); - bool isMuted() const; - void setMuted(bool muted); - int bufferStatus(); - QMediaTimeRange availablePlaybackRanges(); - - void changeStatus(QMediaPlayer::MediaStatus newStatus); - - void close(); - - void addProbe(MFAudioProbeControl* probe); - void removeProbe(MFAudioProbeControl* probe); - void addProbe(MFVideoProbeControl* probe); - void removeProbe(MFVideoProbeControl* probe); - -Q_SIGNALS: - void error(QMediaPlayer::Error error, QString errorString, bool isFatal); - void sessionEvent(IMFMediaEvent *sessionEvent); - void statusChanged(); - void audioAvailable(); - void videoAvailable(); - void durationUpdate(qint64 duration); - void seekableUpdate(bool seekable); - void positionChanged(qint64 position); - void playbackRateChanged(qreal rate); - void volumeChanged(int volume); - void mutedChanged(bool muted); - void bufferStatusChanged(int percentFilled); - -private Q_SLOTS: - void handleMediaSourceReady(); - void handleSessionEvent(IMFMediaEvent *sessionEvent); - void handleSourceError(long hr); - -private: - long m_cRef; - MFPlayerService *m_playerService; - IMFMediaSession *m_session; - IMFPresentationClock *m_presentationClock; - IMFRateControl *m_rateControl; - IMFRateSupport *m_rateSupport; - IMFAudioStreamVolume *m_volumeControl; - IPropertyStore *m_netsourceStatistics; - PROPVARIANT m_varStart; - UINT64 m_duration; - - enum Command - { - CmdNone = 0, - CmdStop, - CmdStart, - CmdPause, - CmdSeek, - CmdSeekResume, - CmdStartAndSeek - }; - - void clear(); - void setPositionInternal(qint64 position, Command requestCmd); - void setPlaybackRateInternal(qreal rate); - void commitRateChange(qreal rate, BOOL isThin); - bool canScrub() const; - void scrub(bool enableScrub); - bool m_scrubbing; - float m_restoreRate; - - SourceResolver *m_sourceResolver; - HANDLE m_hCloseEvent; - bool m_closing; - - enum MediaType - { - Unknown = 0, - Audio = 1, - Video = 2, - }; - DWORD m_mediaTypes; - - enum PendingState - { - NoPending = 0, - CmdPending, - SeekPending, - }; - - struct SeekState - { - void setCommand(Command cmd) { - prevCmd = command; - command = cmd; - } - Command command; - Command prevCmd; - float rate; // Playback rate - BOOL isThin; // Thinned playback? - qint64 start; // Start position - }; - SeekState m_state; // Current nominal state. - SeekState m_request; // Pending request. - PendingState m_pendingState; - float m_pendingRate; - void updatePendingCommands(Command command); - - QMediaPlayer::MediaStatus m_status; - bool m_canScrub; - int m_volume; - bool m_muted; - - void setVolumeInternal(int volume); - - void createSession(); - void setupPlaybackTopology(IMFMediaSource *source, IMFPresentationDescriptor *sourcePD); - MediaType getStreamType(IMFStreamDescriptor *stream) const; - IMFTopologyNode* addSourceNode(IMFTopology* topology, IMFMediaSource* source, - IMFPresentationDescriptor* presentationDesc, IMFStreamDescriptor *streamDesc); - IMFTopologyNode* addOutputNode(MediaType mediaType, IMFTopology* topology, DWORD sinkID); - - bool addAudioSampleGrabberNode(IMFTopology* topology); - bool setupAudioSampleGrabber(IMFTopology *topology, IMFTopologyNode *sourceNode, IMFTopologyNode *outputNode); - QAudioFormat audioFormatForMFMediaType(IMFMediaType *mediaType) const; - AudioSampleGrabberCallback *m_audioSampleGrabber; - IMFTopologyNode *m_audioSampleGrabberNode; - - IMFTopology *insertMFT(IMFTopology *topology, TOPOID outputNodeId); - bool insertResizer(IMFTopology *topology); - void insertColorConverter(IMFTopology *topology, TOPOID outputNodeId); - MFTransform *m_videoProbeMFT; - QList<MFVideoProbeControl*> m_videoProbes; -}; - - -#endif diff --git a/src/plugins/wmf/player/mftvideo.cpp b/src/plugins/wmf/player/mftvideo.cpp deleted file mode 100644 index 9dce654f2..000000000 --- a/src/plugins/wmf/player/mftvideo.cpp +++ /dev/null @@ -1,753 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "mftvideo.h" -#include "mfvideoprobecontrol.h" -#include <private/qmemoryvideobuffer_p.h> -#include <mferror.h> -#include <strmif.h> -#include <uuids.h> -#include <InitGuid.h> -#include <d3d9.h> -#include <qdebug.h> - -// This MFT sends all samples it processes to connected video probes. -// Sample is sent to probes in ProcessInput. -// In ProcessOutput this MFT simply returns the original sample. - -// The implementation is based on a boilerplate from the MF SDK example. - -MFTransform::MFTransform(): - m_cRef(1), - m_inputType(0), - m_outputType(0), - m_sample(0), - m_videoSinkTypeHandler(0), - m_bytesPerLine(0) -{ -} - -MFTransform::~MFTransform() -{ - if (m_inputType) - m_inputType->Release(); - - if (m_outputType) - m_outputType->Release(); - - if (m_videoSinkTypeHandler) - m_videoSinkTypeHandler->Release(); -} - -void MFTransform::addProbe(MFVideoProbeControl *probe) -{ - QMutexLocker locker(&m_videoProbeMutex); - - if (m_videoProbes.contains(probe)) - return; - - m_videoProbes.append(probe); -} - -void MFTransform::removeProbe(MFVideoProbeControl *probe) -{ - QMutexLocker locker(&m_videoProbeMutex); - m_videoProbes.removeOne(probe); -} - -void MFTransform::setVideoSink(IUnknown *videoSink) -{ - // This transform supports the same input types as the video sink. - // Store its type handler interface in order to report the correct supported types. - - if (m_videoSinkTypeHandler) { - m_videoSinkTypeHandler->Release(); - m_videoSinkTypeHandler = NULL; - } - - if (videoSink) - videoSink->QueryInterface(IID_PPV_ARGS(&m_videoSinkTypeHandler)); -} - -STDMETHODIMP MFTransform::QueryInterface(REFIID riid, void** ppv) -{ - if (!ppv) - return E_POINTER; - if (riid == IID_IMFTransform) { - *ppv = static_cast<IMFTransform*>(this); - } else if (riid == IID_IUnknown) { - *ppv = static_cast<IUnknown*>(this); - } else { - *ppv = NULL; - return E_NOINTERFACE; - } - AddRef(); - return S_OK; -} - -STDMETHODIMP_(ULONG) MFTransform::AddRef() -{ - return InterlockedIncrement(&m_cRef); -} - -STDMETHODIMP_(ULONG) MFTransform::Release() -{ - ULONG cRef = InterlockedDecrement(&m_cRef); - if (cRef == 0) { - delete this; - } - return cRef; -} - -STDMETHODIMP MFTransform::GetStreamLimits(DWORD *pdwInputMinimum, DWORD *pdwInputMaximum, DWORD *pdwOutputMinimum, DWORD *pdwOutputMaximum) -{ - if (!pdwInputMinimum || !pdwInputMaximum || !pdwOutputMinimum || !pdwOutputMaximum) - return E_POINTER; - *pdwInputMinimum = 1; - *pdwInputMaximum = 1; - *pdwOutputMinimum = 1; - *pdwOutputMaximum = 1; - return S_OK; -} - -STDMETHODIMP MFTransform::GetStreamCount(DWORD *pcInputStreams, DWORD *pcOutputStreams) -{ - if (!pcInputStreams || !pcOutputStreams) - return E_POINTER; - - *pcInputStreams = 1; - *pcOutputStreams = 1; - return S_OK; -} - -STDMETHODIMP MFTransform::GetStreamIDs(DWORD dwInputIDArraySize, DWORD *pdwInputIDs, DWORD dwOutputIDArraySize, DWORD *pdwOutputIDs) -{ - // streams are numbered consecutively - Q_UNUSED(dwInputIDArraySize); - Q_UNUSED(pdwInputIDs); - Q_UNUSED(dwOutputIDArraySize); - Q_UNUSED(pdwOutputIDs); - return E_NOTIMPL; -} - -STDMETHODIMP MFTransform::GetInputStreamInfo(DWORD dwInputStreamID, MFT_INPUT_STREAM_INFO *pStreamInfo) -{ - QMutexLocker locker(&m_mutex); - - if (dwInputStreamID > 0) - return MF_E_INVALIDSTREAMNUMBER; - - if (!pStreamInfo) - return E_POINTER; - - pStreamInfo->cbSize = 0; - pStreamInfo->hnsMaxLatency = 0; - pStreamInfo->cbMaxLookahead = 0; - pStreamInfo->cbAlignment = 0; - pStreamInfo->dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES - | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER - | MFT_INPUT_STREAM_PROCESSES_IN_PLACE; - - return S_OK; -} - -STDMETHODIMP MFTransform::GetOutputStreamInfo(DWORD dwOutputStreamID, MFT_OUTPUT_STREAM_INFO *pStreamInfo) -{ - QMutexLocker locker(&m_mutex); - - if (dwOutputStreamID > 0) - return MF_E_INVALIDSTREAMNUMBER; - - if (!pStreamInfo) - return E_POINTER; - - pStreamInfo->cbSize = 0; - pStreamInfo->cbAlignment = 0; - pStreamInfo->dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES - | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER - | MFT_OUTPUT_STREAM_PROVIDES_SAMPLES - | MFT_OUTPUT_STREAM_DISCARDABLE; - - return S_OK; -} - -STDMETHODIMP MFTransform::GetAttributes(IMFAttributes **pAttributes) -{ - // This MFT does not support attributes. - Q_UNUSED(pAttributes); - return E_NOTIMPL; -} - -STDMETHODIMP MFTransform::GetInputStreamAttributes(DWORD dwInputStreamID, IMFAttributes **pAttributes) -{ - // This MFT does not support input stream attributes. - Q_UNUSED(dwInputStreamID); - Q_UNUSED(pAttributes); - return E_NOTIMPL; -} - -STDMETHODIMP MFTransform::GetOutputStreamAttributes(DWORD dwOutputStreamID, IMFAttributes **pAttributes) -{ - // This MFT does not support output stream attributes. - Q_UNUSED(dwOutputStreamID); - Q_UNUSED(pAttributes); - return E_NOTIMPL; -} - -STDMETHODIMP MFTransform::DeleteInputStream(DWORD dwStreamID) -{ - // This MFT has a fixed number of input streams. - Q_UNUSED(dwStreamID); - return E_NOTIMPL; -} - -STDMETHODIMP MFTransform::AddInputStreams(DWORD cStreams, DWORD *adwStreamIDs) -{ - // This MFT has a fixed number of input streams. - Q_UNUSED(cStreams); - Q_UNUSED(adwStreamIDs); - return E_NOTIMPL; -} - -STDMETHODIMP MFTransform::GetInputAvailableType(DWORD dwInputStreamID, DWORD dwTypeIndex, IMFMediaType **ppType) -{ - // We support the same input types as the video sink - if (!m_videoSinkTypeHandler) - return E_NOTIMPL; - - if (dwInputStreamID > 0) - return MF_E_INVALIDSTREAMNUMBER; - - if (!ppType) - return E_POINTER; - - return m_videoSinkTypeHandler->GetMediaTypeByIndex(dwTypeIndex, ppType); -} - -STDMETHODIMP MFTransform::GetOutputAvailableType(DWORD dwOutputStreamID, DWORD dwTypeIndex, IMFMediaType **ppType) -{ - // Since we don't modify the samples, the output type must be the same as the input type. - // Report our input type as the only available output type. - - if (dwOutputStreamID > 0) - return MF_E_INVALIDSTREAMNUMBER; - - if (!ppType) - return E_POINTER; - - // Input type must be set first - if (!m_inputType) - return MF_E_TRANSFORM_TYPE_NOT_SET; - - if (dwTypeIndex > 0) - return MF_E_NO_MORE_TYPES; - - // Return a copy to make sure our type is not modified - if (FAILED(MFCreateMediaType(ppType))) - return E_OUTOFMEMORY; - - return m_inputType->CopyAllItems(*ppType); -} - -STDMETHODIMP MFTransform::SetInputType(DWORD dwInputStreamID, IMFMediaType *pType, DWORD dwFlags) -{ - if (dwInputStreamID > 0) - return MF_E_INVALIDSTREAMNUMBER; - - QMutexLocker locker(&m_mutex); - - if (m_sample) - return MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING; - - if (!isMediaTypeSupported(pType)) - return MF_E_INVALIDMEDIATYPE; - - if (dwFlags == MFT_SET_TYPE_TEST_ONLY) - return pType ? S_OK : E_POINTER; - - if (m_inputType) { - m_inputType->Release(); - // Input type has changed, discard output type (if it's set) so it's reset later on - DWORD flags = 0; - if (m_outputType && m_outputType->IsEqual(pType, &flags) != S_OK) { - m_outputType->Release(); - m_outputType = 0; - } - } - - m_inputType = pType; - - if (m_inputType) - m_inputType->AddRef(); - - return S_OK; -} - -STDMETHODIMP MFTransform::SetOutputType(DWORD dwOutputStreamID, IMFMediaType *pType, DWORD dwFlags) -{ - if (dwOutputStreamID > 0) - return MF_E_INVALIDSTREAMNUMBER; - - if (dwFlags == MFT_SET_TYPE_TEST_ONLY && !pType) - return E_POINTER; - - QMutexLocker locker(&m_mutex); - - // Input type must be set first - if (!m_inputType) - return MF_E_TRANSFORM_TYPE_NOT_SET; - - if (m_sample) - return MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING; - - DWORD flags = 0; - if (pType && m_inputType->IsEqual(pType, &flags) != S_OK) - return MF_E_INVALIDMEDIATYPE; - - if (dwFlags == MFT_SET_TYPE_TEST_ONLY) - return pType ? S_OK : E_POINTER; - - if (m_outputType) - m_outputType->Release(); - - m_outputType = pType; - - if (m_outputType) { - m_outputType->AddRef(); - m_format = videoFormatForMFMediaType(m_outputType, &m_bytesPerLine); - } - - return S_OK; -} - -STDMETHODIMP MFTransform::GetInputCurrentType(DWORD dwInputStreamID, IMFMediaType **ppType) -{ - if (dwInputStreamID > 0) - return MF_E_INVALIDSTREAMNUMBER; - - if (ppType == NULL) - return E_POINTER; - - QMutexLocker locker(&m_mutex); - - if (!m_inputType) - return MF_E_TRANSFORM_TYPE_NOT_SET; - - // Return a copy to make sure our type is not modified - if (FAILED(MFCreateMediaType(ppType))) - return E_OUTOFMEMORY; - - return m_inputType->CopyAllItems(*ppType); -} - -STDMETHODIMP MFTransform::GetOutputCurrentType(DWORD dwOutputStreamID, IMFMediaType **ppType) -{ - if (dwOutputStreamID > 0) - return MF_E_INVALIDSTREAMNUMBER; - - if (ppType == NULL) - return E_POINTER; - - QMutexLocker locker(&m_mutex); - - if (!m_outputType) - return MF_E_TRANSFORM_TYPE_NOT_SET; - - // Return a copy to make sure our type is not modified - if (FAILED(MFCreateMediaType(ppType))) - return E_OUTOFMEMORY; - - return m_outputType->CopyAllItems(*ppType); -} - -STDMETHODIMP MFTransform::GetInputStatus(DWORD dwInputStreamID, DWORD *pdwFlags) -{ - if (dwInputStreamID > 0) - return MF_E_INVALIDSTREAMNUMBER; - - if (!pdwFlags) - return E_POINTER; - - QMutexLocker locker(&m_mutex); - - if (!m_inputType || !m_outputType) - return MF_E_TRANSFORM_TYPE_NOT_SET; - - if (m_sample) - *pdwFlags = 0; - else - *pdwFlags = MFT_INPUT_STATUS_ACCEPT_DATA; - - return S_OK; -} - -STDMETHODIMP MFTransform::GetOutputStatus(DWORD *pdwFlags) -{ - if (!pdwFlags) - return E_POINTER; - - QMutexLocker locker(&m_mutex); - - if (!m_inputType || !m_outputType) - return MF_E_TRANSFORM_TYPE_NOT_SET; - - if (m_sample) - *pdwFlags = MFT_OUTPUT_STATUS_SAMPLE_READY; - else - *pdwFlags = 0; - - return S_OK; -} - -STDMETHODIMP MFTransform::SetOutputBounds(LONGLONG hnsLowerBound, LONGLONG hnsUpperBound) -{ - Q_UNUSED(hnsLowerBound); - Q_UNUSED(hnsUpperBound); - return E_NOTIMPL; -} - -STDMETHODIMP MFTransform::ProcessEvent(DWORD dwInputStreamID, IMFMediaEvent *pEvent) -{ - // This MFT ignores all events, and the pipeline should send all events downstream. - Q_UNUSED(dwInputStreamID); - Q_UNUSED(pEvent); - return E_NOTIMPL; -} - -STDMETHODIMP MFTransform::ProcessMessage(MFT_MESSAGE_TYPE eMessage, ULONG_PTR ulParam) -{ - Q_UNUSED(ulParam); - - HRESULT hr = S_OK; - - switch (eMessage) - { - case MFT_MESSAGE_COMMAND_FLUSH: - hr = OnFlush(); - break; - - case MFT_MESSAGE_COMMAND_DRAIN: - // Drain: Tells the MFT not to accept any more input until - // all of the pending output has been processed. That is our - // default behevior already, so there is nothing to do. - break; - - case MFT_MESSAGE_SET_D3D_MANAGER: - // The pipeline should never send this message unless the MFT - // has the MF_SA_D3D_AWARE attribute set to TRUE. However, if we - // do get this message, it's invalid and we don't implement it. - hr = E_NOTIMPL; - break; - - // The remaining messages do not require any action from this MFT. - case MFT_MESSAGE_NOTIFY_BEGIN_STREAMING: - case MFT_MESSAGE_NOTIFY_END_STREAMING: - case MFT_MESSAGE_NOTIFY_END_OF_STREAM: - case MFT_MESSAGE_NOTIFY_START_OF_STREAM: - break; - } - - return hr; -} - -STDMETHODIMP MFTransform::ProcessInput(DWORD dwInputStreamID, IMFSample *pSample, DWORD dwFlags) -{ - if (dwInputStreamID > 0) - return MF_E_INVALIDSTREAMNUMBER; - - if (dwFlags != 0) - return E_INVALIDARG; // dwFlags is reserved and must be zero. - - QMutexLocker locker(&m_mutex); - - if (!m_inputType) - return MF_E_TRANSFORM_TYPE_NOT_SET; - - if (m_sample) - return MF_E_NOTACCEPTING; - - // Validate the number of buffers. There should only be a single buffer to hold the video frame. - DWORD dwBufferCount = 0; - HRESULT hr = pSample->GetBufferCount(&dwBufferCount); - if (FAILED(hr)) - return hr; - - if (dwBufferCount == 0) - return E_FAIL; - - if (dwBufferCount > 1) - return MF_E_SAMPLE_HAS_TOO_MANY_BUFFERS; - - m_sample = pSample; - m_sample->AddRef(); - - QMutexLocker lockerProbe(&m_videoProbeMutex); - - if (!m_videoProbes.isEmpty()) { - QVideoFrame frame = makeVideoFrame(); - - for (MFVideoProbeControl* probe : qAsConst(m_videoProbes)) - probe->bufferProbed(frame); - } - - return S_OK; -} - -STDMETHODIMP MFTransform::ProcessOutput(DWORD dwFlags, DWORD cOutputBufferCount, MFT_OUTPUT_DATA_BUFFER *pOutputSamples, DWORD *pdwStatus) -{ - if (pOutputSamples == NULL || pdwStatus == NULL) - return E_POINTER; - - if (cOutputBufferCount != 1) - return E_INVALIDARG; - - QMutexLocker locker(&m_mutex); - - if (!m_inputType) - return MF_E_TRANSFORM_TYPE_NOT_SET; - - if (!m_outputType) { - pOutputSamples[0].dwStatus = MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE; - return MF_E_TRANSFORM_STREAM_CHANGE; - } - - IMFMediaBuffer *input = NULL; - IMFMediaBuffer *output = NULL; - - if (dwFlags == MFT_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER) - goto done; - else if (dwFlags != 0) - return E_INVALIDARG; - - if (!m_sample) - return MF_E_TRANSFORM_NEED_MORE_INPUT; - - // Since the MFT_OUTPUT_STREAM_PROVIDES_SAMPLES flag is set, the client - // should not be providing samples here - if (pOutputSamples[0].pSample != NULL) - return E_INVALIDARG; - - pOutputSamples[0].pSample = m_sample; - pOutputSamples[0].pSample->AddRef(); - - // Send video frame to probes - // We do it here (instead of inside ProcessInput) to make sure samples discarded by the renderer - // are not sent. - m_videoProbeMutex.lock(); - if (!m_videoProbes.isEmpty()) { - QVideoFrame frame = makeVideoFrame(); - - for (MFVideoProbeControl* probe : qAsConst(m_videoProbes)) - probe->bufferProbed(frame); - } - m_videoProbeMutex.unlock(); - -done: - pOutputSamples[0].dwStatus = 0; - *pdwStatus = 0; - - m_sample->Release(); - m_sample = 0; - - if (input) - input->Release(); - if (output) - output->Release(); - - return S_OK; -} - -HRESULT MFTransform::OnFlush() -{ - QMutexLocker locker(&m_mutex); - - if (m_sample) { - m_sample->Release(); - m_sample = 0; - } - return S_OK; -} - -QVideoFrame::PixelFormat MFTransform::formatFromSubtype(const GUID& subtype) -{ - if (subtype == MFVideoFormat_ARGB32) - return QVideoFrame::Format_ARGB32; - else if (subtype == MFVideoFormat_RGB32) - return QVideoFrame::Format_RGB32; - else if (subtype == MFVideoFormat_RGB24) - return QVideoFrame::Format_RGB24; - else if (subtype == MFVideoFormat_RGB565) - return QVideoFrame::Format_RGB565; - else if (subtype == MFVideoFormat_RGB555) - return QVideoFrame::Format_RGB555; - else if (subtype == MFVideoFormat_AYUV) - return QVideoFrame::Format_AYUV444; - else if (subtype == MFVideoFormat_I420) - return QVideoFrame::Format_YUV420P; - else if (subtype == MFVideoFormat_UYVY) - return QVideoFrame::Format_UYVY; - else if (subtype == MFVideoFormat_YV12) - return QVideoFrame::Format_YV12; - else if (subtype == MFVideoFormat_NV12) - return QVideoFrame::Format_NV12; - - return QVideoFrame::Format_Invalid; -} - -QVideoSurfaceFormat MFTransform::videoFormatForMFMediaType(IMFMediaType *mediaType, int *bytesPerLine) -{ - UINT32 stride; - if (FAILED(mediaType->GetUINT32(MF_MT_DEFAULT_STRIDE, &stride))) { - *bytesPerLine = 0; - return QVideoSurfaceFormat(); - } - - *bytesPerLine = (int)stride; - - QSize size; - UINT32 width, height; - if (FAILED(MFGetAttributeSize(mediaType, MF_MT_FRAME_SIZE, &width, &height))) - return QVideoSurfaceFormat(); - - size.setWidth(width); - size.setHeight(height); - - GUID subtype = GUID_NULL; - if (FAILED(mediaType->GetGUID(MF_MT_SUBTYPE, &subtype))) - return QVideoSurfaceFormat(); - - QVideoFrame::PixelFormat pixelFormat = formatFromSubtype(subtype); - QVideoSurfaceFormat format(size, pixelFormat); - - UINT32 num, den; - if (SUCCEEDED(MFGetAttributeRatio(mediaType, MF_MT_PIXEL_ASPECT_RATIO, &num, &den))) { - format.setPixelAspectRatio(num, den); - } - if (SUCCEEDED(MFGetAttributeRatio(mediaType, MF_MT_FRAME_RATE, &num, &den))) { - format.setFrameRate(qreal(num)/den); - } - - return format; -} - -QVideoFrame MFTransform::makeVideoFrame() -{ - QVideoFrame frame; - - if (!m_format.isValid()) - return frame; - - IMFMediaBuffer *buffer = 0; - - do { - if (FAILED(m_sample->ConvertToContiguousBuffer(&buffer))) - break; - - QByteArray array = dataFromBuffer(buffer, m_format.frameHeight(), &m_bytesPerLine); - if (array.isEmpty()) - break; - - // Wrapping IMFSample or IMFMediaBuffer in a QVideoFrame is not possible because we cannot hold - // IMFSample for a "long" time without affecting the rest of the topology. - // If IMFSample is held for more than 5 frames decoder starts to reuse it even though it hasn't been released it yet. - // That is why we copy data from IMFMediaBuffer here. - frame = QVideoFrame(new QMemoryVideoBuffer(array, m_bytesPerLine), m_format.frameSize(), m_format.pixelFormat()); - - // WMF uses 100-nanosecond units, Qt uses microseconds - LONGLONG startTime = -1; - if (SUCCEEDED(m_sample->GetSampleTime(&startTime))) { - frame.setStartTime(startTime * 0.1); - - LONGLONG duration = -1; - if (SUCCEEDED(m_sample->GetSampleDuration(&duration))) - frame.setEndTime((startTime + duration) * 0.1); - } - } while (false); - - if (buffer) - buffer->Release(); - - return frame; -} - -QByteArray MFTransform::dataFromBuffer(IMFMediaBuffer *buffer, int height, int *bytesPerLine) -{ - QByteArray array; - BYTE *bytes; - DWORD length; - HRESULT hr = buffer->Lock(&bytes, NULL, &length); - if (SUCCEEDED(hr)) { - array = QByteArray((const char *)bytes, (int)length); - buffer->Unlock(); - } else { - // try to lock as Direct3DSurface - IDirect3DSurface9 *surface = 0; - do { - if (FAILED(MFGetService(buffer, MR_BUFFER_SERVICE, IID_IDirect3DSurface9, (void**)&surface))) - break; - - D3DLOCKED_RECT rect; - if (FAILED(surface->LockRect(&rect, NULL, D3DLOCK_READONLY))) - break; - - if (bytesPerLine) - *bytesPerLine = (int)rect.Pitch; - - array = QByteArray((const char *)rect.pBits, rect.Pitch * height); - surface->UnlockRect(); - } while (false); - - if (surface) { - surface->Release(); - surface = 0; - } - } - - return array; -} - -bool MFTransform::isMediaTypeSupported(IMFMediaType *type) -{ - // If we don't have the video sink's type handler, - // assume it supports anything... - if (!m_videoSinkTypeHandler || !type) - return true; - - return m_videoSinkTypeHandler->IsMediaTypeSupported(type, NULL) == S_OK; -} diff --git a/src/plugins/wmf/player/mftvideo.h b/src/plugins/wmf/player/mftvideo.h deleted file mode 100644 index ffcb80b32..000000000 --- a/src/plugins/wmf/player/mftvideo.h +++ /dev/null @@ -1,117 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef MFTRANSFORM_H -#define MFTRANSFORM_H - -#include <mfapi.h> -#include <mfidl.h> -#include <QtCore/qlist.h> -#include <QtCore/qmutex.h> -#include <QtMultimedia/qvideosurfaceformat.h> - -QT_USE_NAMESPACE - -class MFVideoProbeControl; - -class MFTransform: public IMFTransform -{ -public: - MFTransform(); - ~MFTransform(); - - void addProbe(MFVideoProbeControl* probe); - void removeProbe(MFVideoProbeControl* probe); - - void setVideoSink(IUnknown *videoSink); - - // IUnknown methods - STDMETHODIMP QueryInterface(REFIID iid, void** ppv); - STDMETHODIMP_(ULONG) AddRef(); - STDMETHODIMP_(ULONG) Release(); - - // IMFTransform methods - STDMETHODIMP GetStreamLimits(DWORD *pdwInputMinimum, DWORD *pdwInputMaximum, DWORD *pdwOutputMinimum, DWORD *pdwOutputMaximum); - STDMETHODIMP GetStreamCount(DWORD *pcInputStreams, DWORD *pcOutputStreams); - STDMETHODIMP GetStreamIDs(DWORD dwInputIDArraySize, DWORD *pdwInputIDs, DWORD dwOutputIDArraySize, DWORD *pdwOutputIDs); - STDMETHODIMP GetInputStreamInfo(DWORD dwInputStreamID, MFT_INPUT_STREAM_INFO *pStreamInfo); - STDMETHODIMP GetOutputStreamInfo(DWORD dwOutputStreamID, MFT_OUTPUT_STREAM_INFO *pStreamInfo); - STDMETHODIMP GetAttributes(IMFAttributes **pAttributes); - STDMETHODIMP GetInputStreamAttributes(DWORD dwInputStreamID, IMFAttributes **pAttributes); - STDMETHODIMP GetOutputStreamAttributes(DWORD dwOutputStreamID, IMFAttributes **pAttributes); - STDMETHODIMP DeleteInputStream(DWORD dwStreamID); - STDMETHODIMP AddInputStreams(DWORD cStreams, DWORD *adwStreamIDs); - STDMETHODIMP GetInputAvailableType(DWORD dwInputStreamID, DWORD dwTypeIndex, IMFMediaType **ppType); - STDMETHODIMP GetOutputAvailableType(DWORD dwOutputStreamID,DWORD dwTypeIndex, IMFMediaType **ppType); - STDMETHODIMP SetInputType(DWORD dwInputStreamID, IMFMediaType *pType, DWORD dwFlags); - STDMETHODIMP SetOutputType(DWORD dwOutputStreamID, IMFMediaType *pType, DWORD dwFlags); - STDMETHODIMP GetInputCurrentType(DWORD dwInputStreamID, IMFMediaType **ppType); - STDMETHODIMP GetOutputCurrentType(DWORD dwOutputStreamID, IMFMediaType **ppType); - STDMETHODIMP GetInputStatus(DWORD dwInputStreamID, DWORD *pdwFlags); - STDMETHODIMP GetOutputStatus(DWORD *pdwFlags); - STDMETHODIMP SetOutputBounds(LONGLONG hnsLowerBound, LONGLONG hnsUpperBound); - STDMETHODIMP ProcessEvent(DWORD dwInputStreamID, IMFMediaEvent *pEvent); - STDMETHODIMP ProcessMessage(MFT_MESSAGE_TYPE eMessage, ULONG_PTR ulParam); - STDMETHODIMP ProcessInput(DWORD dwInputStreamID, IMFSample *pSample, DWORD dwFlags); - STDMETHODIMP ProcessOutput(DWORD dwFlags, DWORD cOutputBufferCount, MFT_OUTPUT_DATA_BUFFER *pOutputSamples, DWORD *pdwStatus); - -private: - HRESULT OnFlush(); - static QVideoFrame::PixelFormat formatFromSubtype(const GUID& subtype); - static QVideoSurfaceFormat videoFormatForMFMediaType(IMFMediaType *mediaType, int *bytesPerLine); - QVideoFrame makeVideoFrame(); - QByteArray dataFromBuffer(IMFMediaBuffer *buffer, int height, int *bytesPerLine); - bool isMediaTypeSupported(IMFMediaType *type); - - long m_cRef; - IMFMediaType *m_inputType; - IMFMediaType *m_outputType; - IMFSample *m_sample; - QMutex m_mutex; - - IMFMediaTypeHandler *m_videoSinkTypeHandler; - - QList<MFVideoProbeControl*> m_videoProbes; - QMutex m_videoProbeMutex; - - QVideoSurfaceFormat m_format; - int m_bytesPerLine; -}; - -#endif diff --git a/src/plugins/wmf/player/mfvideoprobecontrol.cpp b/src/plugins/wmf/player/mfvideoprobecontrol.cpp deleted file mode 100644 index 13d9a1bfe..000000000 --- a/src/plugins/wmf/player/mfvideoprobecontrol.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "mfvideoprobecontrol.h" - -MFVideoProbeControl::MFVideoProbeControl(QObject *parent) - : QMediaVideoProbeControl(parent) -{ -} - -MFVideoProbeControl::~MFVideoProbeControl() -{ -} - -void MFVideoProbeControl::bufferProbed(const QVideoFrame& frame) -{ - QMetaObject::invokeMethod(this, "videoFrameProbed", Qt::QueuedConnection, Q_ARG(QVideoFrame, frame)); -} diff --git a/src/plugins/wmf/player/mfvideoprobecontrol.h b/src/plugins/wmf/player/mfvideoprobecontrol.h deleted file mode 100644 index 2b238725a..000000000 --- a/src/plugins/wmf/player/mfvideoprobecontrol.h +++ /dev/null @@ -1,59 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef MFVIDEOPROBECONTROL_H -#define MFVIDEOPROBECONTROL_H - -#include <qmediavideoprobecontrol.h> -#include <QtCore/qmutex.h> -#include <qvideoframe.h> - -QT_USE_NAMESPACE - -class MFVideoProbeControl : public QMediaVideoProbeControl -{ - Q_OBJECT -public: - explicit MFVideoProbeControl(QObject *parent); - virtual ~MFVideoProbeControl(); - - void bufferProbed(const QVideoFrame& frame); -}; - -#endif diff --git a/src/plugins/wmf/player/mfvideorenderercontrol.cpp b/src/plugins/wmf/player/mfvideorenderercontrol.cpp deleted file mode 100644 index 7b121255f..000000000 --- a/src/plugins/wmf/player/mfvideorenderercontrol.cpp +++ /dev/null @@ -1,2426 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Mobility Components. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "mfvideorenderercontrol.h" -#include "mfactivate.h" - -#include "evrcustompresenter.h" - -#include <qabstractvideosurface.h> -#include <qvideosurfaceformat.h> -#include <qtcore/qtimer.h> -#include <qtcore/qmutex.h> -#include <qtcore/qcoreevent.h> -#include <qtcore/qcoreapplication.h> -#include <qtcore/qthread.h> -#include "guiddef.h" -#include <qtcore/qdebug.h> - -//#define DEBUG_MEDIAFOUNDATION -#define PAD_TO_DWORD(x) (((x) + 3) & ~3) - -namespace -{ - class MediaSampleVideoBuffer : public QAbstractVideoBuffer - { - public: - MediaSampleVideoBuffer(IMFMediaBuffer *buffer, int bytesPerLine) - : QAbstractVideoBuffer(NoHandle) - , m_buffer(buffer) - , m_bytesPerLine(bytesPerLine) - , m_mapMode(NotMapped) - { - buffer->AddRef(); - } - - ~MediaSampleVideoBuffer() - { - m_buffer->Release(); - } - - uchar *map(MapMode mode, int *numBytes, int *bytesPerLine) - { - if (m_mapMode == NotMapped && mode != NotMapped) { - BYTE *bytes; - DWORD length; - HRESULT hr = m_buffer->Lock(&bytes, NULL, &length); - if (SUCCEEDED(hr)) { - if (numBytes) - *numBytes = int(length); - - if (bytesPerLine) - *bytesPerLine = m_bytesPerLine; - - m_mapMode = mode; - return reinterpret_cast<uchar *>(bytes); - } else { - qWarning("Faild to lock mf buffer!"); - } - } - return 0; - } - - void unmap() - { - if (m_mapMode == NotMapped) - return; - m_mapMode = NotMapped; - m_buffer->Unlock(); - } - - MapMode mapMode() const - { - return m_mapMode; - } - - private: - IMFMediaBuffer *m_buffer; - int m_bytesPerLine; - MapMode m_mapMode; - }; - - // Custom interface for handling IMFStreamSink::PlaceMarker calls asynchronously. - MIDL_INTERFACE("a3ff32de-1031-438a-8b47-82f8acda59b7") - IMarker : public IUnknown - { - virtual STDMETHODIMP GetMarkerType(MFSTREAMSINK_MARKER_TYPE *pType) = 0; - virtual STDMETHODIMP GetMarkerValue(PROPVARIANT *pvar) = 0; - virtual STDMETHODIMP GetContext(PROPVARIANT *pvar) = 0; - }; - - class Marker : public IMarker - { - public: - static HRESULT Create( - MFSTREAMSINK_MARKER_TYPE eMarkerType, - const PROPVARIANT* pvarMarkerValue, // Can be NULL. - const PROPVARIANT* pvarContextValue, // Can be NULL. - IMarker **ppMarker) - { - if (ppMarker == NULL) - return E_POINTER; - - HRESULT hr = S_OK; - Marker *pMarker = new Marker(eMarkerType); - if (pMarker == NULL) - hr = E_OUTOFMEMORY; - - // Copy the marker data. - if (SUCCEEDED(hr) && pvarMarkerValue) - hr = PropVariantCopy(&pMarker->m_varMarkerValue, pvarMarkerValue); - - if (SUCCEEDED(hr) && pvarContextValue) - hr = PropVariantCopy(&pMarker->m_varContextValue, pvarContextValue); - - if (SUCCEEDED(hr)) { - *ppMarker = pMarker; - (*ppMarker)->AddRef(); - } - - if (pMarker) - pMarker->Release(); - - return hr; - } - - // IUnknown methods. - STDMETHODIMP QueryInterface(REFIID iid, void** ppv) - { - if (!ppv) - return E_POINTER; - if (iid == IID_IUnknown) { - *ppv = static_cast<IUnknown*>(this); - } else if (iid == __uuidof(IMarker)) { - *ppv = static_cast<IMarker*>(this); - } else { - *ppv = NULL; - return E_NOINTERFACE; - } - AddRef(); - return S_OK; - } - - STDMETHODIMP_(ULONG) AddRef() - { - return InterlockedIncrement(&m_cRef); - } - - STDMETHODIMP_(ULONG) Release() - { - LONG cRef = InterlockedDecrement(&m_cRef); - if (cRef == 0) - delete this; - // For thread safety, return a temporary variable. - return cRef; - } - - STDMETHODIMP GetMarkerType(MFSTREAMSINK_MARKER_TYPE *pType) - { - if (pType == NULL) - return E_POINTER; - *pType = m_eMarkerType; - return S_OK; - } - - STDMETHODIMP GetMarkerValue(PROPVARIANT *pvar) - { - if (pvar == NULL) - return E_POINTER; - return PropVariantCopy(pvar, &m_varMarkerValue); - } - - STDMETHODIMP GetContext(PROPVARIANT *pvar) - { - if (pvar == NULL) - return E_POINTER; - return PropVariantCopy(pvar, &m_varContextValue); - } - - protected: - MFSTREAMSINK_MARKER_TYPE m_eMarkerType; - PROPVARIANT m_varMarkerValue; - PROPVARIANT m_varContextValue; - - private: - long m_cRef; - - Marker(MFSTREAMSINK_MARKER_TYPE eMarkerType) : m_cRef(1), m_eMarkerType(eMarkerType) - { - PropVariantInit(&m_varMarkerValue); - PropVariantInit(&m_varContextValue); - } - - virtual ~Marker() - { - PropVariantClear(&m_varMarkerValue); - PropVariantClear(&m_varContextValue); - } - }; - - class MediaStream : public QObject, public IMFStreamSink, public IMFMediaTypeHandler - { - Q_OBJECT - friend class MFVideoRendererControl; - public: - static const DWORD DEFAULT_MEDIA_STREAM_ID = 0x0; - - MediaStream(IMFMediaSink *parent, MFVideoRendererControl *rendererControl) - : m_cRef(1) - , m_eventQueue(0) - , m_shutdown(false) - , m_surface(0) - , m_state(State_TypeNotSet) - , m_currentFormatIndex(-1) - , m_bytesPerLine(0) - , m_workQueueId(0) - , m_workQueueCB(this, &MediaStream::onDispatchWorkItem) - , m_finalizeResult(0) - , m_scheduledBuffer(0) - , m_bufferStartTime(-1) - , m_bufferDuration(-1) - , m_presentationClock(0) - , m_sampleRequested(false) - , m_currentMediaType(0) - , m_prerolling(false) - , m_prerollTargetTime(0) - , m_startTime(0) - , m_rendererControl(rendererControl) - , m_rate(1.f) - { - m_sink = parent; - - if (FAILED(MFCreateEventQueue(&m_eventQueue))) - qWarning("Failed to create mf event queue!"); - if (FAILED(MFAllocateWorkQueue(&m_workQueueId))) - qWarning("Failed to allocated mf work queue!"); - } - - ~MediaStream() - { - Q_ASSERT(m_shutdown); - } - - //from IUnknown - STDMETHODIMP QueryInterface(REFIID riid, void** ppvObject) - { - if (!ppvObject) - return E_POINTER; - if (riid == IID_IMFStreamSink) { - *ppvObject = static_cast<IMFStreamSink*>(this); - } else if (riid == IID_IMFMediaEventGenerator) { - *ppvObject = static_cast<IMFMediaEventGenerator*>(this); - } else if (riid == IID_IMFMediaTypeHandler) { - *ppvObject = static_cast<IMFMediaTypeHandler*>(this); - } else if (riid == IID_IUnknown) { - *ppvObject = static_cast<IUnknown*>(static_cast<IMFStreamSink*>(this)); - } else { - *ppvObject = NULL; - return E_NOINTERFACE; - } - AddRef(); - return S_OK; - } - - STDMETHODIMP_(ULONG) AddRef(void) - { - return InterlockedIncrement(&m_cRef); - } - - STDMETHODIMP_(ULONG) Release(void) - { - LONG cRef = InterlockedDecrement(&m_cRef); - if (cRef == 0) - delete this; - // For thread safety, return a temporary variable. - return cRef; - } - - //from IMFMediaEventGenerator - STDMETHODIMP GetEvent( - DWORD dwFlags, - IMFMediaEvent **ppEvent) - { - // GetEvent can block indefinitely, so we don't hold the lock. - // This requires some juggling with the event queue pointer. - HRESULT hr = S_OK; - IMFMediaEventQueue *queue = NULL; - - m_mutex.lock(); - if (m_shutdown) - hr = MF_E_SHUTDOWN; - if (SUCCEEDED(hr)) { - queue = m_eventQueue; - queue->AddRef(); - } - m_mutex.unlock(); - - // Now get the event. - if (SUCCEEDED(hr)) { - hr = queue->GetEvent(dwFlags, ppEvent); - queue->Release(); - } - - return hr; - } - - STDMETHODIMP BeginGetEvent( - IMFAsyncCallback *pCallback, - IUnknown *punkState) - { - QMutexLocker locker(&m_mutex); - if (m_shutdown) - return MF_E_SHUTDOWN; - return m_eventQueue->BeginGetEvent(pCallback, punkState); - } - - STDMETHODIMP EndGetEvent( - IMFAsyncResult *pResult, - IMFMediaEvent **ppEvent) - { - QMutexLocker locker(&m_mutex); - if (m_shutdown) - return MF_E_SHUTDOWN; - return m_eventQueue->EndGetEvent(pResult, ppEvent); - } - - STDMETHODIMP QueueEvent( - MediaEventType met, - REFGUID guidExtendedType, - HRESULT hrStatus, - const PROPVARIANT *pvValue) - { -#ifdef DEBUG_MEDIAFOUNDATION - qDebug() << "MediaStream::QueueEvent" << met; -#endif - QMutexLocker locker(&m_mutex); - if (m_shutdown) - return MF_E_SHUTDOWN; - return m_eventQueue->QueueEventParamVar(met, guidExtendedType, hrStatus, pvValue); - } - - //from IMFStreamSink - STDMETHODIMP GetMediaSink( - IMFMediaSink **ppMediaSink) - { - QMutexLocker locker(&m_mutex); - if (m_shutdown) - return MF_E_SHUTDOWN; - else if (!ppMediaSink) - return E_INVALIDARG; - - m_sink->AddRef(); - *ppMediaSink = m_sink; - return S_OK; - } - - STDMETHODIMP GetIdentifier( - DWORD *pdwIdentifier) - { - *pdwIdentifier = MediaStream::DEFAULT_MEDIA_STREAM_ID; - return S_OK; - } - - STDMETHODIMP GetMediaTypeHandler( - IMFMediaTypeHandler **ppHandler) - { - LPVOID handler = NULL; - HRESULT hr = QueryInterface(IID_IMFMediaTypeHandler, &handler); - *ppHandler = (IMFMediaTypeHandler*)(handler); - return hr; - } - - STDMETHODIMP ProcessSample( - IMFSample *pSample) - { - if (pSample == NULL) - return E_INVALIDARG; - HRESULT hr = S_OK; - QMutexLocker locker(&m_mutex); - if (m_shutdown) - return MF_E_SHUTDOWN; - - if (!m_prerolling) { - hr = validateOperation(OpProcessSample); - if (FAILED(hr)) - return hr; - } - - pSample->AddRef(); - m_sampleQueue.push_back(pSample); - - // Unless we are paused, start an async operation to dispatch the next sample. - if (m_state != State_Paused) - hr = queueAsyncOperation(OpProcessSample); - - return hr; - } - - STDMETHODIMP PlaceMarker( - MFSTREAMSINK_MARKER_TYPE eMarkerType, - const PROPVARIANT *pvarMarkerValue, - const PROPVARIANT *pvarContextValue) - { - HRESULT hr = S_OK; - QMutexLocker locker(&m_mutex); - IMarker *pMarker = NULL; - if (m_shutdown) - return MF_E_SHUTDOWN; - - hr = validateOperation(OpPlaceMarker); - if (FAILED(hr)) - return hr; - - // Create a marker object and put it on the sample queue. - hr = Marker::Create(eMarkerType, pvarMarkerValue, pvarContextValue, &pMarker); - if (FAILED(hr)) - return hr; - - m_sampleQueue.push_back(pMarker); - - // Unless we are paused, start an async operation to dispatch the next sample/marker. - if (m_state != State_Paused) - hr = queueAsyncOperation(OpPlaceMarker); // Increments ref count on pOp. - return hr; - } - - STDMETHODIMP Flush( void) - { -#ifdef DEBUG_MEDIAFOUNDATION - qDebug() << "MediaStream::Flush"; -#endif - QMutexLocker locker(&m_mutex); - if (m_shutdown) - return MF_E_SHUTDOWN; - // Note: Even though we are flushing data, we still need to send - // any marker events that were queued. - clearBufferCache(); - return processSamplesFromQueue(DropSamples); - } - - //from IMFMediaTypeHandler - STDMETHODIMP IsMediaTypeSupported( - IMFMediaType *pMediaType, - IMFMediaType **ppMediaType) - { - if (ppMediaType) - *ppMediaType = NULL; - QMutexLocker locker(&m_mutex); - if (m_shutdown) - return MF_E_SHUTDOWN; - - int index = getMediaTypeIndex(pMediaType); - if (index < 0) { - if (ppMediaType && m_mediaTypes.size() > 0) { - *ppMediaType = m_mediaTypes[0]; - (*ppMediaType)->AddRef(); - } - return MF_E_INVALIDMEDIATYPE; - } - - BOOL compressed = TRUE; - pMediaType->IsCompressedFormat(&compressed); - if (compressed) { - if (ppMediaType && (SUCCEEDED(MFCreateMediaType(ppMediaType)))) { - (*ppMediaType)->CopyAllItems(pMediaType); - (*ppMediaType)->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, TRUE); - (*ppMediaType)->SetUINT32(MF_MT_COMPRESSED, FALSE); - (*ppMediaType)->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE); - } - return MF_E_INVALIDMEDIATYPE; - } - - return S_OK; - } - - STDMETHODIMP GetMediaTypeCount( - DWORD *pdwTypeCount) - { - if (pdwTypeCount == NULL) - return E_INVALIDARG; - QMutexLocker locker(&m_mutex); - *pdwTypeCount = DWORD(m_mediaTypes.size()); - return S_OK; - } - - STDMETHODIMP GetMediaTypeByIndex( - DWORD dwIndex, - IMFMediaType **ppType) - { - if (ppType == NULL) - return E_INVALIDARG; - HRESULT hr = S_OK; - QMutexLocker locker(&m_mutex); - if (m_shutdown) - hr = MF_E_SHUTDOWN; - - if (SUCCEEDED(hr)) { - if (dwIndex >= DWORD(m_mediaTypes.size())) - hr = MF_E_NO_MORE_TYPES; - } - - if (SUCCEEDED(hr)) { - *ppType = m_mediaTypes[dwIndex]; - (*ppType)->AddRef(); - } - return hr; - } - - STDMETHODIMP SetCurrentMediaType( - IMFMediaType *pMediaType) - { - HRESULT hr = S_OK; - QMutexLocker locker(&m_mutex); - if (m_shutdown) - return MF_E_SHUTDOWN; - - DWORD flag = MF_MEDIATYPE_EQUAL_MAJOR_TYPES | - MF_MEDIATYPE_EQUAL_FORMAT_TYPES | - MF_MEDIATYPE_EQUAL_FORMAT_DATA; - - if (m_currentMediaType && (m_currentMediaType->IsEqual(pMediaType, &flag) == S_OK)) - return S_OK; - - hr = validateOperation(OpSetMediaType); - - if (SUCCEEDED(hr)) { - int index = getMediaTypeIndex(pMediaType); - if (index >= 0) { - UINT64 size; - hr = pMediaType->GetUINT64(MF_MT_FRAME_SIZE, &size); - if (SUCCEEDED(hr)) { - m_currentFormatIndex = index; - int width = int(HI32(size)); - int height = int(LO32(size)); - QVideoSurfaceFormat format(QSize(width, height), m_pixelFormats[index]); - m_surfaceFormat = format; - - MFVideoArea viewport; - if (SUCCEEDED(pMediaType->GetBlob(MF_MT_GEOMETRIC_APERTURE, - reinterpret_cast<UINT8*>(&viewport), - sizeof(MFVideoArea), - NULL))) { - - m_surfaceFormat.setViewport(QRect(viewport.OffsetX.value, - viewport.OffsetY.value, - viewport.Area.cx, - viewport.Area.cy)); - } - - if (FAILED(pMediaType->GetUINT32(MF_MT_DEFAULT_STRIDE, (UINT32*)&m_bytesPerLine))) { - m_bytesPerLine = getBytesPerLine(format); - } - - m_state = State_Ready; - if (m_currentMediaType) - m_currentMediaType->Release(); - m_currentMediaType = pMediaType; - pMediaType->AddRef(); - } - } else { - hr = MF_E_INVALIDREQUEST; - } - } - return hr; - } - - STDMETHODIMP GetCurrentMediaType( - IMFMediaType **ppMediaType) - { - if (ppMediaType == NULL) - return E_INVALIDARG; - QMutexLocker locker(&m_mutex); - if (m_shutdown) - return MF_E_SHUTDOWN; - if (m_currentFormatIndex < 0) - return MF_E_NOT_INITIALIZED; - *ppMediaType = m_currentMediaType; - (*ppMediaType)->AddRef(); - return S_OK; - } - - STDMETHODIMP GetMajorType( - GUID *pguidMajorType) - { - if (pguidMajorType == NULL) - return E_INVALIDARG; - *pguidMajorType = MFMediaType_Video; - return S_OK; - } - - // - void setSurface(QAbstractVideoSurface *surface) - { - m_mutex.lock(); - m_surface = surface; - m_mutex.unlock(); - supportedFormatsChanged(); - } - - void setClock(IMFPresentationClock *presentationClock) - { - QMutexLocker locker(&m_mutex); - if (!m_shutdown) { - if (m_presentationClock) - m_presentationClock->Release(); - m_presentationClock = presentationClock; - if (m_presentationClock) - m_presentationClock->AddRef(); - } - } - - void shutdown() - { - QMutexLocker locker(&m_mutex); - Q_ASSERT(!m_shutdown); - - if (m_currentMediaType) { - m_currentMediaType->Release(); - m_currentMediaType = NULL; - m_currentFormatIndex = -1; - } - - if (m_eventQueue) - m_eventQueue->Shutdown(); - - MFUnlockWorkQueue(m_workQueueId); - - if (m_presentationClock) { - m_presentationClock->Release(); - m_presentationClock = NULL; - } - - clearMediaTypes(); - clearSampleQueue(); - clearBufferCache(); - - if (m_eventQueue) { - m_eventQueue->Release(); - m_eventQueue = NULL; - } - - m_shutdown = true; - } - - HRESULT startPreroll(MFTIME hnsUpcomingStartTime) - { - QMutexLocker locker(&m_mutex); - HRESULT hr = validateOperation(OpPreroll); - if (SUCCEEDED(hr)) { - m_state = State_Prerolling; - m_prerollTargetTime = hnsUpcomingStartTime; - hr = queueAsyncOperation(OpPreroll); - } - return hr; - } - - HRESULT finalize(IMFAsyncCallback *pCallback, IUnknown *punkState) - { - QMutexLocker locker(&m_mutex); - HRESULT hr = S_OK; - hr = validateOperation(OpFinalize); - if (SUCCEEDED(hr) && m_finalizeResult != NULL) - hr = MF_E_INVALIDREQUEST; // The operation is already pending. - - // Create and store the async result object. - if (SUCCEEDED(hr)) - hr = MFCreateAsyncResult(NULL, pCallback, punkState, &m_finalizeResult); - - if (SUCCEEDED(hr)) { - m_state = State_Finalized; - hr = queueAsyncOperation(OpFinalize); - } - return hr; - } - - HRESULT start(MFTIME start) - { -#ifdef DEBUG_MEDIAFOUNDATION - qDebug() << "MediaStream::start" << start; -#endif - HRESULT hr = S_OK; - QMutexLocker locker(&m_mutex); - if (m_rate != 0) - hr = validateOperation(OpStart); - - if (SUCCEEDED(hr)) { - MFTIME sysTime; - if (start != PRESENTATION_CURRENT_POSITION) - m_startTime = start; // Cache the start time. - else - m_presentationClock->GetCorrelatedTime(0, &m_startTime, &sysTime); - m_state = State_Started; - hr = queueAsyncOperation(OpStart); - } - return hr; - } - - HRESULT restart() - { -#ifdef DEBUG_MEDIAFOUNDATION - qDebug() << "MediaStream::restart"; -#endif - QMutexLocker locker(&m_mutex); - HRESULT hr = validateOperation(OpRestart); - if (SUCCEEDED(hr)) { - m_state = State_Started; - hr = queueAsyncOperation(OpRestart); - } - return hr; - } - - HRESULT stop() - { -#ifdef DEBUG_MEDIAFOUNDATION - qDebug() << "MediaStream::stop"; -#endif - QMutexLocker locker(&m_mutex); - HRESULT hr = validateOperation(OpStop); - if (SUCCEEDED(hr)) { - m_state = State_Stopped; - hr = queueAsyncOperation(OpStop); - } - return hr; - } - - HRESULT pause() - { -#ifdef DEBUG_MEDIAFOUNDATION - qDebug() << "MediaStream::pause"; -#endif - QMutexLocker locker(&m_mutex); - HRESULT hr = validateOperation(OpPause); - if (SUCCEEDED(hr)) { - m_state = State_Paused; - hr = queueAsyncOperation(OpPause); - } - return hr; - } - - HRESULT setRate(float rate) - { -#ifdef DEBUG_MEDIAFOUNDATION - qDebug() << "MediaStream::setRate" << rate; -#endif - QMutexLocker locker(&m_mutex); - HRESULT hr = validateOperation(OpSetRate); - if (SUCCEEDED(hr)) { - m_rate = rate; - hr = queueAsyncOperation(OpSetRate); - } - return hr; - } - - void supportedFormatsChanged() - { - QMutexLocker locker(&m_mutex); - m_pixelFormats.clear(); - clearMediaTypes(); - if (!m_surface) - return; - const QList<QVideoFrame::PixelFormat> formats = m_surface->supportedPixelFormats(); - for (QVideoFrame::PixelFormat format : formats) { - IMFMediaType *mediaType; - if (FAILED(MFCreateMediaType(&mediaType))) { - qWarning("Failed to create mf media type!"); - continue; - } - mediaType->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, TRUE); - mediaType->SetUINT32(MF_MT_COMPRESSED, FALSE); - mediaType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE); - mediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); - switch (format) { - case QVideoFrame::Format_ARGB32: - case QVideoFrame::Format_ARGB32_Premultiplied: - mediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_ARGB32); - break; - case QVideoFrame::Format_RGB32: - mediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32); - break; - case QVideoFrame::Format_BGR24: // MFVideoFormat_RGB24 has a BGR layout - mediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24); - break; - case QVideoFrame::Format_RGB565: - mediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB565); - break; - case QVideoFrame::Format_RGB555: - mediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB555); - break; - case QVideoFrame::Format_AYUV444: - case QVideoFrame::Format_AYUV444_Premultiplied: - mediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_AYUV); - break; - case QVideoFrame::Format_YUV420P: - mediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_I420); - break; - case QVideoFrame::Format_UYVY: - mediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_UYVY); - break; - case QVideoFrame::Format_YV12: - mediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_YV12); - break; - case QVideoFrame::Format_NV12: - mediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_NV12); - break; - default: - mediaType->Release(); - continue; - } - // QAbstractVideoSurface::supportedPixelFormats() returns formats in descending - // order of preference, while IMFMediaTypeHandler is supposed to return supported - // formats in ascending order of preference. We need to reverse the list. - m_pixelFormats.prepend(format); - m_mediaTypes.prepend(mediaType); - } - } - - void present() - { - QMutexLocker locker(&m_mutex); - if (!m_scheduledBuffer) - return; - QVideoFrame frame = QVideoFrame( - new MediaSampleVideoBuffer(m_scheduledBuffer, m_bytesPerLine), - m_surfaceFormat.frameSize(), - m_surfaceFormat.pixelFormat()); - frame.setStartTime(m_bufferStartTime * 0.1); - frame.setEndTime((m_bufferStartTime + m_bufferDuration) * 0.1); - m_surface->present(frame); - m_scheduledBuffer->Release(); - m_scheduledBuffer = NULL; - if (m_rate != 0) - schedulePresentation(true); - } - - void clearScheduledFrame() - { - QMutexLocker locker(&m_mutex); - if (m_scheduledBuffer) { - m_scheduledBuffer->Release(); - m_scheduledBuffer = NULL; - schedulePresentation(true); - } - } - - enum - { - StartSurface = QEvent::User, - StopSurface, - FlushSurface, - PresentSurface - }; - - class PresentEvent : public QEvent - { - public: - PresentEvent(MFTIME targetTime) - : QEvent(QEvent::Type(PresentSurface)) - , m_time(targetTime) - { - } - - MFTIME targetTime() - { - return m_time; - } - - private: - MFTIME m_time; - }; - - protected: - void customEvent(QEvent *event) - { - QMutexLocker locker(&m_mutex); - if (event->type() == StartSurface) { - if (m_state == State_WaitForSurfaceStart) { - m_startResult = startSurface(); - queueAsyncOperation(OpStart); - } - } else if (event->type() == StopSurface) { - stopSurface(); - } else { - QObject::customEvent(event); - } - } - HRESULT m_startResult; - - private: - HRESULT startSurface() - { - if (!m_surface->isFormatSupported(m_surfaceFormat)) - return S_FALSE; - if (!m_surface->start(m_surfaceFormat)) - return S_FALSE; - return S_OK; - } - - void stopSurface() - { - m_surface->stop(); - } - - enum FlushState - { - DropSamples = 0, - WriteSamples - }; - - // State enum: Defines the current state of the stream. - enum State - { - State_TypeNotSet = 0, // No media type is set - State_Ready, // Media type is set, Start has never been called. - State_Prerolling, - State_Started, - State_Paused, - State_Stopped, - State_WaitForSurfaceStart, - State_Finalized, - State_Count = State_Finalized + 1 // Number of states - }; - - // StreamOperation: Defines various operations that can be performed on the stream. - enum StreamOperation - { - OpSetMediaType = 0, - OpStart, - OpPreroll, - OpRestart, - OpPause, - OpStop, - OpSetRate, - OpProcessSample, - OpPlaceMarker, - OpFinalize, - - Op_Count = OpFinalize + 1 // Number of operations - }; - - // AsyncOperation: - // Used to queue asynchronous operations. When we call MFPutWorkItem, we use this - // object for the callback state (pState). Then, when the callback is invoked, - // we can use the object to determine which asynchronous operation to perform. - class AsyncOperation : public IUnknown - { - public: - AsyncOperation(StreamOperation op) - :m_cRef(1), m_op(op) - { - } - - StreamOperation m_op; // The operation to perform. - - //from IUnknown - STDMETHODIMP QueryInterface(REFIID iid, void** ppv) - { - if (!ppv) - return E_POINTER; - if (iid == IID_IUnknown) { - *ppv = static_cast<IUnknown*>(this); - } else { - *ppv = NULL; - return E_NOINTERFACE; - } - AddRef(); - return S_OK; - } - STDMETHODIMP_(ULONG) AddRef() - { - return InterlockedIncrement(&m_cRef); - } - STDMETHODIMP_(ULONG) Release() - { - ULONG uCount = InterlockedDecrement(&m_cRef); - if (uCount == 0) - delete this; - // For thread safety, return a temporary variable. - return uCount; - } - - private: - long m_cRef; - virtual ~AsyncOperation() - { - Q_ASSERT(m_cRef == 0); - } - }; - - // ValidStateMatrix: Defines a look-up table that says which operations - // are valid from which states. - static BOOL ValidStateMatrix[State_Count][Op_Count]; - - long m_cRef; - QMutex m_mutex; - - IMFMediaType *m_currentMediaType; - State m_state; - IMFMediaSink *m_sink; - IMFMediaEventQueue *m_eventQueue; - DWORD m_workQueueId; - AsyncCallback<MediaStream> m_workQueueCB; - QList<IUnknown*> m_sampleQueue; - IMFAsyncResult *m_finalizeResult; // Result object for Finalize operation. - MFTIME m_startTime; // Presentation time when the clock started. - - bool m_shutdown; - QList<IMFMediaType*> m_mediaTypes; - QList<QVideoFrame::PixelFormat> m_pixelFormats; - int m_currentFormatIndex; - int m_bytesPerLine; - QVideoSurfaceFormat m_surfaceFormat; - QAbstractVideoSurface* m_surface; - MFVideoRendererControl *m_rendererControl; - - void clearMediaTypes() - { - for (IMFMediaType* mediaType : qAsConst(m_mediaTypes)) - mediaType->Release(); - m_mediaTypes.clear(); - } - - int getMediaTypeIndex(IMFMediaType *mt) - { - GUID majorType; - if (FAILED(mt->GetMajorType(&majorType))) - return -1; - if (majorType != MFMediaType_Video) - return -1; - - GUID subType; - if (FAILED(mt->GetGUID(MF_MT_SUBTYPE, &subType))) - return -1; - - for (int index = 0; index < m_mediaTypes.size(); ++index) { - GUID st; - m_mediaTypes[index]->GetGUID(MF_MT_SUBTYPE, &st); - if (st == subType) - return index; - } - return -1; - } - - int getBytesPerLine(const QVideoSurfaceFormat &format) - { - switch (format.pixelFormat()) { - // 32 bpp packed formats. - case QVideoFrame::Format_RGB32: - case QVideoFrame::Format_AYUV444: - return format.frameWidth() * 4; - // 24 bpp packed formats. - case QVideoFrame::Format_RGB24: - case QVideoFrame::Format_BGR24: - return PAD_TO_DWORD(format.frameWidth() * 3); - // 16 bpp packed formats. - case QVideoFrame::Format_RGB565: - case QVideoFrame::Format_RGB555: - case QVideoFrame::Format_YUYV: - case QVideoFrame::Format_UYVY: - return PAD_TO_DWORD(format.frameWidth() * 2); - // Planar formats. - case QVideoFrame::Format_IMC1: - case QVideoFrame::Format_IMC2: - case QVideoFrame::Format_IMC3: - case QVideoFrame::Format_IMC4: - case QVideoFrame::Format_YV12: - case QVideoFrame::Format_NV12: - case QVideoFrame::Format_YUV420P: - return PAD_TO_DWORD(format.frameWidth()); - default: - return 0; - } - } - - // Callback for MFPutWorkItem. - HRESULT onDispatchWorkItem(IMFAsyncResult* pAsyncResult) - { - QMutexLocker locker(&m_mutex); - if (m_shutdown) - return MF_E_SHUTDOWN; - - HRESULT hr = S_OK; - IUnknown *pState = NULL; - hr = pAsyncResult->GetState(&pState); - if (SUCCEEDED(hr)) { - // The state object is an AsncOperation object. - AsyncOperation *pOp = (AsyncOperation*)pState; - StreamOperation op = pOp->m_op; - switch (op) { - case OpStart: - endPreroll(S_FALSE); - if (m_state == State_WaitForSurfaceStart) { - hr = m_startResult; - m_state = State_Started; - } else if (!m_surface->isActive()) { - if (thread() == QThread::currentThread()) { - hr = startSurface(); - } - else { - m_state = State_WaitForSurfaceStart; - QCoreApplication::postEvent(m_rendererControl, new QChildEvent(QEvent::Type(StartSurface), this)); - break; - } - } - - if (m_state == State_Started) - schedulePresentation(true); - case OpRestart: - endPreroll(S_FALSE); - if (SUCCEEDED(hr)) { - // Send MEStreamSinkStarted. - hr = queueEvent(MEStreamSinkStarted, GUID_NULL, hr, NULL); - // Kick things off by requesting samples... - schedulePresentation(true); - // There might be samples queue from earlier (ie, while paused). - if (SUCCEEDED(hr)) - hr = processSamplesFromQueue(WriteSamples); - } - break; - case OpPreroll: - beginPreroll(); - break; - case OpStop: - // Drop samples from queue. - hr = processSamplesFromQueue(DropSamples); - clearBufferCache(); - // Send the event even if the previous call failed. - hr = queueEvent(MEStreamSinkStopped, GUID_NULL, hr, NULL); - if (m_surface->isActive()) { - if (thread() == QThread::currentThread()) { - stopSurface(); - } - else { - QCoreApplication::postEvent(m_rendererControl, new QChildEvent(QEvent::Type(StopSurface), this)); - } - } - break; - case OpPause: - hr = queueEvent(MEStreamSinkPaused, GUID_NULL, hr, NULL); - break; - case OpSetRate: - hr = queueEvent(MEStreamSinkRateChanged, GUID_NULL, S_OK, NULL); - break; - case OpProcessSample: - case OpPlaceMarker: - hr = dispatchProcessSample(pOp); - break; - case OpFinalize: - endPreroll(S_FALSE); - hr = dispatchFinalize(pOp); - break; - } - } - - if (pState) - pState->Release(); - return hr; - } - - - HRESULT queueEvent(MediaEventType met, REFGUID guidExtendedType, HRESULT hrStatus, const PROPVARIANT* pvValue) - { - HRESULT hr = S_OK; - if (m_shutdown) - hr = MF_E_SHUTDOWN; - if (SUCCEEDED(hr)) - hr = m_eventQueue->QueueEventParamVar(met, guidExtendedType, hrStatus, pvValue); - return hr; - } - - HRESULT validateOperation(StreamOperation op) - { - Q_ASSERT(!m_shutdown); - if (ValidStateMatrix[m_state][op]) - return S_OK; - else - return MF_E_INVALIDREQUEST; - } - - HRESULT queueAsyncOperation(StreamOperation op) - { - HRESULT hr = S_OK; - AsyncOperation *asyncOp = new AsyncOperation(op); - if (asyncOp == NULL) - hr = E_OUTOFMEMORY; - - if (SUCCEEDED(hr)) - hr = MFPutWorkItem(m_workQueueId, &m_workQueueCB, asyncOp); - - if (asyncOp) - asyncOp->Release(); - - return hr; - } - - HRESULT processSamplesFromQueue(FlushState bFlushData) - { - HRESULT hr = S_OK; - QList<IUnknown*>::Iterator pos = m_sampleQueue.begin(); - // Enumerate all of the samples/markers in the queue. - while (pos != m_sampleQueue.end()) { - IUnknown *pUnk = NULL; - IMarker *pMarker = NULL; - IMFSample *pSample = NULL; - pUnk = *pos; - // Figure out if this is a marker or a sample. - if (SUCCEEDED(hr)) { - hr = pUnk->QueryInterface(__uuidof(IMarker), (void**)&pMarker); - if (hr == E_NOINTERFACE) - hr = pUnk->QueryInterface(IID_IMFSample, (void**)&pSample); - } - - // Now handle the sample/marker appropriately. - if (SUCCEEDED(hr)) { - if (pMarker) { - hr = sendMarkerEvent(pMarker, bFlushData); - } else { - Q_ASSERT(pSample != NULL); // Not a marker, must be a sample - if (bFlushData == WriteSamples) - hr = processSampleData(pSample); - } - } - if (pMarker) - pMarker->Release(); - if (pSample) - pSample->Release(); - - if (FAILED(hr)) - break; - - pos++; - } - - clearSampleQueue(); - return hr; - } - - void beginPreroll() - { - if (m_prerolling) - return; - m_prerolling = true; - clearSampleQueue(); - clearBufferCache(); - queueEvent(MEStreamSinkRequestSample, GUID_NULL, S_OK, NULL); - } - - void endPreroll(HRESULT hrStatus) - { - if (!m_prerolling) - return; - m_prerolling = false; - queueEvent(MEStreamSinkPrerolled, GUID_NULL, hrStatus, NULL); - } - MFTIME m_prerollTargetTime; - bool m_prerolling; - - void clearSampleQueue() { - for (IUnknown* sample : qAsConst(m_sampleQueue)) - sample->Release(); - m_sampleQueue.clear(); - } - - HRESULT sendMarkerEvent(IMarker *pMarker, FlushState FlushState) - { - HRESULT hr = S_OK; - HRESULT hrStatus = S_OK; // Status code for marker event. - if (FlushState == DropSamples) - hrStatus = E_ABORT; - - PROPVARIANT var; - PropVariantInit(&var); - - // Get the context data. - hr = pMarker->GetContext(&var); - - if (SUCCEEDED(hr)) - hr = queueEvent(MEStreamSinkMarker, GUID_NULL, hrStatus, &var); - - PropVariantClear(&var); - return hr; - } - - HRESULT dispatchProcessSample(AsyncOperation* pOp) - { - HRESULT hr = S_OK; - Q_ASSERT(pOp != NULL); - Q_UNUSED(pOp); - hr = processSamplesFromQueue(WriteSamples); - // We are in the middle of an asynchronous operation, so if something failed, send an error. - if (FAILED(hr)) - hr = queueEvent(MEError, GUID_NULL, hr, NULL); - - return hr; - } - - HRESULT dispatchFinalize(AsyncOperation*) - { - HRESULT hr = S_OK; - // Write any samples left in the queue... - hr = processSamplesFromQueue(WriteSamples); - - // Set the async status and invoke the callback. - m_finalizeResult->SetStatus(hr); - hr = MFInvokeCallback(m_finalizeResult); - return hr; - } - - HRESULT processSampleData(IMFSample *pSample) - { - m_sampleRequested = false; - - LONGLONG time, duration = -1; - HRESULT hr = pSample->GetSampleTime(&time); - if (SUCCEEDED(hr)) - pSample->GetSampleDuration(&duration); - - if (m_prerolling) { - if (SUCCEEDED(hr) && ((time - m_prerollTargetTime) * m_rate) >= 0) { - IMFMediaBuffer *pBuffer = NULL; - hr = pSample->ConvertToContiguousBuffer(&pBuffer); - if (SUCCEEDED(hr)) { - SampleBuffer sb; - sb.m_buffer = pBuffer; - sb.m_time = time; - sb.m_duration = duration; - m_bufferCache.push_back(sb); - endPreroll(S_OK); - } - } else { - queueEvent(MEStreamSinkRequestSample, GUID_NULL, S_OK, NULL); - } - } else { - bool requestSample = true; - // If the time stamp is too early, just discard this sample. - if (SUCCEEDED(hr) && ((time - m_startTime) * m_rate) >= 0) { - IMFMediaBuffer *pBuffer = NULL; - hr = pSample->ConvertToContiguousBuffer(&pBuffer); - if (SUCCEEDED(hr)) { - SampleBuffer sb; - sb.m_buffer = pBuffer; - sb.m_time = time; - sb.m_duration = duration; - m_bufferCache.push_back(sb); - } - if (m_rate == 0) - requestSample = false; - } - schedulePresentation(requestSample); - } - return hr; - } - - class SampleBuffer - { - public: - IMFMediaBuffer *m_buffer; - LONGLONG m_time; - LONGLONG m_duration; - }; - QList<SampleBuffer> m_bufferCache; - static const int BUFFER_CACHE_SIZE = 2; - - void clearBufferCache() - { - for (SampleBuffer sb : qAsConst(m_bufferCache)) - sb.m_buffer->Release(); - m_bufferCache.clear(); - - if (m_scheduledBuffer) { - m_scheduledBuffer->Release(); - m_scheduledBuffer = NULL; - } - } - - void schedulePresentation(bool requestSample) - { - if (m_state == State_Paused || m_state == State_Prerolling) - return; - if (!m_scheduledBuffer) { - //get time from presentation time - MFTIME currentTime = m_startTime, sysTime; - bool timeOK = true; - if (m_rate != 0) { - if (FAILED(m_presentationClock->GetCorrelatedTime(0, ¤tTime, &sysTime))) - timeOK = false; - } - while (!m_bufferCache.isEmpty()) { - SampleBuffer sb = m_bufferCache.takeFirst(); - if (timeOK && ((sb.m_time - currentTime) * m_rate) < 0) { - sb.m_buffer->Release(); -#ifdef DEBUG_MEDIAFOUNDATION - qDebug() << "currentPresentTime =" << float(currentTime / 10000) * 0.001f << " and sampleTime is" << float(sb.m_time / 10000) * 0.001f; -#endif - continue; - } - m_scheduledBuffer = sb.m_buffer; - m_bufferStartTime = sb.m_time; - m_bufferDuration = sb.m_duration; - QCoreApplication::postEvent(m_rendererControl, new PresentEvent(sb.m_time)); - if (m_rate == 0) - queueEvent(MEStreamSinkScrubSampleComplete, GUID_NULL, S_OK, NULL); - break; - } - } - if (requestSample && !m_sampleRequested && m_bufferCache.size() < BUFFER_CACHE_SIZE) { - m_sampleRequested = true; - queueEvent(MEStreamSinkRequestSample, GUID_NULL, S_OK, NULL); - } - } - IMFMediaBuffer *m_scheduledBuffer; - MFTIME m_bufferStartTime; - MFTIME m_bufferDuration; - IMFPresentationClock *m_presentationClock; - bool m_sampleRequested; - float m_rate; - }; - - BOOL MediaStream::ValidStateMatrix[MediaStream::State_Count][MediaStream::Op_Count] = - { - // States: Operations: - // SetType Start Preroll, Restart Pause Stop SetRate Sample Marker Finalize - /* NotSet */ TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, - - /* Ready */ TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, - - /* Prerolling */ TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, - - /* Start */ FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, - - /* Pause */ FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, - - /* Stop */ FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, - - /*WaitForSurfaceStart*/ FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, - - /* Final */ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE - - // Note about states: - // 1. OnClockRestart should only be called from paused state. - // 2. While paused, the sink accepts samples but does not process them. - }; - - class MediaSink : public IMFFinalizableMediaSink, - public IMFClockStateSink, - public IMFMediaSinkPreroll, - public IMFGetService, - public IMFRateSupport - { - public: - MediaSink(MFVideoRendererControl *rendererControl) - : m_cRef(1) - , m_shutdown(false) - , m_presentationClock(0) - , m_playRate(1) - { - m_stream = new MediaStream(this, rendererControl); - } - - ~MediaSink() - { - Q_ASSERT(m_shutdown); - } - - void setSurface(QAbstractVideoSurface *surface) - { - QMutexLocker locker(&m_mutex); - if (m_shutdown) - return; - m_stream->setSurface(surface); - } - - void supportedFormatsChanged() - { - QMutexLocker locker(&m_mutex); - if (m_shutdown) - return; - m_stream->supportedFormatsChanged(); - } - - void present() - { - QMutexLocker locker(&m_mutex); - if (m_shutdown) - return; - m_stream->present(); - } - - void clearScheduledFrame() - { - QMutexLocker locker(&m_mutex); - if (m_shutdown) - return; - m_stream->clearScheduledFrame(); - } - - MFTIME getTime() - { - QMutexLocker locker(&m_mutex); - if (!m_presentationClock) - return 0; - MFTIME time, sysTime; - m_presentationClock->GetCorrelatedTime(0, &time, &sysTime); - return time; - } - - float getPlayRate() - { - QMutexLocker locker(&m_mutex); - return m_playRate; - } - - //from IUnknown - STDMETHODIMP QueryInterface(REFIID riid, void** ppvObject) - { - if (!ppvObject) - return E_POINTER; - if (riid == IID_IMFMediaSink) { - *ppvObject = static_cast<IMFMediaSink*>(this); - } else if (riid == IID_IMFGetService) { - *ppvObject = static_cast<IMFGetService*>(this); - } else if (riid == IID_IMFMediaSinkPreroll) { - *ppvObject = static_cast<IMFMediaSinkPreroll*>(this); - } else if (riid == IID_IMFClockStateSink) { - *ppvObject = static_cast<IMFClockStateSink*>(this); - } else if (riid == IID_IMFRateSupport) { - *ppvObject = static_cast<IMFRateSupport*>(this); - } else if (riid == IID_IUnknown) { - *ppvObject = static_cast<IUnknown*>(static_cast<IMFFinalizableMediaSink*>(this)); - } else { - *ppvObject = NULL; - return E_NOINTERFACE; - } - AddRef(); - return S_OK; - } - - STDMETHODIMP_(ULONG) AddRef(void) - { - return InterlockedIncrement(&m_cRef); - } - - STDMETHODIMP_(ULONG) Release(void) - { - LONG cRef = InterlockedDecrement(&m_cRef); - if (cRef == 0) - delete this; - // For thread safety, return a temporary variable. - return cRef; - } - - // IMFGetService methods - STDMETHODIMP GetService(const GUID &guidService, - const IID &riid, - LPVOID *ppvObject) - { - if (!ppvObject) - return E_POINTER; - - if (guidService != MF_RATE_CONTROL_SERVICE) - return MF_E_UNSUPPORTED_SERVICE; - - return QueryInterface(riid, ppvObject); - } - - //IMFMediaSinkPreroll - STDMETHODIMP NotifyPreroll(MFTIME hnsUpcomingStartTime) - { - QMutexLocker locker(&m_mutex); - if (m_shutdown) - return MF_E_SHUTDOWN; - return m_stream->startPreroll(hnsUpcomingStartTime); - } - - //from IMFFinalizableMediaSink - STDMETHODIMP BeginFinalize(IMFAsyncCallback *pCallback, IUnknown *punkState) - { - QMutexLocker locker(&m_mutex); - if (m_shutdown) - return MF_E_SHUTDOWN; - return m_stream->finalize(pCallback, punkState); - } - - STDMETHODIMP EndFinalize(IMFAsyncResult *pResult) - { - HRESULT hr = S_OK; - // Return the status code from the async result. - if (pResult == NULL) - hr = E_INVALIDARG; - else - hr = pResult->GetStatus(); - return hr; - } - - //from IMFMediaSink - STDMETHODIMP GetCharacteristics( - DWORD *pdwCharacteristics) - { - QMutexLocker locker(&m_mutex); - if (m_shutdown) - return MF_E_SHUTDOWN; - *pdwCharacteristics = MEDIASINK_FIXED_STREAMS | MEDIASINK_CAN_PREROLL; - return S_OK; - } - - STDMETHODIMP AddStreamSink( - DWORD, - IMFMediaType *, - IMFStreamSink **) - { - QMutexLocker locker(&m_mutex); - return m_shutdown ? MF_E_SHUTDOWN : MF_E_STREAMSINKS_FIXED; - } - - STDMETHODIMP RemoveStreamSink( - DWORD) - { - QMutexLocker locker(&m_mutex); - return m_shutdown ? MF_E_SHUTDOWN : MF_E_STREAMSINKS_FIXED; - } - - STDMETHODIMP GetStreamSinkCount( - DWORD *pcStreamSinkCount) - { - QMutexLocker locker(&m_mutex); - if (m_shutdown) - return MF_E_SHUTDOWN; - *pcStreamSinkCount = 1; - return S_OK; - } - - STDMETHODIMP GetStreamSinkByIndex( - DWORD dwIndex, - IMFStreamSink **ppStreamSink) - { - QMutexLocker locker(&m_mutex); - if (m_shutdown) - return MF_E_SHUTDOWN; - - if (dwIndex != 0) - return MF_E_INVALIDINDEX; - - *ppStreamSink = m_stream; - m_stream->AddRef(); - return S_OK; - } - - STDMETHODIMP GetStreamSinkById( - DWORD dwStreamSinkIdentifier, - IMFStreamSink **ppStreamSink) - { - if (ppStreamSink == NULL) - return E_INVALIDARG; - if (dwStreamSinkIdentifier != MediaStream::DEFAULT_MEDIA_STREAM_ID) - return MF_E_INVALIDSTREAMNUMBER; - - QMutexLocker locker(&m_mutex); - if (m_shutdown) - return MF_E_SHUTDOWN; - - *ppStreamSink = m_stream; - m_stream->AddRef(); - return S_OK; - } - - STDMETHODIMP SetPresentationClock( - IMFPresentationClock *pPresentationClock) - { - QMutexLocker locker(&m_mutex); - if (m_shutdown) - return MF_E_SHUTDOWN; - - if (m_presentationClock) { - m_presentationClock->RemoveClockStateSink(this); - m_presentationClock->Release(); - } - m_presentationClock = pPresentationClock; - if (m_presentationClock) { - m_presentationClock->AddRef(); - m_presentationClock->AddClockStateSink(this); - } - m_stream->setClock(m_presentationClock); - return S_OK; - } - - STDMETHODIMP GetPresentationClock( - IMFPresentationClock **ppPresentationClock) - { - QMutexLocker locker(&m_mutex); - if (m_shutdown) - return MF_E_SHUTDOWN; - *ppPresentationClock = m_presentationClock; - if (m_presentationClock) { - m_presentationClock->AddRef(); - return S_OK; - } - return MF_E_NO_CLOCK; - } - - STDMETHODIMP Shutdown(void) - { - QMutexLocker locker(&m_mutex); - if (m_shutdown) - return MF_E_SHUTDOWN; - - m_stream->shutdown(); - if (m_presentationClock) { - m_presentationClock->Release(); - m_presentationClock = NULL; - } - m_stream->Release(); - m_stream = NULL; - m_shutdown = true; - return S_OK; - } - - // IMFClockStateSink methods - STDMETHODIMP OnClockStart(MFTIME, LONGLONG llClockStartOffset) - { - QMutexLocker locker(&m_mutex); - if (m_shutdown) - return MF_E_SHUTDOWN; - return m_stream->start(llClockStartOffset); - } - - STDMETHODIMP OnClockStop(MFTIME) - { - QMutexLocker locker(&m_mutex); - if (m_shutdown) - return MF_E_SHUTDOWN; - return m_stream->stop(); - } - - STDMETHODIMP OnClockPause(MFTIME) - { - QMutexLocker locker(&m_mutex); - if (m_shutdown) - return MF_E_SHUTDOWN; - return m_stream->pause(); - } - - STDMETHODIMP OnClockRestart(MFTIME) - { - QMutexLocker locker(&m_mutex); - if (m_shutdown) - return MF_E_SHUTDOWN; - return m_stream->restart(); - } - - STDMETHODIMP OnClockSetRate(MFTIME, float flRate) - { - QMutexLocker locker(&m_mutex); - if (m_shutdown) - return MF_E_SHUTDOWN; - m_playRate = flRate; - return m_stream->setRate(flRate); - } - - // IMFRateSupport methods - STDMETHODIMP GetFastestRate(MFRATE_DIRECTION eDirection, - BOOL fThin, - float *pflRate) - { - if (!pflRate) - return E_POINTER; - - *pflRate = (fThin ? 8.f : 2.0f) * (eDirection == MFRATE_FORWARD ? 1 : -1) ; - - return S_OK; - } - - STDMETHODIMP GetSlowestRate(MFRATE_DIRECTION eDirection, - BOOL fThin, - float *pflRate) - { - Q_UNUSED(eDirection); - Q_UNUSED(fThin); - - if (!pflRate) - return E_POINTER; - - // we support any rate - *pflRate = 0.f; - - return S_OK; - } - - STDMETHODIMP IsRateSupported(BOOL fThin, - float flRate, - float *pflNearestSupportedRate) - { - HRESULT hr = S_OK; - - if (!qFuzzyIsNull(flRate)) { - MFRATE_DIRECTION direction = flRate > 0.f ? MFRATE_FORWARD - : MFRATE_REVERSE; - - float fastestRate = 0.f; - float slowestRate = 0.f; - GetFastestRate(direction, fThin, &fastestRate); - GetSlowestRate(direction, fThin, &slowestRate); - - if (direction == MFRATE_REVERSE) - qSwap(fastestRate, slowestRate); - - if (flRate < slowestRate || flRate > fastestRate) { - hr = MF_E_UNSUPPORTED_RATE; - if (pflNearestSupportedRate) { - *pflNearestSupportedRate = qBound(slowestRate, - flRate, - fastestRate); - } - } - } else if (pflNearestSupportedRate) { - *pflNearestSupportedRate = flRate; - } - - return hr; - } - - private: - long m_cRef; - QMutex m_mutex; - bool m_shutdown; - IMFPresentationClock *m_presentationClock; - MediaStream *m_stream; - float m_playRate; - }; - - class VideoRendererActivate : public IMFActivate - { - public: - VideoRendererActivate(MFVideoRendererControl *rendererControl) - : m_cRef(1) - , m_sink(0) - , m_rendererControl(rendererControl) - , m_attributes(0) - , m_surface(0) - { - MFCreateAttributes(&m_attributes, 0); - m_sink = new MediaSink(rendererControl); - } - - ~VideoRendererActivate() - { - m_attributes->Release(); - } - - //from IUnknown - STDMETHODIMP QueryInterface(REFIID riid, void** ppvObject) - { - if (!ppvObject) - return E_POINTER; - if (riid == IID_IMFActivate) { - *ppvObject = static_cast<IMFActivate*>(this); - } else if (riid == IID_IMFAttributes) { - *ppvObject = static_cast<IMFAttributes*>(this); - } else if (riid == IID_IUnknown) { - *ppvObject = static_cast<IUnknown*>(static_cast<IMFActivate*>(this)); - } else { - *ppvObject = NULL; - return E_NOINTERFACE; - } - AddRef(); - return S_OK; - } - - STDMETHODIMP_(ULONG) AddRef(void) - { - return InterlockedIncrement(&m_cRef); - } - - STDMETHODIMP_(ULONG) Release(void) - { - LONG cRef = InterlockedDecrement(&m_cRef); - if (cRef == 0) - delete this; - // For thread safety, return a temporary variable. - return cRef; - } - - //from IMFActivate - STDMETHODIMP ActivateObject(REFIID riid, void **ppv) - { - if (!ppv) - return E_INVALIDARG; - QMutexLocker locker(&m_mutex); - if (!m_sink) { - m_sink = new MediaSink(m_rendererControl); - if (m_surface) - m_sink->setSurface(m_surface); - } - return m_sink->QueryInterface(riid, ppv); - } - - STDMETHODIMP ShutdownObject(void) - { - QMutexLocker locker(&m_mutex); - HRESULT hr = S_OK; - if (m_sink) { - hr = m_sink->Shutdown(); - m_sink->Release(); - m_sink = NULL; - } - return hr; - } - - STDMETHODIMP DetachObject(void) - { - QMutexLocker locker(&m_mutex); - if (m_sink) { - m_sink->Release(); - m_sink = NULL; - } - return S_OK; - } - - //from IMFAttributes - STDMETHODIMP GetItem( - REFGUID guidKey, - PROPVARIANT *pValue) - { - return m_attributes->GetItem(guidKey, pValue); - } - - STDMETHODIMP GetItemType( - REFGUID guidKey, - MF_ATTRIBUTE_TYPE *pType) - { - return m_attributes->GetItemType(guidKey, pType); - } - - STDMETHODIMP CompareItem( - REFGUID guidKey, - REFPROPVARIANT Value, - BOOL *pbResult) - { - return m_attributes->CompareItem(guidKey, Value, pbResult); - } - - STDMETHODIMP Compare( - IMFAttributes *pTheirs, - MF_ATTRIBUTES_MATCH_TYPE MatchType, - BOOL *pbResult) - { - return m_attributes->Compare(pTheirs, MatchType, pbResult); - } - - STDMETHODIMP GetUINT32( - REFGUID guidKey, - UINT32 *punValue) - { - return m_attributes->GetUINT32(guidKey, punValue); - } - - STDMETHODIMP GetUINT64( - REFGUID guidKey, - UINT64 *punValue) - { - return m_attributes->GetUINT64(guidKey, punValue); - } - - STDMETHODIMP GetDouble( - REFGUID guidKey, - double *pfValue) - { - return m_attributes->GetDouble(guidKey, pfValue); - } - - STDMETHODIMP GetGUID( - REFGUID guidKey, - GUID *pguidValue) - { - return m_attributes->GetGUID(guidKey, pguidValue); - } - - STDMETHODIMP GetStringLength( - REFGUID guidKey, - UINT32 *pcchLength) - { - return m_attributes->GetStringLength(guidKey, pcchLength); - } - - STDMETHODIMP GetString( - REFGUID guidKey, - LPWSTR pwszValue, - UINT32 cchBufSize, - UINT32 *pcchLength) - { - return m_attributes->GetString(guidKey, pwszValue, cchBufSize, pcchLength); - } - - STDMETHODIMP GetAllocatedString( - REFGUID guidKey, - LPWSTR *ppwszValue, - UINT32 *pcchLength) - { - return m_attributes->GetAllocatedString(guidKey, ppwszValue, pcchLength); - } - - STDMETHODIMP GetBlobSize( - REFGUID guidKey, - UINT32 *pcbBlobSize) - { - return m_attributes->GetBlobSize(guidKey, pcbBlobSize); - } - - STDMETHODIMP GetBlob( - REFGUID guidKey, - UINT8 *pBuf, - UINT32 cbBufSize, - UINT32 *pcbBlobSize) - { - return m_attributes->GetBlob(guidKey, pBuf, cbBufSize, pcbBlobSize); - } - - STDMETHODIMP GetAllocatedBlob( - REFGUID guidKey, - UINT8 **ppBuf, - UINT32 *pcbSize) - { - return m_attributes->GetAllocatedBlob(guidKey, ppBuf, pcbSize); - } - - STDMETHODIMP GetUnknown( - REFGUID guidKey, - REFIID riid, - LPVOID *ppv) - { - return m_attributes->GetUnknown(guidKey, riid, ppv); - } - - STDMETHODIMP SetItem( - REFGUID guidKey, - REFPROPVARIANT Value) - { - return m_attributes->SetItem(guidKey, Value); - } - - STDMETHODIMP DeleteItem( - REFGUID guidKey) - { - return m_attributes->DeleteItem(guidKey); - } - - STDMETHODIMP DeleteAllItems(void) - { - return m_attributes->DeleteAllItems(); - } - - STDMETHODIMP SetUINT32( - REFGUID guidKey, - UINT32 unValue) - { - return m_attributes->SetUINT32(guidKey, unValue); - } - - STDMETHODIMP SetUINT64( - REFGUID guidKey, - UINT64 unValue) - { - return m_attributes->SetUINT64(guidKey, unValue); - } - - STDMETHODIMP SetDouble( - REFGUID guidKey, - double fValue) - { - return m_attributes->SetDouble(guidKey, fValue); - } - - STDMETHODIMP SetGUID( - REFGUID guidKey, - REFGUID guidValue) - { - return m_attributes->SetGUID(guidKey, guidValue); - } - - STDMETHODIMP SetString( - REFGUID guidKey, - LPCWSTR wszValue) - { - return m_attributes->SetString(guidKey, wszValue); - } - - STDMETHODIMP SetBlob( - REFGUID guidKey, - const UINT8 *pBuf, - UINT32 cbBufSize) - { - return m_attributes->SetBlob(guidKey, pBuf, cbBufSize); - } - - STDMETHODIMP SetUnknown( - REFGUID guidKey, - IUnknown *pUnknown) - { - return m_attributes->SetUnknown(guidKey, pUnknown); - } - - STDMETHODIMP LockStore(void) - { - return m_attributes->LockStore(); - } - - STDMETHODIMP UnlockStore(void) - { - return m_attributes->UnlockStore(); - } - - STDMETHODIMP GetCount( - UINT32 *pcItems) - { - return m_attributes->GetCount(pcItems); - } - - STDMETHODIMP GetItemByIndex( - UINT32 unIndex, - GUID *pguidKey, - PROPVARIANT *pValue) - { - return m_attributes->GetItemByIndex(unIndex, pguidKey, pValue); - } - - STDMETHODIMP CopyAllItems( - IMFAttributes *pDest) - { - return m_attributes->CopyAllItems(pDest); - } - - ///////////////////////////////// - void setSurface(QAbstractVideoSurface *surface) - { - QMutexLocker locker(&m_mutex); - if (m_surface == surface) - return; - - m_surface = surface; - - if (!m_sink) - return; - m_sink->setSurface(m_surface); - } - - void supportedFormatsChanged() - { - QMutexLocker locker(&m_mutex); - if (!m_sink) - return; - m_sink->supportedFormatsChanged(); - } - - void present() - { - QMutexLocker locker(&m_mutex); - if (!m_sink) - return; - m_sink->present(); - } - - void clearScheduledFrame() - { - QMutexLocker locker(&m_mutex); - if (!m_sink) - return; - m_sink->clearScheduledFrame(); - } - - MFTIME getTime() - { - if (m_sink) - return m_sink->getTime(); - return 0; - } - - float getPlayRate() - { - if (m_sink) - return m_sink->getPlayRate(); - return 1; - } - - private: - long m_cRef; - bool m_shutdown; - MediaSink *m_sink; - MFVideoRendererControl *m_rendererControl; - IMFAttributes *m_attributes; - QAbstractVideoSurface *m_surface; - QMutex m_mutex; - }; -} - - -class EVRCustomPresenterActivate : public MFAbstractActivate -{ -public: - EVRCustomPresenterActivate(); - ~EVRCustomPresenterActivate() - { } - - STDMETHODIMP ActivateObject(REFIID riid, void **ppv); - STDMETHODIMP ShutdownObject(); - STDMETHODIMP DetachObject(); - - void setSurface(QAbstractVideoSurface *surface); - -private: - EVRCustomPresenter *m_presenter; - QAbstractVideoSurface *m_surface; - QMutex m_mutex; -}; - - -MFVideoRendererControl::MFVideoRendererControl(QObject *parent) - : QVideoRendererControl(parent) - , m_surface(0) - , m_currentActivate(0) - , m_callback(0) - , m_presenterActivate(0) -{ -} - -MFVideoRendererControl::~MFVideoRendererControl() -{ - clear(); -} - -void MFVideoRendererControl::clear() -{ - if (m_surface) - m_surface->stop(); - - if (m_presenterActivate) { - m_presenterActivate->ShutdownObject(); - m_presenterActivate->Release(); - m_presenterActivate = NULL; - } - - if (m_currentActivate) { - m_currentActivate->ShutdownObject(); - m_currentActivate->Release(); - } - m_currentActivate = NULL; -} - -void MFVideoRendererControl::releaseActivate() -{ - clear(); -} - -QAbstractVideoSurface *MFVideoRendererControl::surface() const -{ - return m_surface; -} - -void MFVideoRendererControl::setSurface(QAbstractVideoSurface *surface) -{ - if (m_surface) - disconnect(m_surface, SIGNAL(supportedFormatsChanged()), this, SLOT(supportedFormatsChanged())); - m_surface = surface; - - if (m_surface) { - connect(m_surface, SIGNAL(supportedFormatsChanged()), this, SLOT(supportedFormatsChanged())); - } - - if (m_presenterActivate) - m_presenterActivate->setSurface(m_surface); - else if (m_currentActivate) - static_cast<VideoRendererActivate*>(m_currentActivate)->setSurface(m_surface); -} - -void MFVideoRendererControl::customEvent(QEvent *event) -{ - if (m_presenterActivate) - return; - - if (!m_currentActivate) - return; - - if (event->type() == MediaStream::PresentSurface) { - MFTIME targetTime = static_cast<MediaStream::PresentEvent*>(event)->targetTime(); - MFTIME currentTime = static_cast<VideoRendererActivate*>(m_currentActivate)->getTime(); - float playRate = static_cast<VideoRendererActivate*>(m_currentActivate)->getPlayRate(); - if (!qFuzzyIsNull(playRate) && targetTime != currentTime) { - // If the scheduled frame is too late, skip it - const int interval = ((targetTime - currentTime) / 10000) / playRate; - if (interval < 0) - static_cast<VideoRendererActivate*>(m_currentActivate)->clearScheduledFrame(); - else - QTimer::singleShot(interval, this, SLOT(present())); - } else { - present(); - } - return; - } - if (event->type() >= MediaStream::StartSurface) { - QChildEvent *childEvent = static_cast<QChildEvent*>(event); - static_cast<MediaStream*>(childEvent->child())->customEvent(event); - } else { - QObject::customEvent(event); - } -} - -void MFVideoRendererControl::supportedFormatsChanged() -{ - if (m_presenterActivate) - return; - - if (m_currentActivate) - static_cast<VideoRendererActivate*>(m_currentActivate)->supportedFormatsChanged(); -} - -void MFVideoRendererControl::present() -{ - if (m_presenterActivate) - return; - - if (m_currentActivate) - static_cast<VideoRendererActivate*>(m_currentActivate)->present(); -} - -IMFActivate* MFVideoRendererControl::createActivate() -{ - Q_ASSERT(m_surface); - - clear(); - - // Create the EVR media sink, but replace the presenter with our own - if (SUCCEEDED(MFCreateVideoRendererActivate(::GetShellWindow(), &m_currentActivate))) { - m_presenterActivate = new EVRCustomPresenterActivate; - m_currentActivate->SetUnknown(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE, m_presenterActivate); - } else { - m_currentActivate = new VideoRendererActivate(this); - } - - setSurface(m_surface); - - return m_currentActivate; -} - - -EVRCustomPresenterActivate::EVRCustomPresenterActivate() - : MFAbstractActivate() - , m_presenter(0) - , m_surface(0) -{ } - -HRESULT EVRCustomPresenterActivate::ActivateObject(REFIID riid, void **ppv) -{ - if (!ppv) - return E_INVALIDARG; - QMutexLocker locker(&m_mutex); - if (!m_presenter) { - m_presenter = new EVRCustomPresenter; - if (m_surface) - m_presenter->setSurface(m_surface); - } - return m_presenter->QueryInterface(riid, ppv); -} - -HRESULT EVRCustomPresenterActivate::ShutdownObject() -{ - // The presenter does not implement IMFShutdown so - // this function is the same as DetachObject() - return DetachObject(); -} - -HRESULT EVRCustomPresenterActivate::DetachObject() -{ - QMutexLocker locker(&m_mutex); - if (m_presenter) { - m_presenter->Release(); - m_presenter = 0; - } - return S_OK; -} - -void EVRCustomPresenterActivate::setSurface(QAbstractVideoSurface *surface) -{ - QMutexLocker locker(&m_mutex); - if (m_surface == surface) - return; - - m_surface = surface; - - if (m_presenter) - m_presenter->setSurface(surface); -} - -#include "moc_mfvideorenderercontrol.cpp" -#include "mfvideorenderercontrol.moc" diff --git a/src/plugins/wmf/player/mfvideorenderercontrol.h b/src/plugins/wmf/player/mfvideorenderercontrol.h deleted file mode 100644 index da9e97ba9..000000000 --- a/src/plugins/wmf/player/mfvideorenderercontrol.h +++ /dev/null @@ -1,81 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Mobility Components. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef MFVIDEORENDERERCONTROL_H -#define MFVIDEORENDERERCONTROL_H - -#include "qvideorenderercontrol.h" -#include <mfapi.h> -#include <mfidl.h> - -QT_USE_NAMESPACE - -class EVRCustomPresenterActivate; - -class MFVideoRendererControl : public QVideoRendererControl -{ - Q_OBJECT -public: - MFVideoRendererControl(QObject *parent = 0); - ~MFVideoRendererControl(); - - QAbstractVideoSurface *surface() const; - void setSurface(QAbstractVideoSurface *surface); - - IMFActivate* createActivate(); - void releaseActivate(); - -protected: - void customEvent(QEvent *event); - -private Q_SLOTS: - void supportedFormatsChanged(); - void present(); - -private: - void clear(); - - QAbstractVideoSurface *m_surface; - IMFActivate *m_currentActivate; - IMFSampleGrabberSinkCallback *m_callback; - - EVRCustomPresenterActivate *m_presenterActivate; -}; - -#endif diff --git a/src/plugins/wmf/player/player.pri b/src/plugins/wmf/player/player.pri deleted file mode 100644 index af2f7458b..000000000 --- a/src/plugins/wmf/player/player.pri +++ /dev/null @@ -1,34 +0,0 @@ -INCLUDEPATH += $$PWD - -LIBS += -lgdi32 -luser32 -QMAKE_USE += wmf - -HEADERS += \ - $$PWD/mfplayerservice.h \ - $$PWD/mfplayersession.h \ - $$PWD/mfplayercontrol.h \ - $$PWD/mfvideorenderercontrol.h \ - $$PWD/mfaudioendpointcontrol.h \ - $$PWD/mfmetadatacontrol.h \ - $$PWD/mfaudioprobecontrol.h \ - $$PWD/mfvideoprobecontrol.h \ - $$PWD/mfevrvideowindowcontrol.h \ - $$PWD/samplegrabber.h \ - $$PWD/mftvideo.h \ - $$PWD/mfactivate.h - -SOURCES += \ - $$PWD/mfplayerservice.cpp \ - $$PWD/mfplayersession.cpp \ - $$PWD/mfplayercontrol.cpp \ - $$PWD/mfvideorenderercontrol.cpp \ - $$PWD/mfaudioendpointcontrol.cpp \ - $$PWD/mfmetadatacontrol.cpp \ - $$PWD/mfaudioprobecontrol.cpp \ - $$PWD/mfvideoprobecontrol.cpp \ - $$PWD/mfevrvideowindowcontrol.cpp \ - $$PWD/samplegrabber.cpp \ - $$PWD/mftvideo.cpp \ - $$PWD/mfactivate.cpp - -include($$PWD/../../common/evr.pri) diff --git a/src/plugins/wmf/player/samplegrabber.cpp b/src/plugins/wmf/player/samplegrabber.cpp deleted file mode 100644 index d137335f3..000000000 --- a/src/plugins/wmf/player/samplegrabber.cpp +++ /dev/null @@ -1,173 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "samplegrabber.h" -#include "mfaudioprobecontrol.h" - -STDMETHODIMP SampleGrabberCallback::QueryInterface(REFIID riid, void** ppv) -{ - if (!ppv) - return E_POINTER; - if (riid == IID_IMFSampleGrabberSinkCallback) { - *ppv = static_cast<IMFSampleGrabberSinkCallback*>(this); - } else if (riid == IID_IMFClockStateSink) { - *ppv = static_cast<IMFClockStateSink*>(this); - } else if (riid == IID_IUnknown) { - *ppv = static_cast<IUnknown*>(this); - } else { - *ppv = NULL; - return E_NOINTERFACE; - } - AddRef(); - return S_OK; -} - -STDMETHODIMP_(ULONG) SampleGrabberCallback::AddRef() -{ - return InterlockedIncrement(&m_cRef); -} - -STDMETHODIMP_(ULONG) SampleGrabberCallback::Release() -{ - ULONG cRef = InterlockedDecrement(&m_cRef); - if (cRef == 0) { - delete this; - } - return cRef; - -} - -// IMFClockStateSink methods. - -STDMETHODIMP SampleGrabberCallback::OnClockStart(MFTIME hnsSystemTime, LONGLONG llClockStartOffset) -{ - Q_UNUSED(hnsSystemTime); - Q_UNUSED(llClockStartOffset); - return S_OK; -} - -STDMETHODIMP SampleGrabberCallback::OnClockStop(MFTIME hnsSystemTime) -{ - Q_UNUSED(hnsSystemTime); - return S_OK; -} - -STDMETHODIMP SampleGrabberCallback::OnClockPause(MFTIME hnsSystemTime) -{ - Q_UNUSED(hnsSystemTime); - return S_OK; -} - -STDMETHODIMP SampleGrabberCallback::OnClockRestart(MFTIME hnsSystemTime) -{ - Q_UNUSED(hnsSystemTime); - return S_OK; -} - -STDMETHODIMP SampleGrabberCallback::OnClockSetRate(MFTIME hnsSystemTime, float flRate) -{ - Q_UNUSED(hnsSystemTime); - Q_UNUSED(flRate); - return S_OK; -} - -// IMFSampleGrabberSink methods. - -STDMETHODIMP SampleGrabberCallback::OnSetPresentationClock(IMFPresentationClock* pClock) -{ - Q_UNUSED(pClock); - return S_OK; -} - -STDMETHODIMP SampleGrabberCallback::OnShutdown() -{ - return S_OK; -} - -void AudioSampleGrabberCallback::addProbe(MFAudioProbeControl* probe) -{ - QMutexLocker locker(&m_audioProbeMutex); - - if (m_audioProbes.contains(probe)) - return; - - m_audioProbes.append(probe); -} - -void AudioSampleGrabberCallback::removeProbe(MFAudioProbeControl* probe) -{ - QMutexLocker locker(&m_audioProbeMutex); - m_audioProbes.removeOne(probe); -} - -void AudioSampleGrabberCallback::setFormat(const QAudioFormat& format) -{ - m_format = format; -} - -STDMETHODIMP AudioSampleGrabberCallback::OnProcessSample(REFGUID guidMajorMediaType, DWORD dwSampleFlags, - LONGLONG llSampleTime, LONGLONG llSampleDuration, const BYTE * pSampleBuffer, - DWORD dwSampleSize) -{ - Q_UNUSED(dwSampleFlags); - Q_UNUSED(llSampleTime); - Q_UNUSED(llSampleDuration); - - if (guidMajorMediaType != GUID_NULL && guidMajorMediaType != MFMediaType_Audio) - return S_OK; - - QMutexLocker locker(&m_audioProbeMutex); - - if (m_audioProbes.isEmpty()) - return S_OK; - - // Check if sample has a presentation time - if (llSampleTime == _I64_MAX) { - // Set default QAudioBuffer start time - llSampleTime = -1; - } else { - // WMF uses 100-nanosecond units, Qt uses microseconds - llSampleTime /= 10; - } - - for (MFAudioProbeControl* probe : qAsConst(m_audioProbes)) - probe->bufferProbed((const char*)pSampleBuffer, dwSampleSize, m_format, llSampleTime); - - return S_OK; -} diff --git a/src/plugins/wmf/player/samplegrabber.h b/src/plugins/wmf/player/samplegrabber.h deleted file mode 100644 index 9ca673a1b..000000000 --- a/src/plugins/wmf/player/samplegrabber.h +++ /dev/null @@ -1,96 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef SAMPLEGRABBER_H -#define SAMPLEGRABBER_H - -#include <QtCore/qmutex.h> -#include <QtCore/qlist.h> -#include <QtMultimedia/qaudioformat.h> -#include <mfapi.h> -#include <mfidl.h> - -class MFAudioProbeControl; - -class SampleGrabberCallback : public IMFSampleGrabberSinkCallback -{ -public: - // IUnknown methods - STDMETHODIMP QueryInterface(REFIID iid, void** ppv); - STDMETHODIMP_(ULONG) AddRef(); - STDMETHODIMP_(ULONG) Release(); - - // IMFClockStateSink methods - STDMETHODIMP OnClockStart(MFTIME hnsSystemTime, LONGLONG llClockStartOffset); - STDMETHODIMP OnClockStop(MFTIME hnsSystemTime); - STDMETHODIMP OnClockPause(MFTIME hnsSystemTime); - STDMETHODIMP OnClockRestart(MFTIME hnsSystemTime); - STDMETHODIMP OnClockSetRate(MFTIME hnsSystemTime, float flRate); - - // IMFSampleGrabberSinkCallback methods - STDMETHODIMP OnSetPresentationClock(IMFPresentationClock* pClock); - STDMETHODIMP OnShutdown(); - -protected: - SampleGrabberCallback() : m_cRef(1) {} - -public: - virtual ~SampleGrabberCallback() {} - -private: - long m_cRef; -}; - -class AudioSampleGrabberCallback: public SampleGrabberCallback { -public: - void addProbe(MFAudioProbeControl* probe); - void removeProbe(MFAudioProbeControl* probe); - void setFormat(const QAudioFormat& format); - - STDMETHODIMP OnProcessSample(REFGUID guidMajorMediaType, DWORD dwSampleFlags, - LONGLONG llSampleTime, LONGLONG llSampleDuration, const BYTE * pSampleBuffer, - DWORD dwSampleSize); - -private: - QList<MFAudioProbeControl*> m_audioProbes; - QMutex m_audioProbeMutex; - QAudioFormat m_format; -}; - -#endif // SAMPLEGRABBER_H |