diff options
Diffstat (limited to 'src/plugins/directshow/player')
21 files changed, 0 insertions, 6662 deletions
diff --git a/src/plugins/directshow/player/directshowaudioendpointcontrol.cpp b/src/plugins/directshow/player/directshowaudioendpointcontrol.cpp deleted file mode 100644 index f4e45cdd8..000000000 --- a/src/plugins/directshow/player/directshowaudioendpointcontrol.cpp +++ /dev/null @@ -1,161 +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 "directshowaudioendpointcontrol.h" - -#include "directshowglobal.h" -#include "directshowplayerservice.h" - -QT_BEGIN_NAMESPACE - -DirectShowAudioEndpointControl::DirectShowAudioEndpointControl( - DirectShowPlayerService *service, QObject *parent) - : QAudioOutputSelectorControl(parent) - , m_service(service) -{ - if (CreateBindCtx(0, &m_bindContext) == S_OK) { - m_deviceEnumerator = com_new<ICreateDevEnum>(CLSID_SystemDeviceEnum); - - updateEndpoints(); - - setActiveOutput(m_defaultEndpoint); - } -} - -DirectShowAudioEndpointControl::~DirectShowAudioEndpointControl() -{ - for (IMoniker *moniker : qAsConst(m_devices)) - moniker->Release(); - - if (m_bindContext) - m_bindContext->Release(); - - if (m_deviceEnumerator) - m_deviceEnumerator->Release(); -} - -QList<QString> DirectShowAudioEndpointControl::availableOutputs() const -{ - return m_devices.keys(); -} - -QString DirectShowAudioEndpointControl::outputDescription(const QString &name) const -{ -#ifdef __IPropertyBag_INTERFACE_DEFINED__ - QString description; - - if (IMoniker *moniker = m_devices.value(name, 0)) { - IPropertyBag *propertyBag = nullptr; - if (SUCCEEDED(moniker->BindToStorage( - nullptr, nullptr, IID_IPropertyBag, reinterpret_cast<void **>(&propertyBag)))) { - VARIANT name; - VariantInit(&name); - if (SUCCEEDED(propertyBag->Read(L"FriendlyName", &name, nullptr))) - description = QString::fromWCharArray(name.bstrVal); - VariantClear(&name); - propertyBag->Release(); - } - } - - return description; -#else - return name.section(QLatin1Char('\\'), -1); -#endif -} - -QString DirectShowAudioEndpointControl::defaultOutput() const -{ - return m_defaultEndpoint; -} - -QString DirectShowAudioEndpointControl::activeOutput() const -{ - return m_activeEndpoint; -} - -void DirectShowAudioEndpointControl::setActiveOutput(const QString &name) -{ - if (m_activeEndpoint == name) - return; - - if (IMoniker *moniker = m_devices.value(name, 0)) { - IBaseFilter *filter = nullptr; - - if (moniker->BindToObject( - m_bindContext, - nullptr, - IID_IBaseFilter, - reinterpret_cast<void **>(&filter)) == S_OK) { - m_service->setAudioOutput(filter); - - filter->Release(); - } - } -} - -void DirectShowAudioEndpointControl::updateEndpoints() -{ - IMalloc *oleMalloc = nullptr; - if (m_deviceEnumerator && CoGetMalloc(1, &oleMalloc) == S_OK) { - IEnumMoniker *monikers = nullptr; - - if (m_deviceEnumerator->CreateClassEnumerator( - CLSID_AudioRendererCategory, &monikers, 0) == S_OK) { - for (IMoniker *moniker = nullptr; monikers->Next(1, &moniker, nullptr) == S_OK; moniker->Release()) { - OLECHAR *string = nullptr; - if (moniker->GetDisplayName(m_bindContext, nullptr, &string) == S_OK) { - QString deviceId = QString::fromWCharArray(string); - oleMalloc->Free(string); - - moniker->AddRef(); - m_devices.insert(deviceId, moniker); - - if (m_defaultEndpoint.isEmpty() - || deviceId.endsWith(QLatin1String("Default DirectSound Device"))) { - m_defaultEndpoint = deviceId; - } - } - } - monikers->Release(); - } - oleMalloc->Release(); - } -} - -QT_END_NAMESPACE diff --git a/src/plugins/directshow/player/directshowaudioendpointcontrol.h b/src/plugins/directshow/player/directshowaudioendpointcontrol.h deleted file mode 100644 index 05c4eb990..000000000 --- a/src/plugins/directshow/player/directshowaudioendpointcontrol.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 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 DIRECTSHOWAUDIOENDPOINTCONTROL_H -#define DIRECTSHOWAUDIOENDPOINTCONTROL_H - -#include "qaudiooutputselectorcontrol.h" - -#include <dshow.h> - -QT_BEGIN_NAMESPACE - -class DirectShowPlayerService; - -class DirectShowAudioEndpointControl : public QAudioOutputSelectorControl -{ - Q_OBJECT -public: - DirectShowAudioEndpointControl(DirectShowPlayerService *service, QObject *parent = nullptr); - ~DirectShowAudioEndpointControl() override; - - QList<QString> availableOutputs() const override; - - QString outputDescription(const QString &name) const override; - - QString defaultOutput() const override; - QString activeOutput() const override; - - void setActiveOutput(const QString& name) override; - -private: - void updateEndpoints(); - - DirectShowPlayerService *m_service; - IBindCtx *m_bindContext = nullptr; - ICreateDevEnum *m_deviceEnumerator = nullptr; - - QMap<QString, IMoniker *> m_devices; - QString m_defaultEndpoint; - QString m_activeEndpoint; -}; - -QT_END_NAMESPACE - -#endif - diff --git a/src/plugins/directshow/player/directshowevrvideowindowcontrol.cpp b/src/plugins/directshow/player/directshowevrvideowindowcontrol.cpp deleted file mode 100644 index 89bfc1467..000000000 --- a/src/plugins/directshow/player/directshowevrvideowindowcontrol.cpp +++ /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$ -** -****************************************************************************/ - -#include "directshowevrvideowindowcontrol.h" - -#include "directshowglobal.h" - -DirectShowEvrVideoWindowControl::DirectShowEvrVideoWindowControl(QObject *parent) - : EvrVideoWindowControl(parent) -{ -} - -DirectShowEvrVideoWindowControl::~DirectShowEvrVideoWindowControl() -{ - if (m_evrFilter) - m_evrFilter->Release(); -} - -IBaseFilter *DirectShowEvrVideoWindowControl::filter() -{ - if (!m_evrFilter) { - m_evrFilter = com_new<IBaseFilter>(clsid_EnhancedVideoRenderer); - if (!setEvr(m_evrFilter)) { - m_evrFilter->Release(); - m_evrFilter = nullptr; - } - } - - return m_evrFilter; -} diff --git a/src/plugins/directshow/player/directshowevrvideowindowcontrol.h b/src/plugins/directshow/player/directshowevrvideowindowcontrol.h deleted file mode 100644 index edbde78d6..000000000 --- a/src/plugins/directshow/player/directshowevrvideowindowcontrol.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 DIRECTSHOWEVRVIDEOWINDOWCONTROL_H -#define DIRECTSHOWEVRVIDEOWINDOWCONTROL_H - -#include "evrvideowindowcontrol.h" - -struct IBaseFilter; - -QT_BEGIN_NAMESPACE - -class DirectShowEvrVideoWindowControl : public EvrVideoWindowControl -{ -public: - DirectShowEvrVideoWindowControl(QObject *parent = nullptr); - ~DirectShowEvrVideoWindowControl(); - - IBaseFilter *filter(); - -private: - IBaseFilter *m_evrFilter = nullptr; -}; - -QT_END_NAMESPACE - -#endif // DIRECTSHOWEVRVIDEOWINDOWCONTROL_H diff --git a/src/plugins/directshow/player/directshowioreader.cpp b/src/plugins/directshow/player/directshowioreader.cpp deleted file mode 100644 index 3318d57b5..000000000 --- a/src/plugins/directshow/player/directshowioreader.cpp +++ /dev/null @@ -1,462 +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 "directshowioreader.h" - -#include "directshoweventloop.h" -#include "directshowglobal.h" -#include "directshowiosource.h" - -#include <QtCore/qcoreapplication.h> -#include <QtCore/qcoreevent.h> -#include <QtCore/qiodevice.h> -#include <QtCore/qthread.h> - -QT_BEGIN_NAMESPACE - -class DirectShowSampleRequest -{ -public: - DirectShowSampleRequest( - IMediaSample *sample, DWORD_PTR userData, LONGLONG position, LONG length, BYTE *buffer) - : sample(sample) - , userData(userData) - , position(position) - , length(length) - , buffer(buffer) - { - } - - DirectShowSampleRequest *remove() { DirectShowSampleRequest *n = next; delete this; return n; } - - DirectShowSampleRequest *next = nullptr; - IMediaSample *sample; - DWORD_PTR userData; - LONGLONG position; - LONG length; - BYTE *buffer; - HRESULT result = S_FALSE; -}; - -DirectShowIOReader::DirectShowIOReader( - QIODevice *device, DirectShowIOSource *source, DirectShowEventLoop *loop) - : m_source(source) - , m_device(device) - , m_loop(loop) -{ - moveToThread(device->thread()); - - connect(device, &QIODevice::readyRead, this, &DirectShowIOReader::readyRead); -} - -DirectShowIOReader::~DirectShowIOReader() -{ - flushRequests(); -} - -HRESULT DirectShowIOReader::QueryInterface(REFIID riid, void **ppvObject) -{ - return m_source->QueryInterface(riid, ppvObject); -} - -ULONG DirectShowIOReader::AddRef() -{ - return m_source->AddRef(); -} - -ULONG DirectShowIOReader::Release() -{ - return m_source->Release(); -} - -// IAsyncReader -HRESULT DirectShowIOReader::RequestAllocator( - IMemAllocator *pPreferred, ALLOCATOR_PROPERTIES *pProps, IMemAllocator **ppActual) -{ - if (!ppActual || !pProps) - return E_POINTER; - - ALLOCATOR_PROPERTIES actualProperties; - - if (pProps->cbAlign == 0) - pProps->cbAlign = 1; - - if (pPreferred && pPreferred->SetProperties(pProps, &actualProperties) == S_OK) { - pPreferred->AddRef(); - - *ppActual = pPreferred; - m_source->setAllocator(*ppActual); - return S_OK; - } - - *ppActual = com_new<IMemAllocator>(CLSID_MemoryAllocator); - if (*ppActual) { - if ((*ppActual)->SetProperties(pProps, &actualProperties) == S_OK) { - m_source->setAllocator(*ppActual); - return S_OK; - } - (*ppActual)->Release(); - } - ppActual = nullptr; - return E_FAIL; -} - -HRESULT DirectShowIOReader::Request(IMediaSample *pSample, DWORD_PTR dwUser) -{ - QMutexLocker locker(&m_mutex); - - if (!pSample) - return E_POINTER; - if (m_flushing) - return VFW_E_WRONG_STATE; - - REFERENCE_TIME startTime = 0; - REFERENCE_TIME endTime = 0; - BYTE *buffer; - - if (pSample->GetTime(&startTime, &endTime) != S_OK - || pSample->GetPointer(&buffer) != S_OK) { - return VFW_E_SAMPLE_TIME_NOT_SET; - } - LONGLONG position = startTime / 10000000; - LONG length = qMin<qint64>((endTime - startTime) / 10000000, m_availableLength); - - auto request = new DirectShowSampleRequest(pSample, dwUser, position, length, buffer); - - if (m_pendingTail) { - m_pendingTail->next = request; - } else { - m_pendingHead = request; - m_loop->postEvent(this, new QEvent(QEvent::User)); - } - m_pendingTail = request; - - return S_OK; -} - -HRESULT DirectShowIOReader::WaitForNext( - DWORD dwTimeout, IMediaSample **ppSample, DWORD_PTR *pdwUser) -{ - if (!ppSample || !pdwUser) - return E_POINTER; - - QMutexLocker locker(&m_mutex); - - do { - if (m_readyHead) { - DirectShowSampleRequest *request = m_readyHead; - - *ppSample = request->sample; - *pdwUser = request->userData; - - HRESULT hr = request->result; - - m_readyHead = request->next; - - if (!m_readyHead) - m_readyTail = nullptr; - - delete request; - - return hr; - } - if (m_flushing) { - *ppSample = nullptr; - *pdwUser = 0; - - return VFW_E_WRONG_STATE; - } - } while (m_wait.wait(&m_mutex, dwTimeout)); - - *ppSample = nullptr; - *pdwUser = 0; - - return VFW_E_TIMEOUT; -} - -HRESULT DirectShowIOReader::SyncReadAligned(IMediaSample *pSample) -{ - if (!pSample) - return E_POINTER; - - REFERENCE_TIME startTime = 0; - REFERENCE_TIME endTime = 0; - BYTE *buffer; - - if (pSample->GetTime(&startTime, &endTime) != S_OK - || pSample->GetPointer(&buffer) != S_OK) { - return VFW_E_SAMPLE_TIME_NOT_SET; - } - LONGLONG position = startTime / 10000000; - LONG length = (endTime - startTime) / 10000000; - - QMutexLocker locker(&m_mutex); - - if (thread() == QThread::currentThread()) { - qint64 bytesRead = 0; - - HRESULT hr = blockingRead(position, length, buffer, &bytesRead); - if (SUCCEEDED(hr)) - pSample->SetActualDataLength(bytesRead); - - return hr; - } - m_synchronousPosition = position; - m_synchronousLength = length; - m_synchronousBuffer = buffer; - - m_loop->postEvent(this, new QEvent(QEvent::User)); - - m_wait.wait(&m_mutex); - - m_synchronousBuffer = nullptr; - - if (SUCCEEDED(m_synchronousResult)) - pSample->SetActualDataLength(m_synchronousBytesRead); - - return m_synchronousResult; -} - -HRESULT DirectShowIOReader::SyncRead(LONGLONG llPosition, LONG lLength, BYTE *pBuffer) -{ - if (!pBuffer) - return E_POINTER; - - if (thread() == QThread::currentThread()) { - qint64 bytesRead; - return blockingRead(llPosition, lLength, pBuffer, &bytesRead); - } - QMutexLocker locker(&m_mutex); - - m_synchronousPosition = llPosition; - m_synchronousLength = lLength; - m_synchronousBuffer = pBuffer; - - m_loop->postEvent(this, new QEvent(QEvent::User)); - - m_wait.wait(&m_mutex); - - m_synchronousBuffer = nullptr; - - return m_synchronousResult; -} - -HRESULT DirectShowIOReader::Length(LONGLONG *pTotal, LONGLONG *pAvailable) -{ - if (!pTotal || !pAvailable) - return E_POINTER; - - QMutexLocker locker(&m_mutex); - *pTotal = m_totalLength; - *pAvailable = m_availableLength; - return S_OK; -} - - -HRESULT DirectShowIOReader::BeginFlush() -{ - QMutexLocker locker(&m_mutex); - - if (m_flushing) - return S_FALSE; - - m_flushing = true; - - flushRequests(); - - m_wait.wakeAll(); - - return S_OK; -} - -HRESULT DirectShowIOReader::EndFlush() -{ - QMutexLocker locker(&m_mutex); - - if (!m_flushing) - return S_FALSE; - - m_flushing = false; - - return S_OK; -} - -void DirectShowIOReader::customEvent(QEvent *event) -{ - if (event->type() == QEvent::User) { - readyRead(); - } else { - QObject::customEvent(event); - } -} - -void DirectShowIOReader::readyRead() -{ - QMutexLocker locker(&m_mutex); - - m_availableLength = m_device->bytesAvailable() + m_device->pos(); - m_totalLength = m_device->size(); - - if (m_synchronousBuffer) { - if (nonBlockingRead( - m_synchronousPosition, - m_synchronousLength, - m_synchronousBuffer, - &m_synchronousBytesRead, - &m_synchronousResult)) { - m_wait.wakeAll(); - } - } else { - qint64 bytesRead = 0; - - while (m_pendingHead && nonBlockingRead( - m_pendingHead->position, - m_pendingHead->length, - m_pendingHead->buffer, - &bytesRead, - &m_pendingHead->result)) { - m_pendingHead->sample->SetActualDataLength(bytesRead); - - if (m_readyTail) - m_readyTail->next = m_pendingHead; - m_readyTail = m_pendingHead; - - m_pendingHead = m_pendingHead->next; - - m_readyTail->next = nullptr; - - if (!m_pendingHead) - m_pendingTail = nullptr; - - if (!m_readyHead) - m_readyHead = m_readyTail; - - m_wait.wakeAll(); - } - } -} - -HRESULT DirectShowIOReader::blockingRead( - LONGLONG position, LONG length, BYTE *buffer, qint64 *bytesRead) -{ - *bytesRead = 0; - - if (qint64(position) > m_device->size()) - return S_FALSE; - - const qint64 maxSize = qMin<qint64>(m_device->size(), position + length); - - while (m_device->bytesAvailable() + m_device->pos() < maxSize) { - if (!m_device->waitForReadyRead(-1)) - return S_FALSE; - } - - if (m_device->pos() != position && !m_device->seek(position)) - return S_FALSE; - - const qint64 maxBytes = qMin<qint64>(length, m_device->bytesAvailable()); - - *bytesRead = m_device->read(reinterpret_cast<char *>(buffer), maxBytes); - - if (*bytesRead != length) { - ::memset(buffer + *bytesRead, 0, length - *bytesRead); - - return S_FALSE; - } - return S_OK; -} - -bool DirectShowIOReader::nonBlockingRead( - LONGLONG position, LONG length, BYTE *buffer, qint64 *bytesRead, HRESULT *result) -{ - const qint64 maxSize = qMin<qint64>(m_device->size(), position + length); - - if (position > m_device->size()) { - *bytesRead = 0; - *result = S_FALSE; - - return true; - } - if (m_device->bytesAvailable() + m_device->pos() >= maxSize) { - if (m_device->pos() != position && !m_device->seek(position)) { - *bytesRead = 0; - *result = S_FALSE; - - return true; - } - const qint64 maxBytes = qMin<qint64>(length, m_device->bytesAvailable()); - - *bytesRead = m_device->read(reinterpret_cast<char *>(buffer), maxBytes); - - if (*bytesRead != length) { - ::memset(buffer + *bytesRead, 0, length - *bytesRead); - - *result = S_FALSE; - } else { - *result = S_OK; - } - - return true; - } - return false; -} - -void DirectShowIOReader::flushRequests() -{ - while (m_pendingHead) { - m_pendingHead->result = VFW_E_WRONG_STATE; - - if (m_readyTail) - m_readyTail->next = m_pendingHead; - - m_readyTail = m_pendingHead; - - m_pendingHead = m_pendingHead->next; - - m_readyTail->next = nullptr; - - if (!m_pendingHead) - m_pendingTail = nullptr; - - if (!m_readyHead) - m_readyHead = m_readyTail; - } -} - -QT_END_NAMESPACE diff --git a/src/plugins/directshow/player/directshowioreader.h b/src/plugins/directshow/player/directshowioreader.h deleted file mode 100644 index a0f2d7adb..000000000 --- a/src/plugins/directshow/player/directshowioreader.h +++ /dev/null @@ -1,120 +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 DIRECTSHOWIOREADER_H -#define DIRECTSHOWIOREADER_H - -#include <dshow.h> - -#include <QtCore/qmutex.h> -#include <QtCore/qobject.h> -#include <QtCore/qwaitcondition.h> - -QT_BEGIN_NAMESPACE -class QIODevice; - -class DirectShowEventLoop; -class DirectShowIOSource; -class DirectShowSampleRequest; - -class DirectShowIOReader : public QObject, public IAsyncReader -{ - Q_OBJECT -public: - DirectShowIOReader(QIODevice *device, DirectShowIOSource *source, DirectShowEventLoop *loop); - ~DirectShowIOReader() override; - - // IUnknown - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) override; - ULONG STDMETHODCALLTYPE AddRef() override; - ULONG STDMETHODCALLTYPE Release() override; - - // IAsyncReader - HRESULT STDMETHODCALLTYPE RequestAllocator( - IMemAllocator *pPreferred, ALLOCATOR_PROPERTIES *pProps, - IMemAllocator **ppActual) override; - - HRESULT STDMETHODCALLTYPE Request(IMediaSample *pSample, DWORD_PTR dwUser) override; - - HRESULT STDMETHODCALLTYPE WaitForNext( - DWORD dwTimeout, IMediaSample **ppSample, DWORD_PTR *pdwUser) override; - - HRESULT STDMETHODCALLTYPE SyncReadAligned(IMediaSample *pSample) override; - - HRESULT STDMETHODCALLTYPE SyncRead(LONGLONG llPosition, LONG lLength, BYTE *pBuffer) override; - - HRESULT STDMETHODCALLTYPE Length(LONGLONG *pTotal, LONGLONG *pAvailable) override; - - HRESULT STDMETHODCALLTYPE BeginFlush() override; - HRESULT STDMETHODCALLTYPE EndFlush() override; - -protected: - void customEvent(QEvent *event) override; - -private Q_SLOTS: - void readyRead(); - -private: - HRESULT blockingRead(LONGLONG position, LONG length, BYTE *buffer, qint64 *bytesRead); - bool nonBlockingRead( - LONGLONG position, LONG length, BYTE *buffer, qint64 *bytesRead, HRESULT *result); - void flushRequests(); - - DirectShowIOSource *m_source; - QIODevice *m_device; - DirectShowEventLoop *m_loop; - DirectShowSampleRequest *m_pendingHead = nullptr; - DirectShowSampleRequest *m_pendingTail = nullptr; - DirectShowSampleRequest *m_readyHead = nullptr; - DirectShowSampleRequest *m_readyTail = nullptr; - LONGLONG m_synchronousPosition = 0; - LONG m_synchronousLength = 0; - qint64 m_synchronousBytesRead = 0; - BYTE *m_synchronousBuffer = nullptr; - HRESULT m_synchronousResult = S_OK; - LONGLONG m_totalLength = 0; - LONGLONG m_availableLength = 0; - bool m_flushing = false; - QMutex m_mutex; - QWaitCondition m_wait; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/plugins/directshow/player/directshowiosource.cpp b/src/plugins/directshow/player/directshowiosource.cpp deleted file mode 100644 index 54c043c17..000000000 --- a/src/plugins/directshow/player/directshowiosource.cpp +++ /dev/null @@ -1,530 +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 "directshowiosource.h" - -#include "directshowglobal.h" -#include "directshowmediatype.h" -#include "directshowmediatypeenum.h" -#include "directshowpinenum.h" - -#include <QtCore/qcoreapplication.h> -#include <QtCore/qurl.h> - -QT_BEGIN_NAMESPACE - -static const GUID directshow_subtypes[] = -{ - MEDIASUBTYPE_NULL, - MEDIASUBTYPE_Avi, - MEDIASUBTYPE_Asf, - MEDIASUBTYPE_MPEG1Video, - MEDIASUBTYPE_QTMovie, - MEDIASUBTYPE_WAVE, - MEDIASUBTYPE_AIFF, - MEDIASUBTYPE_AU, - MEDIASUBTYPE_DssVideo, - MEDIASUBTYPE_MPEG1Audio, - MEDIASUBTYPE_MPEG1System, - MEDIASUBTYPE_MPEG1VideoCD -}; - -DirectShowIOSource::DirectShowIOSource(DirectShowEventLoop *loop) - : m_loop(loop) -{ - // This filter has only one possible output type, that is, a stream of data - // with no particular subtype. The graph builder will try every demux/decode filters - // to find one able to decode the stream. - // - // The filter works in pull mode, the downstream filter is responsible for requesting - // samples from this one. - // - AM_MEDIA_TYPE type - { - MEDIATYPE_Stream, // majortype - MEDIASUBTYPE_NULL, // subtype - TRUE, // bFixedSizeSamples - FALSE, // bTemporalCompression - 1, // lSampleSize - GUID_NULL, // formattype - nullptr, // pUnk - 0, // cbFormat - nullptr, // pbFormat - }; - - for (const auto &directshowSubtype : directshow_subtypes) { - type.subtype = directshowSubtype; - m_supportedMediaTypes.append(DirectShowMediaType(type)); - } -} - -DirectShowIOSource::~DirectShowIOSource() -{ - Q_ASSERT(m_ref == 0); - - delete m_reader; -} - -void DirectShowIOSource::setDevice(QIODevice *device) -{ - Q_ASSERT(!m_reader); - - m_reader = new DirectShowIOReader(device, this, m_loop); -} - -void DirectShowIOSource::setAllocator(IMemAllocator *allocator) -{ - if (m_allocator == allocator) - return; - - if (m_allocator) - m_allocator->Release(); - - m_allocator = allocator; - - if (m_allocator) - m_allocator->AddRef(); -} - -// IUnknown -HRESULT DirectShowIOSource::QueryInterface(REFIID riid, void **ppvObject) -{ - // 2dd74950-a890-11d1-abe8-00a0c905f375 - static const GUID iid_IAmFilterMiscFlags = { - 0x2dd74950, 0xa890, 0x11d1, {0xab, 0xe8, 0x00, 0xa0, 0xc9, 0x05, 0xf3, 0x75}}; - - if (!ppvObject) - return E_POINTER; - - if (riid == IID_IUnknown || riid == IID_IPersist || riid == IID_IMediaFilter - || riid == IID_IBaseFilter) { - *ppvObject = static_cast<IBaseFilter *>(this); - } else if (riid == iid_IAmFilterMiscFlags) { - *ppvObject = static_cast<IAMFilterMiscFlags *>(this); - } else if (riid == IID_IPin) { - *ppvObject = static_cast<IPin *>(this); - } else if (riid == IID_IAsyncReader) { - m_queriedForAsyncReader = true; - *ppvObject = static_cast<IAsyncReader *>(m_reader); - } else { - *ppvObject = nullptr; - - return E_NOINTERFACE; - } - - AddRef(); - - return S_OK; -} - -ULONG DirectShowIOSource::AddRef() -{ - return InterlockedIncrement(&m_ref); -} - -ULONG DirectShowIOSource::Release() -{ - ULONG ref = InterlockedDecrement(&m_ref); - - if (ref == 0) { - delete this; - } - - return ref; -} - -// IPersist -HRESULT DirectShowIOSource::GetClassID(CLSID *pClassID) -{ - *pClassID = CLSID_NULL; - - return S_OK; -} - -// IMediaFilter -HRESULT DirectShowIOSource::Run(REFERENCE_TIME tStart) -{ - Q_UNUSED(tStart); - QMutexLocker locker(&m_mutex); - - m_state = State_Running; - - return S_OK; -} - -HRESULT DirectShowIOSource::Pause() -{ - QMutexLocker locker(&m_mutex); - - m_state = State_Paused; - - return S_OK; -} - -HRESULT DirectShowIOSource::Stop() -{ - QMutexLocker locker(&m_mutex); - - m_state = State_Stopped; - - return S_OK; -} - -HRESULT DirectShowIOSource::GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *pState) -{ - Q_UNUSED(dwMilliSecsTimeout); - - if (!pState) - return E_POINTER; - - QMutexLocker locker(&m_mutex); - *pState = m_state; - return S_OK; -} - -HRESULT DirectShowIOSource::SetSyncSource(IReferenceClock *pClock) -{ - QMutexLocker locker(&m_mutex); - - if (m_clock) - m_clock->Release(); - - m_clock = pClock; - - if (m_clock) - m_clock->AddRef(); - - return S_OK; -} - -HRESULT DirectShowIOSource::GetSyncSource(IReferenceClock **ppClock) -{ - if (!ppClock) - return E_POINTER; - - if (!m_clock) { - *ppClock = nullptr; - return S_FALSE; - } - m_clock->AddRef(); - *ppClock = m_clock; - return S_OK; -} - -// IBaseFilter -HRESULT DirectShowIOSource::EnumPins(IEnumPins **ppEnum) -{ - if (!ppEnum) - return E_POINTER; - - *ppEnum = new DirectShowPinEnum(QList<IPin *>() << this); - return S_OK; -} - -HRESULT DirectShowIOSource::FindPin(LPCWSTR Id, IPin **ppPin) -{ - if (!ppPin || !Id) - return E_POINTER; - - QMutexLocker locker(&m_mutex); - if (m_pinId == QStringView(Id)) { - AddRef(); - *ppPin = this; - return S_OK; - } - *ppPin = nullptr; - return VFW_E_NOT_FOUND; -} - -HRESULT DirectShowIOSource::JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName) -{ - QMutexLocker locker(&m_mutex); - - m_graph = pGraph; - m_filterName = QString::fromWCharArray(pName); - - return S_OK; -} - -HRESULT DirectShowIOSource::QueryFilterInfo(FILTER_INFO *pInfo) -{ - if (!pInfo) - return E_POINTER; - - QString name = m_filterName; - if (name.length() >= MAX_FILTER_NAME) - name.truncate(MAX_FILTER_NAME - 1); - - int length = name.toWCharArray(pInfo->achName); - pInfo->achName[length] = '\0'; - - if (m_graph) - m_graph->AddRef(); - - pInfo->pGraph = m_graph; - - return S_OK; -} - -HRESULT DirectShowIOSource::QueryVendorInfo(LPWSTR *pVendorInfo) -{ - Q_UNUSED(pVendorInfo); - - return E_NOTIMPL; -} - -// IAMFilterMiscFlags -ULONG DirectShowIOSource::GetMiscFlags() -{ - return AM_FILTER_MISC_FLAGS_IS_SOURCE; -} - -// IPin -HRESULT DirectShowIOSource::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt) -{ - if (!pReceivePin) - return E_POINTER; - - QMutexLocker locker(&m_mutex); - - if (m_state != State_Stopped) - return VFW_E_NOT_STOPPED; - - if (m_peerPin) - return VFW_E_ALREADY_CONNECTED; - - // If we get a type from the graph manager, check that we support that - if (pmt && pmt->majortype != MEDIATYPE_Stream) - return VFW_E_TYPE_NOT_ACCEPTED; - - // This filter only works in pull mode, the downstream filter must query for the - // AsyncReader interface during ReceiveConnection(). - // If it doesn't, we can't connect to it. - m_queriedForAsyncReader = false; - HRESULT hr = 0; - // Negotiation of media type - // - Complete'ish type (Stream with subtype specified). - if (pmt && pmt->subtype != MEDIASUBTYPE_NULL /* aka. GUID_NULL */) { - hr = pReceivePin->ReceiveConnection(this, pmt); - // Update the media type for the current connection. - if (SUCCEEDED(hr)) - DirectShowMediaType::copy(&m_connectionMediaType, pmt); - } else if (pmt && pmt->subtype == MEDIATYPE_NULL) { // - Partial type (Stream, but no subtype specified). - DirectShowMediaType::copy(&m_connectionMediaType, pmt); - // Check if the receiving pin accepts any of the streaming subtypes. - for (const DirectShowMediaType &t : qAsConst(m_supportedMediaTypes)) { - m_connectionMediaType->subtype = t->subtype; - hr = pReceivePin->ReceiveConnection(this, &m_connectionMediaType); - if (SUCCEEDED(hr)) - break; - } - } else { // - No media type specified. - // Check if the receiving pin accepts any of the streaming types. - for (const DirectShowMediaType &t : qAsConst(m_supportedMediaTypes)) { - hr = pReceivePin->ReceiveConnection(this, &t); - if (SUCCEEDED(hr)) { - m_connectionMediaType = t; - break; - } - } - } - - if (SUCCEEDED(hr) && m_queriedForAsyncReader) { - m_peerPin = pReceivePin; - m_peerPin->AddRef(); - } else { - pReceivePin->Disconnect(); - if (m_allocator) { - m_allocator->Release(); - m_allocator = nullptr; - } - if (!m_queriedForAsyncReader) - hr = VFW_E_NO_TRANSPORT; - - m_connectionMediaType.clear(); - } - - return hr; -} - -HRESULT DirectShowIOSource::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt) -{ - Q_UNUSED(pConnector); - Q_UNUSED(pmt); - // Output pin. - return E_NOTIMPL; -} - -HRESULT DirectShowIOSource::Disconnect() -{ - QMutexLocker locker(&m_mutex); - - if (!m_peerPin) - return S_FALSE; - if (m_state != State_Stopped) - return VFW_E_NOT_STOPPED; - - HRESULT hr = m_peerPin->Disconnect(); - if (!SUCCEEDED(hr)) - return hr; - - if (m_allocator) { - m_allocator->Release(); - m_allocator = nullptr; - } - - m_peerPin->Release(); - m_peerPin = nullptr; - - return S_OK; -} - -HRESULT DirectShowIOSource::ConnectedTo(IPin **ppPin) -{ - if (!ppPin) - return E_POINTER; - - QMutexLocker locker(&m_mutex); - if (!m_peerPin) { - *ppPin = nullptr; - return VFW_E_NOT_CONNECTED; - } - m_peerPin->AddRef(); - *ppPin = m_peerPin; - return S_OK; -} - -HRESULT DirectShowIOSource::ConnectionMediaType(AM_MEDIA_TYPE *pmt) -{ - if (!pmt) - return E_POINTER; - - QMutexLocker locker(&m_mutex); - if (!m_peerPin) { - pmt = nullptr; - return VFW_E_NOT_CONNECTED; - } - DirectShowMediaType::copy(pmt, &m_connectionMediaType); - return S_OK; -} - -HRESULT DirectShowIOSource::QueryPinInfo(PIN_INFO *pInfo) -{ - if (!pInfo) - return E_POINTER; - - AddRef(); - - pInfo->pFilter = this; - pInfo->dir = PINDIR_OUTPUT; - - const int bytes = qMin(MAX_FILTER_NAME, (m_pinId.length() + 1) * 2); - - ::memcpy(pInfo->achName, m_pinId.utf16(), bytes); - - return S_OK; -} - -HRESULT DirectShowIOSource::QueryId(LPWSTR *Id) -{ - if (!Id) - return E_POINTER; - - const int bytes = (m_pinId.length() + 1) * 2; - *Id = static_cast<LPWSTR>(::CoTaskMemAlloc(bytes)); - ::memcpy(*Id, m_pinId.utf16(), bytes); - return S_OK; -} - -HRESULT DirectShowIOSource::QueryAccept(const AM_MEDIA_TYPE *pmt) -{ - if (!pmt) - return E_POINTER; - return pmt->majortype == MEDIATYPE_Stream ? S_OK : S_FALSE; -} - -HRESULT DirectShowIOSource::EnumMediaTypes(IEnumMediaTypes **ppEnum) -{ - if (!ppEnum) - return E_POINTER; - *ppEnum = new DirectShowMediaTypeEnum(m_supportedMediaTypes); - return S_OK; -} - -HRESULT DirectShowIOSource::QueryInternalConnections(IPin **apPin, ULONG *nPin) -{ - Q_UNUSED(apPin); - Q_UNUSED(nPin); - - return E_NOTIMPL; -} - -HRESULT DirectShowIOSource::EndOfStream() -{ - return S_OK; -} - -HRESULT DirectShowIOSource::BeginFlush() -{ - return m_reader->BeginFlush(); -} - -HRESULT DirectShowIOSource::EndFlush() -{ - return m_reader->EndFlush(); -} - -HRESULT DirectShowIOSource::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate) -{ - Q_UNUSED(tStart); - Q_UNUSED(tStop); - Q_UNUSED(dRate); - - return S_OK; -} - -HRESULT DirectShowIOSource::QueryDirection(PIN_DIRECTION *pPinDir) -{ - if (!pPinDir) - return E_POINTER; - *pPinDir = PINDIR_OUTPUT; - return S_OK; -} - -QT_END_NAMESPACE diff --git a/src/plugins/directshow/player/directshowiosource.h b/src/plugins/directshow/player/directshowiosource.h deleted file mode 100644 index 837842518..000000000 --- a/src/plugins/directshow/player/directshowiosource.h +++ /dev/null @@ -1,140 +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 DIRECTSHOWIOSOURCE_H -#define DIRECTSHOWIOSOURCE_H - -#include "directshowglobal.h" -#include "directshowioreader.h" -#include "directshowmediatype.h" - -#include <QtCore/qfile.h> - -QT_BEGIN_NAMESPACE - -class DirectShowIOSource - : public IBaseFilter - , public IAMFilterMiscFlags - , public IPin -{ - Q_DISABLE_COPY(DirectShowIOSource) -public: - DirectShowIOSource(DirectShowEventLoop *loop); - virtual ~DirectShowIOSource(); - - void setDevice(QIODevice *device); - void setAllocator(IMemAllocator *allocator); - - // IUnknown - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) override; - ULONG STDMETHODCALLTYPE AddRef() override; - ULONG STDMETHODCALLTYPE Release() override; - - // IPersist - HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID) override; - - // IMediaFilter - HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME tStart) override; - HRESULT STDMETHODCALLTYPE Pause() override; - HRESULT STDMETHODCALLTYPE Stop() override; - - HRESULT STDMETHODCALLTYPE GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *pState) override; - - HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock *pClock) override; - HRESULT STDMETHODCALLTYPE GetSyncSource(IReferenceClock **ppClock) override; - - // IBaseFilter - HRESULT STDMETHODCALLTYPE EnumPins(IEnumPins **ppEnum) override; - HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR Id, IPin **ppPin) override; - - HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName) override; - - HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO *pInfo) override; - HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR *pVendorInfo) override; - - // IAMFilterMiscFlags - ULONG STDMETHODCALLTYPE GetMiscFlags() override; - - // IPin - HRESULT STDMETHODCALLTYPE Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt) override; - HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt) override; - HRESULT STDMETHODCALLTYPE Disconnect() override; - HRESULT STDMETHODCALLTYPE ConnectedTo(IPin **ppPin) override; - - HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE *pmt) override; - - HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO *pInfo) override; - HRESULT STDMETHODCALLTYPE QueryId(LPWSTR *Id) override; - - HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE *pmt) override; - - HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes **ppEnum) override; - - HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin **apPin, ULONG *nPin) override; - - HRESULT STDMETHODCALLTYPE EndOfStream() override; - - HRESULT STDMETHODCALLTYPE BeginFlush() override; - HRESULT STDMETHODCALLTYPE EndFlush() override; - - HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, - double dRate) override; - - HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION *pPinDir) override; - -private: - volatile LONG m_ref = 1; - FILTER_STATE m_state = State_Stopped; - DirectShowIOReader *m_reader = nullptr; - DirectShowEventLoop *m_loop; - IFilterGraph *m_graph = nullptr; - IReferenceClock *m_clock = nullptr; - IMemAllocator *m_allocator = nullptr; - IPin *m_peerPin = nullptr; - DirectShowMediaType m_connectionMediaType; - QList<DirectShowMediaType> m_supportedMediaTypes; - QString m_filterName; - const QString m_pinId = QLatin1String("Data"); - bool m_queriedForAsyncReader = false; - QMutex m_mutex; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/plugins/directshow/player/directshowmetadatacontrol.cpp b/src/plugins/directshow/player/directshowmetadatacontrol.cpp deleted file mode 100644 index 61138951c..000000000 --- a/src/plugins/directshow/player/directshowmetadatacontrol.cpp +++ /dev/null @@ -1,697 +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 <dshow.h> -#ifdef min -#undef min -#endif -#ifdef max -#undef max -#endif - -#include <QtMultimedia/qmediametadata.h> -#include <QtCore/qcoreapplication.h> -#include <QSize> -#include <qdatetime.h> -#include <qimage.h> - -#include <initguid.h> -#include <qnetwork.h> - -#include "directshowmetadatacontrol.h" -#include "directshowplayerservice.h" - -#include <QtMultimedia/private/qtmultimedia-config_p.h> - -#if QT_CONFIG(wmsdk) -#include <wmsdk.h> -#endif - -#if QT_CONFIG(wshellitem) -#include <shlobj.h> -#include <propkeydef.h> -#include <private/qsystemlibrary_p.h> - -DEFINE_PROPERTYKEY(PKEY_Author, 0xF29F85E0, 0x4FF9, 0x1068, 0xAB, 0x91, 0x08, 0x00, 0x2B, 0x27, 0xB3, 0xD9, 4); -DEFINE_PROPERTYKEY(PKEY_Title, 0xF29F85E0, 0x4FF9, 0x1068, 0xAB, 0x91, 0x08, 0x00, 0x2B, 0x27, 0xB3, 0xD9, 2); -DEFINE_PROPERTYKEY(PKEY_Media_SubTitle, 0x56A3372E, 0xCE9C, 0x11D2, 0x9F, 0x0E, 0x00, 0x60, 0x97, 0xC6, 0x86, 0xF6, 38); -DEFINE_PROPERTYKEY(PKEY_ParentalRating, 0x64440492, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 21); -DEFINE_PROPERTYKEY(PKEY_Comment, 0xF29F85E0, 0x4FF9, 0x1068, 0xAB, 0x91, 0x08, 0x00, 0x2B, 0x27, 0xB3, 0xD9, 6); -DEFINE_PROPERTYKEY(PKEY_Copyright, 0x64440492, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 11); -DEFINE_PROPERTYKEY(PKEY_Media_ProviderStyle, 0x64440492, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 40); -DEFINE_PROPERTYKEY(PKEY_Media_Year, 0x56A3372E, 0xCE9C, 0x11D2, 0x9F, 0x0E, 0x00, 0x60, 0x97, 0xC6, 0x86, 0xF6, 5); -DEFINE_PROPERTYKEY(PKEY_Media_DateEncoded, 0x2E4B640D, 0x5019, 0x46D8, 0x88, 0x81, 0x55, 0x41, 0x4C, 0xC5, 0xCA, 0xA0, 100); -DEFINE_PROPERTYKEY(PKEY_Rating, 0x64440492, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 9); -DEFINE_PROPERTYKEY(PKEY_Keywords, 0xF29F85E0, 0x4FF9, 0x1068, 0xAB, 0x91, 0x08, 0x00, 0x2B, 0x27, 0xB3, 0xD9, 5); -DEFINE_PROPERTYKEY(PKEY_Language, 0xD5CDD502, 0x2E9C, 0x101B, 0x93, 0x97, 0x08, 0x00, 0x2B, 0x2C, 0xF9, 0xAE, 28); -DEFINE_PROPERTYKEY(PKEY_Media_Publisher, 0x64440492, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 30); -DEFINE_PROPERTYKEY(PKEY_Media_Duration, 0x64440490, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 3); -DEFINE_PROPERTYKEY(PKEY_Audio_EncodingBitrate, 0x64440490, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 4); -DEFINE_PROPERTYKEY(PKEY_Media_AverageLevel, 0x09EDD5B6, 0xB301, 0x43C5, 0x99, 0x90, 0xD0, 0x03, 0x02, 0xEF, 0xFD, 0x46, 100); -DEFINE_PROPERTYKEY(PKEY_Audio_ChannelCount, 0x64440490, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 7); -DEFINE_PROPERTYKEY(PKEY_Audio_PeakValue, 0x2579E5D0, 0x1116, 0x4084, 0xBD, 0x9A, 0x9B, 0x4F, 0x7C, 0xB4, 0xDF, 0x5E, 100); -DEFINE_PROPERTYKEY(PKEY_Audio_SampleRate, 0x64440490, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 5); -DEFINE_PROPERTYKEY(PKEY_Audio_Format, 0x64440490, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 2); -DEFINE_PROPERTYKEY(PKEY_Music_AlbumTitle, 0x56A3372E, 0xCE9C, 0x11D2, 0x9F, 0x0E, 0x00, 0x60, 0x97, 0xC6, 0x86, 0xF6, 4); -DEFINE_PROPERTYKEY(PKEY_Music_AlbumArtist, 0x56A3372E, 0xCE9C, 0x11D2, 0x9F, 0x0E, 0x00, 0x60, 0x97, 0xC6, 0x86, 0xF6, 13); -DEFINE_PROPERTYKEY(PKEY_Music_Artist, 0x56A3372E, 0xCE9C, 0x11D2, 0x9F, 0x0E, 0x00, 0x60, 0x97, 0xC6, 0x86, 0xF6, 2); -DEFINE_PROPERTYKEY(PKEY_Music_Composer, 0x64440492, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 19); -DEFINE_PROPERTYKEY(PKEY_Music_Conductor, 0x56A3372E, 0xCE9C, 0x11D2, 0x9F, 0x0E, 0x00, 0x60, 0x97, 0xC6, 0x86, 0xF6, 36); -DEFINE_PROPERTYKEY(PKEY_Music_Lyrics, 0x56A3372E, 0xCE9C, 0x11D2, 0x9F, 0x0E, 0x00, 0x60, 0x97, 0xC6, 0x86, 0xF6, 12); -DEFINE_PROPERTYKEY(PKEY_Music_Mood, 0x56A3372E, 0xCE9C, 0x11D2, 0x9F, 0x0E, 0x00, 0x60, 0x97, 0xC6, 0x86, 0xF6, 39); -DEFINE_PROPERTYKEY(PKEY_Music_TrackNumber, 0x56A3372E, 0xCE9C, 0x11D2, 0x9F, 0x0E, 0x00, 0x60, 0x97, 0xC6, 0x86, 0xF6, 7); -DEFINE_PROPERTYKEY(PKEY_Music_Genre, 0x56A3372E, 0xCE9C, 0x11D2, 0x9F, 0x0E, 0x00, 0x60, 0x97, 0xC6, 0x86, 0xF6, 11); -DEFINE_PROPERTYKEY(PKEY_ThumbnailStream, 0xF29F85E0, 0x4FF9, 0x1068, 0xAB, 0x91, 0x08, 0x00, 0x2B, 0x27, 0xB3, 0xD9, 27); -DEFINE_PROPERTYKEY(PKEY_Video_FrameHeight, 0x64440491, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 4); -DEFINE_PROPERTYKEY(PKEY_Video_FrameWidth, 0x64440491, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 3); -DEFINE_PROPERTYKEY(PKEY_Video_HorizontalAspectRatio, 0x64440491, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 42); -DEFINE_PROPERTYKEY(PKEY_Video_VerticalAspectRatio, 0x64440491, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 45); -DEFINE_PROPERTYKEY(PKEY_Video_FrameRate, 0x64440491, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 6); -DEFINE_PROPERTYKEY(PKEY_Video_EncodingBitrate, 0x64440491, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 8); -DEFINE_PROPERTYKEY(PKEY_Video_Director, 0x64440492, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 20); -DEFINE_PROPERTYKEY(PKEY_Video_Compression, 0x64440491, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 10); -DEFINE_PROPERTYKEY(PKEY_Media_Writer, 0x64440492, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 23); - -static QString nameForGUIDString(const QString &guid) -{ - // Audio formats - if (guid == "{00001610-0000-0010-8000-00AA00389B71}" || guid == "{000000FF-0000-0010-8000-00AA00389B71}") - return QStringLiteral("MPEG AAC Audio"); - if (guid == "{00001600-0000-0010-8000-00AA00389B71}") - return QStringLiteral("MPEG ADTS AAC Audio"); - if (guid == "{00000092-0000-0010-8000-00AA00389B71}") - return QStringLiteral("Dolby AC-3 SPDIF"); - if (guid == "{E06D802C-DB46-11CF-B4D1-00805F6CBBEA}" || guid == "{00002000-0000-0010-8000-00AA00389B71}") - return QStringLiteral("Dolby AC-3"); - if (guid == "{A7FB87AF-2D02-42FB-A4D4-05CD93843BDD}") - return QStringLiteral("Dolby Digital Plus"); - if (guid == "{00000009-0000-0010-8000-00AA00389B71}") - return QStringLiteral("DRM"); - if (guid == "{00000008-0000-0010-8000-00AA00389B71}") - return QStringLiteral("Digital Theater Systems Audio (DTS)"); - if (guid == "{00000003-0000-0010-8000-00AA00389B71}") - return QStringLiteral("IEEE Float Audio"); - if (guid == "{00000055-0000-0010-8000-00AA00389B71}") - return QStringLiteral("MPEG Audio Layer-3 (MP3)"); - if (guid == "{00000050-0000-0010-8000-00AA00389B71}") - return QStringLiteral("MPEG-1 Audio"); - if (guid == "{2E6D7033-767A-494D-B478-F29D25DC9037}") - return QStringLiteral("MPEG Audio Layer 1/2"); - if (guid == "{0000000A-0000-0010-8000-00AA00389B71}") - return QStringLiteral("Windows Media Audio Voice"); - if (guid == "{00000001-0000-0010-8000-00AA00389B71}") - return QStringLiteral("Uncompressed PCM Audio"); - if (guid == "{00000164-0000-0010-8000-00AA00389B71}") - return QStringLiteral("Windows Media Audio 9 SPDIF"); - if (guid == "{00000161-0000-0010-8000-00AA00389B71}") - return QStringLiteral("Windows Media Audio 8 (WMA2)"); - if (guid == "{00000162-0000-0010-8000-00AA00389B71}") - return QStringLiteral("Windows Media Audio 9 (WMA3"); - if (guid == "{00000163-0000-0010-8000-00AA00389B71}") - return QStringLiteral("Windows Media Audio 9 Lossless"); - if (guid == "{8D2FD10B-5841-4a6b-8905-588FEC1ADED9}") - return QStringLiteral("Vorbis"); - if (guid == "{0000F1AC-0000-0010-8000-00AA00389B71}") - return QStringLiteral("Free Lossless Audio Codec (FLAC)"); - if (guid == "{00006C61-0000-0010-8000-00AA00389B71}") - return QStringLiteral("Apple Lossless Audio Codec (ALAC)"); - - // Video formats - if (guid == "{35327664-0000-0010-8000-00AA00389B71}") - return QStringLiteral("DVCPRO 25 (DV25)"); - if (guid == "{30357664-0000-0010-8000-00AA00389B71}") - return QStringLiteral("DVCPRO 50 (DV50)"); - if (guid == "{20637664-0000-0010-8000-00AA00389B71}") - return QStringLiteral("DVC/DV Video"); - if (guid == "{31687664-0000-0010-8000-00AA00389B71}") - return QStringLiteral("DVCPRO 100 (DVH1)"); - if (guid == "{64687664-0000-0010-8000-00AA00389B71}") - return QStringLiteral("HD-DVCR (DVHD)"); - if (guid == "{64737664-0000-0010-8000-00AA00389B71}") - return QStringLiteral("SDL-DVCR (DVSD)"); - if (guid == "{6C737664-0000-0010-8000-00AA00389B71}") - return QStringLiteral("SD-DVCR (DVSL)"); - if (guid == "{33363248-0000-0010-8000-00AA00389B71}") - return QStringLiteral("H.263 Video"); - if (guid == "{34363248-0000-0010-8000-00AA00389B71}") - return QStringLiteral("H.264 Video"); - if (guid == "{35363248-0000-0010-8000-00AA00389B71}") - return QStringLiteral("H.265 Video"); - if (guid == "{43564548-0000-0010-8000-00AA00389B71}") - return QStringLiteral("High Efficiency Video Coding (HEVC)"); - if (guid == "{3253344D-0000-0010-8000-00AA00389B71}") - return QStringLiteral("MPEG-4 part 2 Video (M4S2)"); - if (guid == "{47504A4D-0000-0010-8000-00AA00389B71}") - return QStringLiteral("Motion JPEG (MJPG)"); - if (guid == "{3334504D-0000-0010-8000-00AA00389B71}") - return QStringLiteral("Microsoft MPEG 4 version 3 (MP43)"); - if (guid == "{5334504D-0000-0010-8000-00AA00389B71}") - return QStringLiteral("ISO MPEG 4 version 1 (MP4S)"); - if (guid == "{5634504D-0000-0010-8000-00AA00389B71}") - return QStringLiteral("MPEG-4 part 2 Video (MP4V)"); - if (guid == "{E06D8026-DB46-11CF-B4D1-00805F6CBBEA}") - return QStringLiteral("MPEG-2 Video"); - if (guid == "{3147504D-0000-0010-8000-00AA00389B71}") - return QStringLiteral("MPEG-1 Video"); - if (guid == "{3153534D-0000-0010-8000-00AA00389B71}") - return QStringLiteral("Windows Media Screen 1 (MSS1)"); - if (guid == "{3253534D-0000-0010-8000-00AA00389B71}") - return QStringLiteral("Windows Media Video 9 Screen (MSS2)"); - if (guid == "{31564D57-0000-0010-8000-00AA00389B71}") - return QStringLiteral("Windows Media Video 7 (WMV1)"); - if (guid == "{32564D57-0000-0010-8000-00AA00389B71}") - return QStringLiteral("Windows Media Video 8 (WMV2)"); - if (guid == "{33564D57-0000-0010-8000-00AA00389B71}") - return QStringLiteral("Windows Media Video 9 (WMV3)"); - if (guid == "{31435657-0000-0010-8000-00AA00389B71}") - return QStringLiteral("Windows Media Video VC1 (WVC1)"); - if (guid == "{30385056-0000-0010-8000-00AA00389B71}") - return QStringLiteral("VP8 Video"); - if (guid == "{30395056-0000-0010-8000-00AA00389B71}") - return QStringLiteral("VP9 Video"); - return QStringLiteral("Unknown codec"); -} - -typedef HRESULT (WINAPI *q_SHCreateItemFromParsingName)(PCWSTR, IBindCtx *, const GUID&, void **); -static q_SHCreateItemFromParsingName sHCreateItemFromParsingName = nullptr; -#endif - -#if QT_CONFIG(wmsdk) - -namespace -{ - struct QWMMetaDataKey - { - QString qtName; - const wchar_t *wmName; - - QWMMetaDataKey(const QString &qtn, const wchar_t *wmn) : qtName(qtn), wmName(wmn) { } - }; -} - -using QWMMetaDataKeys = QList<QWMMetaDataKey>; -Q_GLOBAL_STATIC(QWMMetaDataKeys, metadataKeys) - -static const QWMMetaDataKeys *qt_wmMetaDataKeys() -{ - if (metadataKeys->isEmpty()) { - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Title, L"Title")); - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::SubTitle, L"WM/SubTitle")); - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Author, L"Author")); - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Comment, L"Comment")); - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Description, L"Description")); - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Category, L"WM/Category")); - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Genre, L"WM/Genre")); - //metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Date, 0)); - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Year, L"WM/Year")); - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::UserRating, L"Rating")); - //metadataKeys->append(QWMMetaDataKey(QMediaMetaData::MetaDatawords, 0)); - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Language, L"WM/Language")); - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Publisher, L"WM/Publisher")); - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Copyright, L"Copyright")); - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::ParentalRating, L"WM/ParentalRating")); - //metadataKeys->append(QWMMetaDataKey(QMediaMetaData::RatingOrganisation, L"RatingOrganisation")); - - // Media - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Size, L"FileSize")); - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::MediaType, L"MediaType")); - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Duration, L"Duration")); - - // Audio - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::AudioBitRate, L"AudioBitRate")); - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::AudioCodec, L"AudioCodec")); - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::ChannelCount, L"ChannelCount")); - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::SampleRate, L"Frequency")); - - // Music - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::AlbumTitle, L"WM/AlbumTitle")); - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::AlbumArtist, L"WM/AlbumArtist")); - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::ContributingArtist, L"Author")); - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Composer, L"WM/Composer")); - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Conductor, L"WM/Conductor")); - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Lyrics, L"WM/Lyrics")); - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Mood, L"WM/Mood")); - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::TrackNumber, L"WM/TrackNumber")); - //metadataKeys->append(QWMMetaDataKey(QMediaMetaData::TrackCount, 0)); - //metadataKeys->append(QWMMetaDataKey(QMediaMetaData::CoverArtUriSmall, 0)); - //metadataKeys->append(QWMMetaDataKey(QMediaMetaData::CoverArtUriLarge, 0)); - - // Image/Video - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Resolution, L"WM/VideoHeight")); - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::PixelAspectRatio, L"AspectRatioX")); - - // Video - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::VideoFrameRate, L"WM/VideoFrameRate")); - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::VideoBitRate, L"VideoBitRate")); - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::VideoCodec, L"VideoCodec")); - - //metadataKeys->append(QWMMetaDataKey(QMediaMetaData::PosterUri, 0)); - - // Movie - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::ChapterNumber, L"ChapterNumber")); - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Director, L"WM/Director")); - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::LeadPerformer, L"LeadPerformer")); - metadataKeys->append(QWMMetaDataKey(QMediaMetaData::Writer, L"WM/Writer")); - } - - return metadataKeys; -} - -static QVariant getValue(IWMHeaderInfo *header, const wchar_t *key) -{ - WORD streamNumber = 0; - WMT_ATTR_DATATYPE type = WMT_TYPE_DWORD; - WORD size = 0; - - if (header->GetAttributeByName(&streamNumber, key, &type, nullptr, &size) == S_OK) { - switch (type) { - case WMT_TYPE_DWORD: - if (size == sizeof(DWORD)) { - DWORD word; - if (header->GetAttributeByName( - &streamNumber, - key, - &type, - reinterpret_cast<BYTE *>(&word), - &size) == S_OK) { - return int(word); - } - } - break; - case WMT_TYPE_STRING: - { - QString string; - string.resize(size / 2); // size is in bytes, string is in UTF16 - - if (header->GetAttributeByName( - &streamNumber, - key, - &type, - reinterpret_cast<BYTE *>(string.data()), - &size) == S_OK) { - return string; - } - } - break; - case WMT_TYPE_BINARY: - { - QByteArray bytes; - bytes.resize(size); - if (header->GetAttributeByName( - &streamNumber, - key, - &type, - reinterpret_cast<BYTE *>(bytes.data()), - &size) == S_OK) { - return bytes; - } - } - break; - case WMT_TYPE_BOOL: - if (size == sizeof(DWORD)) { - DWORD word; - if (header->GetAttributeByName( - &streamNumber, - key, - &type, - reinterpret_cast<BYTE *>(&word), - &size) == S_OK) { - return bool(word); - } - } - break; - case WMT_TYPE_QWORD: - if (size == sizeof(QWORD)) { - QWORD word; - if (header->GetAttributeByName( - &streamNumber, - key, - &type, - reinterpret_cast<BYTE *>(&word), - &size) == S_OK) { - return qint64(word); - } - } - break; - case WMT_TYPE_WORD: - if (size == sizeof(WORD)){ - WORD word; - if (header->GetAttributeByName( - &streamNumber, - key, - &type, - reinterpret_cast<BYTE *>(&word), - &size) == S_OK) { - return short(word); - } - } - break; - case WMT_TYPE_GUID: - if (size == 16) { - } - break; - default: - break; - } - } - return QVariant(); -} -#endif - -#if QT_CONFIG(wshellitem) -static QVariant convertValue(const PROPVARIANT& var) -{ - 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(reinterpret_cast<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; -} -#endif - -DirectShowMetaDataControl::DirectShowMetaDataControl(QObject *parent) - : QMetaDataReaderControl(parent) -{ -} - -DirectShowMetaDataControl::~DirectShowMetaDataControl() = default; - -bool DirectShowMetaDataControl::isMetaDataAvailable() const -{ - return m_available; -} - -QVariant DirectShowMetaDataControl::metaData(const QString &key) const -{ - return m_metadata.value(key); -} - -QStringList DirectShowMetaDataControl::availableMetaData() const -{ - return m_metadata.keys(); -} - -static QString convertBSTR(BSTR *string) -{ - QString value = QString::fromUtf16(reinterpret_cast<ushort *>(*string), - ::SysStringLen(*string)); - - ::SysFreeString(*string); - string = nullptr; - - return value; -} - -void DirectShowMetaDataControl::setMetadata(const QVariantMap &metadata) -{ - m_metadata = metadata; - setMetadataAvailable(!m_metadata.isEmpty()); -} - -void DirectShowMetaDataControl::updateMetadata(const QString &fileSrc, QVariantMap &metadata) -{ -#if QT_CONFIG(wshellitem) - if (!sHCreateItemFromParsingName) { - QSystemLibrary lib(QStringLiteral("shell32")); - sHCreateItemFromParsingName = (q_SHCreateItemFromParsingName)(lib.resolve("SHCreateItemFromParsingName")); - } - - if (!fileSrc.isEmpty() && sHCreateItemFromParsingName) { - IShellItem2* shellItem = nullptr; - if (sHCreateItemFromParsingName(reinterpret_cast<const WCHAR*>(fileSrc.utf16()), - nullptr, IID_PPV_ARGS(&shellItem)) == S_OK) { - - IPropertyStore *pStore = nullptr; - if (shellItem->GetPropertyStore(GPS_DEFAULT, IID_PPV_ARGS(&pStore)) == S_OK) { - DWORD cProps; - if (SUCCEEDED(pStore->GetCount(&cProps))) { - for (DWORD i = 0; i < cProps; ++i) - { - PROPERTYKEY key; - PROPVARIANT var; - PropVariantInit(&var); - if (FAILED(pStore->GetAt(i, &key))) - continue; - if (FAILED(pStore->GetValue(key, &var))) - continue; - - if (IsEqualPropertyKey(key, PKEY_Author)) { - metadata.insert(QMediaMetaData::Author, convertValue(var)); - } else if (IsEqualPropertyKey(key, PKEY_Title)) { - metadata.insert(QMediaMetaData::Title, convertValue(var)); - } else if (IsEqualPropertyKey(key, PKEY_Media_SubTitle)) { - metadata.insert(QMediaMetaData::SubTitle, convertValue(var)); - } else if (IsEqualPropertyKey(key, PKEY_ParentalRating)) { - metadata.insert(QMediaMetaData::ParentalRating, convertValue(var)); - } else if (IsEqualPropertyKey(key, PKEY_Comment)) { - metadata.insert(QMediaMetaData::Description, convertValue(var)); - } else if (IsEqualPropertyKey(key, PKEY_Copyright)) { - metadata.insert(QMediaMetaData::Copyright, convertValue(var)); - } else if (IsEqualPropertyKey(key, PKEY_Media_ProviderStyle)) { - metadata.insert(QMediaMetaData::Genre, convertValue(var)); - } else if (IsEqualPropertyKey(key, PKEY_Media_Year)) { - metadata.insert(QMediaMetaData::Year, convertValue(var)); - } else if (IsEqualPropertyKey(key, PKEY_Media_DateEncoded)) { - metadata.insert(QMediaMetaData::Date, convertValue(var)); - } else if (IsEqualPropertyKey(key, PKEY_Rating)) { - metadata.insert(QMediaMetaData::UserRating, - int((convertValue(var).toUInt() - 1) / qreal(98) * 100)); - } else if (IsEqualPropertyKey(key, PKEY_Keywords)) { - metadata.insert(QMediaMetaData::Keywords, convertValue(var)); - } else if (IsEqualPropertyKey(key, PKEY_Language)) { - metadata.insert(QMediaMetaData::Language, convertValue(var)); - } else if (IsEqualPropertyKey(key, PKEY_Media_Publisher)) { - metadata.insert(QMediaMetaData::Publisher, convertValue(var)); - } else if (IsEqualPropertyKey(key, PKEY_Media_Duration)) { - metadata.insert(QMediaMetaData::Duration, - (convertValue(var).toLongLong() + 10000) / 10000); - } else if (IsEqualPropertyKey(key, PKEY_Audio_EncodingBitrate)) { - metadata.insert(QMediaMetaData::AudioBitRate, convertValue(var)); - } else if (IsEqualPropertyKey(key, PKEY_Media_AverageLevel)) { - metadata.insert(QMediaMetaData::AverageLevel, convertValue(var)); - } else if (IsEqualPropertyKey(key, PKEY_Audio_ChannelCount)) { - metadata.insert(QMediaMetaData::ChannelCount, convertValue(var)); - } else if (IsEqualPropertyKey(key, PKEY_Audio_PeakValue)) { - metadata.insert(QMediaMetaData::PeakValue, convertValue(var)); - } else if (IsEqualPropertyKey(key, PKEY_Audio_SampleRate)) { - metadata.insert(QMediaMetaData::SampleRate, convertValue(var)); - } else if (IsEqualPropertyKey(key, PKEY_Music_AlbumTitle)) { - metadata.insert(QMediaMetaData::AlbumTitle, convertValue(var)); - } else if (IsEqualPropertyKey(key, PKEY_Music_AlbumArtist)) { - metadata.insert(QMediaMetaData::AlbumArtist, convertValue(var)); - } else if (IsEqualPropertyKey(key, PKEY_Music_Artist)) { - metadata.insert(QMediaMetaData::ContributingArtist, convertValue(var)); - } else if (IsEqualPropertyKey(key, PKEY_Music_Composer)) { - metadata.insert(QMediaMetaData::Composer, convertValue(var)); - } else if (IsEqualPropertyKey(key, PKEY_Music_Conductor)) { - metadata.insert(QMediaMetaData::Conductor, convertValue(var)); - } else if (IsEqualPropertyKey(key, PKEY_Music_Lyrics)) { - metadata.insert(QMediaMetaData::Lyrics, convertValue(var)); - } else if (IsEqualPropertyKey(key, PKEY_Music_Mood)) { - metadata.insert(QMediaMetaData::Mood, convertValue(var)); - } else if (IsEqualPropertyKey(key, PKEY_Music_TrackNumber)) { - metadata.insert(QMediaMetaData::TrackNumber, convertValue(var)); - } else if (IsEqualPropertyKey(key, PKEY_Music_Genre)) { - metadata.insert(QMediaMetaData::Genre, convertValue(var)); - } else if (IsEqualPropertyKey(key, PKEY_ThumbnailStream)) { - metadata.insert(QMediaMetaData::ThumbnailImage, convertValue(var)); - } else if (IsEqualPropertyKey(key, PKEY_Video_FrameHeight)) { - QSize res; - res.setHeight(convertValue(var).toUInt()); - if (SUCCEEDED(pStore->GetValue(PKEY_Video_FrameWidth, &var))) - res.setWidth(convertValue(var).toUInt()); - metadata.insert(QMediaMetaData::Resolution, res); - } else if (IsEqualPropertyKey(key, PKEY_Video_HorizontalAspectRatio)) { - QSize aspectRatio; - aspectRatio.setWidth(convertValue(var).toUInt()); - if (SUCCEEDED(pStore->GetValue(PKEY_Video_VerticalAspectRatio, &var))) - aspectRatio.setHeight(convertValue(var).toUInt()); - metadata.insert(QMediaMetaData::PixelAspectRatio, aspectRatio); - } else if (IsEqualPropertyKey(key, PKEY_Video_FrameRate)) { - metadata.insert(QMediaMetaData::VideoFrameRate, - convertValue(var).toReal() / 1000); - } else if (IsEqualPropertyKey(key, PKEY_Video_EncodingBitrate)) { - metadata.insert(QMediaMetaData::VideoBitRate, convertValue(var)); - } else if (IsEqualPropertyKey(key, PKEY_Video_Director)) { - metadata.insert(QMediaMetaData::Director, convertValue(var)); - } else if (IsEqualPropertyKey(key, PKEY_Media_Writer)) { - metadata.insert(QMediaMetaData::Writer, convertValue(var)); - } else if (IsEqualPropertyKey(key, PKEY_Video_Compression)) { - metadata.insert(QMediaMetaData::VideoCodec, nameForGUIDString(convertValue(var).toString())); - } else if (IsEqualPropertyKey(key, PKEY_Audio_Format)) { - metadata.insert(QMediaMetaData::AudioCodec, nameForGUIDString(convertValue(var).toString())); - } - - PropVariantClear(&var); - } - } - - pStore->Release(); - } - - shellItem->Release(); - } - } -#else - Q_UNUSED(fileSrc); - Q_UNUSED(metadata); -#endif -} - -void DirectShowMetaDataControl::updateMetadata(IFilterGraph2 *graph, IBaseFilter *source, QVariantMap &metadata) -{ -#if QT_CONFIG(wmsdk) - if (IWMHeaderInfo *info = com_cast<IWMHeaderInfo>(source, IID_IWMHeaderInfo)) { - const auto keys = *qt_wmMetaDataKeys(); - for (const QWMMetaDataKey &key : keys) { - QVariant var = getValue(info, key.wmName); - if (var.isValid()) { - if (key.qtName == QMediaMetaData::Duration) { - // duration is provided in 100-nanosecond units, convert to milliseconds - var = (var.toLongLong() + 10000) / 10000; - } else if (key.qtName == QMediaMetaData::Resolution) { - QSize res; - res.setHeight(var.toUInt()); - res.setWidth(getValue(info, L"WM/VideoWidth").toUInt()); - var = res; - } else if (key.qtName == QMediaMetaData::VideoFrameRate) { - var = var.toReal() / 1000.f; - } else if (key.qtName == QMediaMetaData::PixelAspectRatio) { - QSize aspectRatio; - aspectRatio.setWidth(var.toUInt()); - aspectRatio.setHeight(getValue(info, L"AspectRatioY").toUInt()); - var = aspectRatio; - } else if (key.qtName == QMediaMetaData::UserRating) { - var = (var.toUInt() - 1) / qreal(98) * 100; - } - - metadata.insert(key.qtName, var); - } - } - - info->Release(); - } - - if (!metadata.isEmpty()) - return; -#endif - { - IAMMediaContent *content = nullptr; - - if ((!graph || graph->QueryInterface( - IID_IAMMediaContent, reinterpret_cast<void **>(&content)) != S_OK) - && (!source || source->QueryInterface( - IID_IAMMediaContent, reinterpret_cast<void **>(&content)) != S_OK)) { - content = nullptr; - } - - if (content) { - BSTR string = nullptr; - - if (content->get_AuthorName(&string) == S_OK) - metadata.insert(QMediaMetaData::Author, convertBSTR(&string)); - - if (content->get_Title(&string) == S_OK) - metadata.insert(QMediaMetaData::Title, convertBSTR(&string)); - - if (content->get_Description(&string) == S_OK) - metadata.insert(QMediaMetaData::Description, convertBSTR(&string)); - - if (content->get_Rating(&string) == S_OK) - metadata.insert(QMediaMetaData::UserRating, convertBSTR(&string)); - - if (content->get_Copyright(&string) == S_OK) - metadata.insert(QMediaMetaData::Copyright, convertBSTR(&string)); - - content->Release(); - } - } -} - -void DirectShowMetaDataControl::setMetadataAvailable(bool available) -{ - if (m_available == available) - return; - - m_available = available; - - // If the metadata is not available, notify about it immediately. - Qt::ConnectionType type = m_available ? Qt::QueuedConnection : Qt::AutoConnection; - QMetaObject::invokeMethod(this, "metaDataAvailableChanged", type, Q_ARG(bool, m_available)); - // Currently the metadata is changed only with its availability. - QMetaObject::invokeMethod(this, "metaDataChanged", type); -} diff --git a/src/plugins/directshow/player/directshowmetadatacontrol.h b/src/plugins/directshow/player/directshowmetadatacontrol.h deleted file mode 100644 index e66127ab3..000000000 --- a/src/plugins/directshow/player/directshowmetadatacontrol.h +++ /dev/null @@ -1,84 +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 DIRECTSHOWMETADATACONTROL_H -#define DIRECTSHOWMETADATACONTROL_H - -#include <dshow.h> - -#include <qmetadatareadercontrol.h> - -#include "directshowglobal.h" - -#include <QtCore/qcoreevent.h> - -QT_BEGIN_NAMESPACE - -class DirectShowMetaDataControl : public QMetaDataReaderControl -{ - Q_OBJECT -public: - DirectShowMetaDataControl(QObject *parent = nullptr); - ~DirectShowMetaDataControl() override; - - bool isMetaDataAvailable() const override; - - QVariant metaData(const QString &key) const override; - QStringList availableMetaData() const override; - - void setMetadata(const QVariantMap &metadata); - - static void updateMetadata(const QString &fileSrc, QVariantMap &metadata); - static void updateMetadata(IFilterGraph2 *graph, IBaseFilter *source, QVariantMap &metadata); - -private: - void setMetadataAvailable(bool available); - - enum Event - { - MetaDataChanged = QEvent::User - }; - - QVariantMap m_metadata; - bool m_available = false; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/plugins/directshow/player/directshowplayercontrol.cpp b/src/plugins/directshow/player/directshowplayercontrol.cpp deleted file mode 100644 index 50e8d6421..000000000 --- a/src/plugins/directshow/player/directshowplayercontrol.cpp +++ /dev/null @@ -1,397 +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 <dshow.h> - -#include "directshowplayercontrol.h" - -#include "directshowplayerservice.h" - -#include <QtCore/qcoreapplication.h> -#include <QtCore/qmath.h> -#include <qaudio.h> - -DirectShowPlayerControl::DirectShowPlayerControl(DirectShowPlayerService *service, QObject *parent) - : QMediaPlayerControl(parent) - , m_service(service) -{ -} - -DirectShowPlayerControl::~DirectShowPlayerControl() -{ - if (m_audio) - m_audio->Release(); -} - -QMediaPlayer::State DirectShowPlayerControl::state() const -{ - return m_state; -} - -QMediaPlayer::MediaStatus DirectShowPlayerControl::mediaStatus() const -{ - return m_status; -} - -qint64 DirectShowPlayerControl::duration() const -{ - return m_duration; -} - -qint64 DirectShowPlayerControl::position() const -{ - if (m_pendingPosition != -1) - return m_pendingPosition; - - return m_service->position(); -} - -void DirectShowPlayerControl::setPosition(qint64 position) -{ - if (m_status == QMediaPlayer::EndOfMedia) { - m_status = QMediaPlayer::LoadedMedia; - emit mediaStatusChanged(m_status); - } - - if (m_state == QMediaPlayer::StoppedState) { - if (m_pendingPosition != position) { - m_pendingPosition = position; - emit positionChanged(m_pendingPosition); - } - return; - } - - m_service->seek(position); - m_pendingPosition = -1; -} - -int DirectShowPlayerControl::volume() const -{ - return m_volume; -} - -void DirectShowPlayerControl::setVolume(int volume) -{ - int boundedVolume = qBound(0, volume, 100); - - if (m_volume == boundedVolume) - return; - - m_volume = boundedVolume; - - if (!m_muted) - setVolumeHelper(m_volume); - - emit volumeChanged(m_volume); -} - -bool DirectShowPlayerControl::isMuted() const -{ - return m_muted; -} - -void DirectShowPlayerControl::setMuted(bool muted) -{ - if (m_muted == muted) - return; - - m_muted = muted; - - setVolumeHelper(m_muted ? 0 : m_volume); - - emit mutedChanged(m_muted); -} - -void DirectShowPlayerControl::setVolumeHelper(int volume) -{ - if (!m_audio) - return; - - long adjustedVolume; - if (volume == 0) { - adjustedVolume = -10000; // -100 dB (lower limit for put_Volume()) - } else if (volume == 100) { - adjustedVolume = 0; - } else { - adjustedVolume = QAudio::convertVolume(volume / qreal(100), - QAudio::LinearVolumeScale, - QAudio::DecibelVolumeScale) * 100; - } - - m_audio->put_Volume(adjustedVolume); -} - -int DirectShowPlayerControl::bufferStatus() const -{ - return m_service->bufferStatus(); -} - -bool DirectShowPlayerControl::isAudioAvailable() const -{ - return m_streamTypes & DirectShowPlayerService::AudioStream; -} - -bool DirectShowPlayerControl::isVideoAvailable() const -{ - return m_streamTypes & DirectShowPlayerService::VideoStream; -} - -bool DirectShowPlayerControl::isSeekable() const -{ - return m_seekable; -} - -QMediaTimeRange DirectShowPlayerControl::availablePlaybackRanges() const -{ - return m_service->availablePlaybackRanges(); -} - -qreal DirectShowPlayerControl::playbackRate() const -{ - return m_playbackRate; -} - -void DirectShowPlayerControl::setPlaybackRate(qreal rate) -{ - if (!qFuzzyCompare(m_playbackRate, rate)) { - m_service->setRate(rate); - - emit playbackRateChanged(m_playbackRate = rate); - } -} - -QMediaContent DirectShowPlayerControl::media() const -{ - return m_media; -} - -const QIODevice *DirectShowPlayerControl::mediaStream() const -{ - return m_stream; -} - -void DirectShowPlayerControl::setMedia(const QMediaContent &media, QIODevice *stream) -{ - if (m_media == media && m_stream == stream) - return; - - m_pendingPosition = -1; - m_emitPosition = -1; - - m_media = media; - m_stream = stream; - - m_updateProperties &= PlaybackRateProperty; - - m_service->load(media, stream); - - emit mediaChanged(m_media); - emitPropertyChanges(); -} - -void DirectShowPlayerControl::play() -{ - playOrPause(QMediaPlayer::PlayingState); -} - -void DirectShowPlayerControl::pause() -{ - playOrPause(QMediaPlayer::PausedState); -} - -void DirectShowPlayerControl::playOrPause(QMediaPlayer::State state) -{ - if (m_status == QMediaPlayer::NoMedia || state == QMediaPlayer::StoppedState) - return; - if (m_status == QMediaPlayer::InvalidMedia) { - setMedia(m_media, m_stream); - if (m_error != QMediaPlayer::NoError) - return; - } - - m_emitPosition = -1; - m_state = state; - - if (m_pendingPosition != -1) - setPosition(m_pendingPosition); - - if (state == QMediaPlayer::PausedState) - m_service->pause(); - else - m_service->play(); - - emit stateChanged(m_state); -} - -void DirectShowPlayerControl::stop() -{ - m_emitPosition = -1; - m_service->stop(); - emit stateChanged(m_state = QMediaPlayer::StoppedState); -} - -void DirectShowPlayerControl::customEvent(QEvent *event) -{ - if (event->type() == QEvent::Type(PropertiesChanged)) { - emitPropertyChanges(); - - event->accept(); - } else { - QMediaPlayerControl::customEvent(event); - } -} - -void DirectShowPlayerControl::emitPropertyChanges() -{ - int properties = m_updateProperties; - m_updateProperties = 0; - - if (properties & StatusProperty) - emit mediaStatusChanged(m_status); - - if ((properties & ErrorProperty) && m_error != QMediaPlayer::NoError) - emit error(m_error, m_errorString); - - if (properties & PlaybackRateProperty) - emit playbackRateChanged(m_playbackRate); - - if (properties & StreamTypesProperty) { - emit audioAvailableChanged(m_streamTypes & DirectShowPlayerService::AudioStream); - emit videoAvailableChanged(m_streamTypes & DirectShowPlayerService::VideoStream); - } - - if (properties & PositionProperty && m_emitPosition != -1) - emit positionChanged(m_emitPosition); - - if (properties & DurationProperty) - emit durationChanged(m_duration); - - if (properties & SeekableProperty) - emit seekableChanged(m_seekable); - - if (properties & StateProperty) - emit stateChanged(m_state); -} - -void DirectShowPlayerControl::scheduleUpdate(int properties) -{ - if (m_updateProperties == 0) - QCoreApplication::postEvent(this, new QEvent(QEvent::Type(PropertiesChanged))); - - m_updateProperties |= properties; -} - -void DirectShowPlayerControl::updateState(QMediaPlayer::State state) -{ - if (m_state != state) { - m_state = state; - - scheduleUpdate(StateProperty); - } -} - -void DirectShowPlayerControl::updateStatus(QMediaPlayer::MediaStatus status) -{ - if (m_status != status) { - m_status = status; - - scheduleUpdate(StatusProperty); - } -} - -void DirectShowPlayerControl::updateMediaInfo(qint64 duration, int streamTypes, bool seekable) -{ - int properties = 0; - - if (m_duration != duration) { - m_duration = duration; - - properties |= DurationProperty; - } - if (m_streamTypes != streamTypes) { - m_streamTypes = streamTypes; - - properties |= StreamTypesProperty; - } - - if (m_seekable != seekable) { - m_seekable = seekable; - - properties |= SeekableProperty; - } - - if (properties != 0) - scheduleUpdate(properties); -} - -void DirectShowPlayerControl::updatePlaybackRate(qreal rate) -{ - if (!qFuzzyCompare(m_playbackRate, rate)) { - m_playbackRate = rate; - - scheduleUpdate(PlaybackRateProperty); - } -} - -void DirectShowPlayerControl::updateAudioOutput(IBaseFilter *filter) -{ - if (m_audio) - m_audio->Release(); - - m_audio = com_cast<IBasicAudio>(filter, IID_IBasicAudio); - setVolumeHelper(m_muted ? 0 : m_volume); -} - -void DirectShowPlayerControl::updateError(QMediaPlayer::Error error, const QString &errorString) -{ - m_error = error; - m_errorString = errorString; - - if (m_error != QMediaPlayer::NoError) - scheduleUpdate(ErrorProperty); -} - -void DirectShowPlayerControl::updatePosition(qint64 position) -{ - if (m_emitPosition != position) { - m_emitPosition = position; - - scheduleUpdate(PositionProperty); - } -} diff --git a/src/plugins/directshow/player/directshowplayercontrol.h b/src/plugins/directshow/player/directshowplayercontrol.h deleted file mode 100644 index 122f5be2f..000000000 --- a/src/plugins/directshow/player/directshowplayercontrol.h +++ /dev/null @@ -1,153 +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 DIRECTSHOWPLAYERCONTROL_H -#define DIRECTSHOWPLAYERCONTROL_H - -#include <dshow.h> - -#include "qmediacontent.h" -#include "qmediaplayercontrol.h" - -#include <QtCore/qcoreevent.h> - -#include "directshowplayerservice.h" - -QT_BEGIN_NAMESPACE - -class DirectShowPlayerControl : public QMediaPlayerControl -{ - Q_OBJECT -public: - DirectShowPlayerControl(DirectShowPlayerService *service, QObject *parent = nullptr); - ~DirectShowPlayerControl() override; - - QMediaPlayer::State state() const override; - - QMediaPlayer::MediaStatus mediaStatus() const override; - - qint64 duration() const override; - - qint64 position() const override; - void setPosition(qint64 position) override; - - int volume() const override; - void setVolume(int volume) override; - - bool isMuted() const override; - void setMuted(bool muted) override; - - int bufferStatus() const override; - - bool isAudioAvailable() const override; - bool isVideoAvailable() const override; - - bool isSeekable() const override; - - QMediaTimeRange availablePlaybackRanges() const override; - - qreal playbackRate() const override; - void setPlaybackRate(qreal rate) override; - - QMediaContent media() const override; - const QIODevice *mediaStream() const override; - void setMedia(const QMediaContent &media, QIODevice *stream) override; - - void play() override; - void pause() override; - void stop() override; - - void updateState(QMediaPlayer::State state); - void updateStatus(QMediaPlayer::MediaStatus status); - void updateMediaInfo(qint64 duration, int streamTypes, bool seekable); - void updatePlaybackRate(qreal rate); - void updateAudioOutput(IBaseFilter *filter); - void updateError(QMediaPlayer::Error error, const QString &errorString); - void updatePosition(qint64 position); - -protected: - void customEvent(QEvent *event) override; - -private: - enum Properties - { - StateProperty = 0x01, - StatusProperty = 0x02, - StreamTypesProperty = 0x04, - DurationProperty = 0x08, - PlaybackRateProperty = 0x10, - SeekableProperty = 0x20, - ErrorProperty = 0x40, - PositionProperty = 0x80 - }; - - enum Event - { - PropertiesChanged = QEvent::User - }; - - void playOrPause(QMediaPlayer::State state); - - void scheduleUpdate(int properties); - void emitPropertyChanges(); - void setVolumeHelper(int volume); - - DirectShowPlayerService *m_service; - IBasicAudio *m_audio = nullptr; - QIODevice *m_stream = nullptr; - int m_updateProperties = 0; - QMediaPlayer::State m_state = QMediaPlayer::StoppedState; - QMediaPlayer::MediaStatus m_status = QMediaPlayer::NoMedia; - QMediaPlayer::Error m_error = QMediaPlayer::NoError; - int m_streamTypes = 0; - int m_volume = 100; - bool m_muted = false; - qint64 m_emitPosition = -1; - qint64 m_pendingPosition = -1; - qint64 m_duration = 0; - qreal m_playbackRate = 0; - bool m_seekable = false; - QMediaContent m_media; - QString m_errorString; - -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/plugins/directshow/player/directshowplayerservice.cpp b/src/plugins/directshow/player/directshowplayerservice.cpp deleted file mode 100644 index 04e27b9c4..000000000 --- a/src/plugins/directshow/player/directshowplayerservice.cpp +++ /dev/null @@ -1,1812 +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 <dshow.h> -#ifdef min -#undef min -#endif -#ifdef max -#undef max -#endif - -#include "directshowplayerservice.h" - -#include "directshowaudioendpointcontrol.h" -#include "directshowmetadatacontrol.h" -#include "vmr9videowindowcontrol.h" -#include "directshowiosource.h" -#include "directshowplayercontrol.h" -#include "directshowvideorenderercontrol.h" -#include "directshowutils.h" -#include "directshowglobal.h" -#include "directshowaudioprobecontrol.h" -#include "directshowvideoprobecontrol.h" -#include "directshowsamplegrabber.h" - -#if QT_CONFIG(evr) -#include "directshowevrvideowindowcontrol.h" -#else -#include <mmreg.h> -#endif - -#include "qmediacontent.h" - -#include <QtMultimedia/private/qtmultimedia-config_p.h> - -#include <QtCore/qcoreapplication.h> -#include <QtCore/qdatetime.h> -#include <QtCore/qdir.h> -#include <QtCore/qthread.h> -#include <QtCore/qvarlengtharray.h> -#include <QtCore/qsize.h> - -#include <QtMultimedia/qaudiobuffer.h> -#include <QtMultimedia/qvideoframe.h> -#include <QtMultimedia/private/qmemoryvideobuffer_p.h> - -#if QT_CONFIG(wmsdk) -# include <wmsdk.h> -#endif - -#ifndef Q_CC_MINGW -# include <comdef.h> -#endif - -QT_BEGIN_NAMESPACE - -Q_GLOBAL_STATIC(DirectShowEventLoop, qt_directShowEventLoop) - -static QString comError(HRESULT hr) -{ -#ifndef Q_CC_MINGW // MinGW 5.3 no longer has swprintf_s(). - _com_error error(hr); - return QString::fromWCharArray(error.ErrorMessage()); -#else - Q_UNUSED(hr); - return QString(); -#endif -} - -// QMediaPlayer uses millisecond time units, direct show uses 100 nanosecond units. -static const int qt_directShowTimeScale = 10000; - -class DirectShowPlayerServiceThread : public QThread -{ -public: - DirectShowPlayerServiceThread(DirectShowPlayerService *service) - : m_service(service) - { - } - -protected: - void run() override { m_service->run(); } - -private: - DirectShowPlayerService *m_service; -}; - -DirectShowPlayerService::DirectShowPlayerService(QObject *parent) - : QMediaService(parent) - , m_loop(qt_directShowEventLoop()) - , m_taskHandle(::CreateEvent(nullptr, FALSE, FALSE, nullptr)) -{ - m_playerControl = new DirectShowPlayerControl(this); - m_metaDataControl = new DirectShowMetaDataControl(this); - m_audioEndpointControl = new DirectShowAudioEndpointControl(this); - - m_taskThread = new DirectShowPlayerServiceThread(this); - m_taskThread->start(); -} - -DirectShowPlayerService::~DirectShowPlayerService() -{ - { - QMutexLocker locker(&m_mutex); - - releaseGraph(); - - m_pendingTasks = Shutdown; - ::SetEvent(m_taskHandle); - } - - m_taskThread->wait(); - delete m_taskThread; - - if (m_audioOutput) { - m_audioOutput->Release(); - m_audioOutput = nullptr; - } - - if (m_videoOutput) { - m_videoOutput->Release(); - m_videoOutput = nullptr; - } - - delete m_playerControl; - delete m_audioEndpointControl; - delete m_metaDataControl; - delete m_videoRendererControl; - delete m_videoWindowControl; - delete m_audioProbeControl; - delete m_videoProbeControl; - - ::CloseHandle(m_taskHandle); -} - -QMediaControl *DirectShowPlayerService::requestControl(const char *name) -{ - if (qstrcmp(name, QMediaPlayerControl_iid) == 0) - return m_playerControl; - if (qstrcmp(name, QAudioOutputSelectorControl_iid) == 0) - return m_audioEndpointControl; - if (qstrcmp(name, QMetaDataReaderControl_iid) == 0) - return m_metaDataControl; - if (qstrcmp(name, QVideoRendererControl_iid) == 0) { - if (!m_videoRendererControl && !m_videoWindowControl) { - m_videoRendererControl = new DirectShowVideoRendererControl(m_loop); - - connect(m_videoRendererControl, &DirectShowVideoRendererControl::filterChanged, - this, &DirectShowPlayerService::videoOutputChanged); - - return m_videoRendererControl; - } - return nullptr; - } - if (qstrcmp(name, QVideoWindowControl_iid) == 0) { - if (!m_videoRendererControl && !m_videoWindowControl) { - IBaseFilter *filter{}; - -#if QT_CONFIG(evr) - if (!qgetenv("QT_DIRECTSHOW_NO_EVR").toInt()) { - DirectShowEvrVideoWindowControl *evrControl = new DirectShowEvrVideoWindowControl; - if ((filter = evrControl->filter())) - m_videoWindowControl = evrControl; - else - delete evrControl; - } -#endif - // Fall back to the VMR9 if the EVR is not available - if (!m_videoWindowControl) { - Vmr9VideoWindowControl *vmr9Control = new Vmr9VideoWindowControl; - filter = vmr9Control->filter(); - m_videoWindowControl = vmr9Control; - } - - setVideoOutput(filter); - - return m_videoWindowControl; - } - return nullptr; - } - if (qstrcmp(name, QMediaAudioProbeControl_iid) == 0) { - if (!m_audioProbeControl) - m_audioProbeControl = new DirectShowAudioProbeControl(); - m_audioProbeControl->ref(); - updateAudioProbe(); - return m_audioProbeControl; - } - if (qstrcmp(name, QMediaVideoProbeControl_iid) == 0) { - if (!m_videoProbeControl) - m_videoProbeControl = new DirectShowVideoProbeControl(); - m_videoProbeControl->ref(); - updateVideoProbe(); - return m_videoProbeControl; - } - return nullptr; -} - -void DirectShowPlayerService::releaseControl(QMediaControl *control) -{ - if (!control) { - qWarning("QMediaService::releaseControl():" - " Attempted release of null control"); - } else if (control == m_videoRendererControl) { - setVideoOutput(nullptr); - - delete m_videoRendererControl; - - m_videoRendererControl = nullptr; - } else if (control == m_videoWindowControl) { - setVideoOutput(nullptr); - - delete m_videoWindowControl; - - m_videoWindowControl = nullptr; - } else if (control == m_audioProbeControl) { - if (!m_audioProbeControl->deref()) { - DirectShowAudioProbeControl *old = m_audioProbeControl; - m_audioProbeControl = nullptr; - updateAudioProbe(); - delete old; - } - } else if (control == m_videoProbeControl) { - if (!m_videoProbeControl->deref()) { - DirectShowVideoProbeControl *old = m_videoProbeControl; - m_videoProbeControl = nullptr; - updateVideoProbe(); - delete old; - } - } -} - -void DirectShowPlayerService::load(const QMediaContent &media, QIODevice *stream) -{ - QMutexLocker locker(&m_mutex); - - m_pendingTasks = 0; - - if (m_graph) - releaseGraph(); - - m_url = media.request().url(); - - m_stream = stream; - m_error = QMediaPlayer::NoError; - m_errorString = QString(); - m_position = 0; - m_seekPosition = -1; - m_duration = 0; - m_streamTypes = 0; - m_executedTasks = 0; - m_buffering = false; - m_seekable = false; - m_atEnd = false; - m_dontCacheNextSeekResult = false; - m_metaDataControl->setMetadata(QVariantMap()); - - if (m_url.isEmpty() && !stream) { - m_pendingTasks = 0; - m_graphStatus = NoMedia; - } else if (stream && (!stream->isReadable() || stream->isSequential())) { - m_pendingTasks = 0; - m_graphStatus = InvalidMedia; - m_error = QMediaPlayer::ResourceError; - } else { - // {36b73882-c2c8-11cf-8b46-00805f6cef60} - static const GUID iid_IFilterGraph2 = { - 0x36b73882, 0xc2c8, 0x11cf, {0x8b, 0x46, 0x00, 0x80, 0x5f, 0x6c, 0xef, 0x60} }; - m_graphStatus = Loading; - - DirectShowUtils::CoInitializeIfNeeded(); - m_graph = com_new<IFilterGraph2>(CLSID_FilterGraph, iid_IFilterGraph2); - m_graphBuilder = com_new<ICaptureGraphBuilder2>(CLSID_CaptureGraphBuilder2, IID_ICaptureGraphBuilder2); - - // Attach the filter graph to the capture graph. - HRESULT hr = m_graphBuilder->SetFiltergraph(m_graph); - if (FAILED(hr)) { - qCWarning(qtDirectShowPlugin, "[0x%x] Failed to attach filter to capture graph", hr); - m_graphBuilder->Release(); - m_graphBuilder = nullptr; - } - - if (stream) - m_pendingTasks = SetStreamSource; - else - m_pendingTasks = SetUrlSource; - - ::SetEvent(m_taskHandle); - } - - m_playerControl->updateError(m_error, m_errorString); - m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable); - m_playerControl->updateState(QMediaPlayer::StoppedState); - m_playerControl->updatePosition(m_position); - updateStatus(); -} - -void DirectShowPlayerService::doSetUrlSource(QMutexLocker<QMutex> *locker) -{ - IBaseFilter *source = nullptr; - - HRESULT hr = E_FAIL; - if (m_url.scheme() == QLatin1String("http") || m_url.scheme() == QLatin1String("https")) { - static const GUID clsid_WMAsfReader = { - 0x187463a0, 0x5bb7, 0x11d3, {0xac, 0xbe, 0x00, 0x80, 0xc7, 0x5e, 0x24, 0x6e} }; - - // {56a868a6-0ad4-11ce-b03a-0020af0ba770} - static const GUID iid_IFileSourceFilter = { - 0x56a868a6, 0x0ad4, 0x11ce, {0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70} }; - - if (IFileSourceFilter *fileSource = com_new<IFileSourceFilter>(clsid_WMAsfReader, iid_IFileSourceFilter)) { - locker->unlock(); - hr = fileSource->Load(reinterpret_cast<const OLECHAR *>(m_url.toString().utf16()), nullptr); - - if (SUCCEEDED(hr)) { - source = com_cast<IBaseFilter>(fileSource, IID_IBaseFilter); - - if (!SUCCEEDED(hr = m_graph->AddFilter(source, L"Source")) && source) { - source->Release(); - source = nullptr; - } - } - fileSource->Release(); - locker->relock(); - } - } - - if (!SUCCEEDED(hr)) { - locker->unlock(); - const QString urlString = m_url.isLocalFile() - ? QDir::toNativeSeparators(m_url.toLocalFile()) : m_url.toString(); - hr = m_graph->AddSourceFilter( - reinterpret_cast<const OLECHAR *>(urlString.utf16()), L"Source", &source); - locker->relock(); - } - - if (SUCCEEDED(hr)) { - m_executedTasks = SetSource; - m_pendingTasks |= Render; - - if (m_audioOutput) - m_pendingTasks |= SetAudioOutput; - if (m_videoOutput) - m_pendingTasks |= SetVideoOutput; - if (m_audioProbeControl) - m_pendingTasks |= SetAudioProbe; - if (m_videoProbeControl) - m_pendingTasks |= SetVideoProbe; - - if (m_rate != 1.0) - m_pendingTasks |= SetRate; - - m_source = source; - } else { - m_graphStatus = InvalidMedia; - - switch (hr) { - case VFW_E_UNKNOWN_FILE_TYPE: - m_error = QMediaPlayer::FormatError; - m_errorString = QString(); - break; - default: - m_error = QMediaPlayer::ResourceError; - m_errorString = QString(); - qWarning("DirectShowPlayerService::doSetUrlSource: Unresolved error code 0x%x (%s)", - uint(hr), qPrintable(comError(hr))); - break; - } - - QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Error))); - } -} - -void DirectShowPlayerService::doSetStreamSource(QMutexLocker<QMutex> *locker) -{ - Q_UNUSED(locker); - DirectShowIOSource *source = new DirectShowIOSource(m_loop); - source->setDevice(m_stream); - - const HRESULT hr = m_graph->AddFilter(source, L"Source"); - if (SUCCEEDED(hr)) { - m_executedTasks = SetSource; - m_pendingTasks |= Render; - - if (m_audioOutput) - m_pendingTasks |= SetAudioOutput; - if (m_videoOutput) - m_pendingTasks |= SetVideoOutput; - - if (m_rate != 1.0) - m_pendingTasks |= SetRate; - - m_source = source; - } else { - source->Release(); - - m_pendingTasks = 0; - m_graphStatus = InvalidMedia; - - m_error = QMediaPlayer::ResourceError; - m_errorString = QString(); - qWarning("DirectShowPlayerService::doPlay: Unresolved error code 0x%x (%s)", - uint(hr), qPrintable(comError(hr))); - - QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Error))); - } -} - -void DirectShowPlayerService::doRender(QMutexLocker<QMutex> *locker) -{ - m_pendingTasks |= m_executedTasks & (Play | Pause); - - if (IMediaControl *control = com_cast<IMediaControl>(m_graph, IID_IMediaControl)) { - control->Stop(); - control->Release(); - } - - if (m_pendingTasks & SetAudioOutput) { - m_graph->AddFilter(m_audioOutput, L"AudioOutput"); - - m_pendingTasks ^= SetAudioOutput; - m_executedTasks |= SetAudioOutput; - } - if (m_pendingTasks & SetVideoOutput) { - m_graph->AddFilter(m_videoOutput, L"VideoOutput"); - - m_pendingTasks ^= SetVideoOutput; - m_executedTasks |= SetVideoOutput; - } - - if (m_pendingTasks & SetAudioProbe) { - doSetAudioProbe(locker); - m_pendingTasks ^= SetAudioProbe; - m_executedTasks |= SetAudioProbe; - } - - if (m_pendingTasks & SetVideoProbe) { - doSetVideoProbe(locker); - m_pendingTasks ^= SetVideoProbe; - m_executedTasks |= SetVideoProbe; - } - - IFilterGraph2 *graph = m_graph; - graph->AddRef(); - - QVarLengthArray<IBaseFilter *, 16> filters; - m_source->AddRef(); - filters.append(m_source); - - bool rendered = false; - - HRESULT renderHr = S_OK; - - while (!filters.isEmpty()) { - IEnumPins *pins = nullptr; - IBaseFilter *filter = filters[filters.size() - 1]; - filters.removeLast(); - - if (!(m_pendingTasks & ReleaseFilters) && SUCCEEDED(filter->EnumPins(&pins))) { - int outputs = 0; - for (IPin *pin = nullptr; pins->Next(1, &pin, nullptr) == S_OK; pin->Release()) { - PIN_DIRECTION direction; - if (pin->QueryDirection(&direction) == S_OK && direction == PINDIR_OUTPUT) { - ++outputs; - - IPin *peer = nullptr; - if (pin->ConnectedTo(&peer) == S_OK) { - PIN_INFO peerInfo; - if (SUCCEEDED(peer->QueryPinInfo(&peerInfo))) - filters.append(peerInfo.pFilter); - peer->Release(); - } else { - locker->unlock(); - HRESULT hr = graph->RenderEx(pin, /*AM_RENDEREX_RENDERTOEXISTINGRENDERERS*/ 1, nullptr); - if (SUCCEEDED(hr)) { - rendered = true; - m_error = QMediaPlayer::NoError; - } else if (!(m_executedTasks & SetVideoOutput)) { - // Do not return an error if no video output is set yet. - rendered = true; - // Remember the error in this case. - // Handle it when playing is requested and no video output has been provided. - m_error = QMediaPlayer::ResourceError; - m_errorString = QString("%1: %2").arg(__FUNCTION__).arg(qt_error_string(hr)); - } else if (renderHr == S_OK || renderHr == VFW_E_NO_DECOMPRESSOR){ - renderHr = hr; - } - locker->relock(); - } - } - } - - pins->Release(); - - if (outputs == 0) - rendered = true; - } - filter->Release(); - } - - if (m_audioOutput && !isConnected(m_audioOutput, PINDIR_INPUT)) { - graph->RemoveFilter(m_audioOutput); - - m_executedTasks &= ~SetAudioOutput; - } - - if (m_videoOutput && !isConnected(m_videoOutput, PINDIR_INPUT)) { - graph->RemoveFilter(m_videoOutput); - - m_executedTasks &= ~SetVideoOutput; - } - - graph->Release(); - - if (!(m_pendingTasks & ReleaseFilters)) { - if (rendered) { - if (!(m_executedTasks & FinalizeLoad)) - m_pendingTasks |= FinalizeLoad; - } else { - m_pendingTasks = 0; - - m_graphStatus = InvalidMedia; - - if (!m_audioOutput && !m_videoOutput) { - m_error = QMediaPlayer::ResourceError; - m_errorString = QString(); - } else { - switch (renderHr) { - case VFW_E_UNSUPPORTED_AUDIO: - case VFW_E_UNSUPPORTED_VIDEO: - case VFW_E_UNSUPPORTED_STREAM: - m_error = QMediaPlayer::FormatError; - m_errorString = QString(); - break; - default: - m_error = QMediaPlayer::ResourceError; - m_errorString = QString(); - qWarning("DirectShowPlayerService::doRender: Unresolved error code 0x%x (%s)", - uint(renderHr), qPrintable(comError(renderHr))); - } - } - - QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Error))); - } - - m_executedTasks |= Render; - } -} - -void DirectShowPlayerService::doFinalizeLoad(QMutexLocker<QMutex> *locker) -{ - if (m_graphStatus != Loaded) { - if (IMediaEvent *event = com_cast<IMediaEvent>(m_graph, IID_IMediaEvent)) { - event->GetEventHandle(reinterpret_cast<OAEVENT *>(&m_eventHandle)); - event->Release(); - } - if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) { - LONGLONG duration = 0; - seeking->GetDuration(&duration); - m_duration = duration / qt_directShowTimeScale; - - DWORD capabilities = 0; - seeking->GetCapabilities(&capabilities); - m_seekable = capabilities & AM_SEEKING_CanSeekAbsolute; - - seeking->Release(); - } - } - - if ((m_executedTasks & SetOutputs) == SetOutputs) { - m_streamTypes = AudioStream | VideoStream; - } else { - m_streamTypes = findStreamTypes(m_source); - } - - m_executedTasks |= FinalizeLoad; - - m_graphStatus = Loaded; - - // Do not block gui thread while updating metadata from file. - locker->unlock(); - DirectShowMetaDataControl::updateMetadata(m_url.toString(), m_metadata); - locker->relock(); - - QCoreApplication::postEvent(this, new QEvent(QEvent::Type(FinalizedLoad))); -} - -void DirectShowPlayerService::releaseGraph() -{ - if (m_videoProbeControl) - m_videoProbeControl->flushVideoFrame(); - - if (m_graph) { - if (m_executingTask != 0) { - // {8E1C39A1-DE53-11cf-AA63-0080C744528D} - static const GUID iid_IAMOpenProgress = { - 0x8E1C39A1, 0xDE53, 0x11cf, {0xAA, 0x63, 0x00, 0x80, 0xC7, 0x44, 0x52, 0x8D} }; - - if (IAMOpenProgress *progress = com_cast<IAMOpenProgress>( - m_graph, iid_IAMOpenProgress)) { - progress->AbortOperation(); - progress->Release(); - } - m_graph->Abort(); - } - - m_pendingTasks = ReleaseGraph; - - ::SetEvent(m_taskHandle); - - m_loop->wait(&m_mutex); - DirectShowUtils::CoUninitializeIfNeeded(); - } -} - -void DirectShowPlayerService::doReleaseGraph(QMutexLocker<QMutex> *locker) -{ - Q_UNUSED(locker); - - if (IMediaControl *control = com_cast<IMediaControl>(m_graph, IID_IMediaControl)) { - control->Stop(); - control->Release(); - } - - doReleaseAudioProbe(locker); - doReleaseVideoProbe(locker); - - if (m_source) { - m_source->Release(); - m_source = nullptr; - } - - m_eventHandle = nullptr; - - m_graph->Release(); - m_graph = nullptr; - - if (m_graphBuilder) { - m_graphBuilder->Release(); - m_graphBuilder = nullptr; - } - - m_loop->wake(); -} - -QT_WARNING_PUSH -QT_WARNING_DISABLE_GCC("-Wmissing-field-initializers") - -void DirectShowPlayerService::doSetVideoProbe(QMutexLocker<QMutex> *locker) -{ - Q_UNUSED(locker); - - if (!m_graph || !m_graphBuilder) { - qCWarning(qtDirectShowPlugin, "Attempting to set a video probe without a valid graph!"); - return; - } - - // Create the sample grabber, if necessary. - if (!m_videoSampleGrabber) { - m_videoSampleGrabber = new DirectShowSampleGrabber; - connect(m_videoSampleGrabber, &DirectShowSampleGrabber::bufferAvailable, this, &DirectShowPlayerService::onVideoBufferAvailable); - } - - if (FAILED(m_graph->AddFilter(m_videoSampleGrabber->filter(), L"Video Sample Grabber"))) { - qCWarning(qtDirectShowPlugin, "Failed to add the video sample grabber into the graph!"); - return; - } - - DirectShowMediaType mediaType({ MEDIATYPE_Video, MEDIASUBTYPE_ARGB32 }); - m_videoSampleGrabber->setMediaType(&mediaType); - - // Connect source filter to sample grabber filter. - HRESULT hr = m_graphBuilder->RenderStream(nullptr, &MEDIATYPE_Video, - m_source, nullptr, m_videoSampleGrabber->filter()); - if (FAILED(hr)) { - qCWarning(qtDirectShowPlugin, "[0x%x] Failed to connect the video sample grabber", hr); - return; - } - - m_videoSampleGrabber->start(DirectShowSampleGrabber::CallbackMethod::BufferCB); -} - -void DirectShowPlayerService::doSetAudioProbe(QMutexLocker<QMutex> *locker) -{ - Q_UNUSED(locker); - - if (!m_graph) { - qCWarning(qtDirectShowPlugin, "Attempting to set an audio probe without a valid graph!"); - return; - } - - // Create the sample grabber, if necessary. - if (!m_audioSampleGrabber) { - m_audioSampleGrabber = new DirectShowSampleGrabber; - connect(m_audioSampleGrabber, &DirectShowSampleGrabber::bufferAvailable, this, &DirectShowPlayerService::onAudioBufferAvailable); - } - - static const AM_MEDIA_TYPE mediaType { MEDIATYPE_Audio, MEDIASUBTYPE_PCM }; - m_audioSampleGrabber->setMediaType(&mediaType); - - if (FAILED(m_graph->AddFilter(m_audioSampleGrabber->filter(), L"Audio Sample Grabber"))) { - qCWarning(qtDirectShowPlugin, "Failed to add the audio sample grabber into the graph!"); - return; - } - - if (!DirectShowUtils::connectFilters(m_graph, m_source, m_audioSampleGrabber->filter(), true)) { - // Connect source filter to sample grabber filter. - HRESULT hr = m_graphBuilder - ? m_graphBuilder->RenderStream(nullptr, &MEDIATYPE_Audio, - m_source, nullptr, m_audioSampleGrabber->filter()) - : E_FAIL; - if (FAILED(hr)) { - qCWarning(qtDirectShowPlugin, "[0x%x] Failed to connect the audio sample grabber", hr); - return; - } - } - - m_audioSampleGrabber->start(DirectShowSampleGrabber::CallbackMethod::BufferCB); -} - -QT_WARNING_POP - -void DirectShowPlayerService::doReleaseVideoProbe(QMutexLocker<QMutex> *locker) -{ - Q_UNUSED(locker); - - if (!m_graph) - return; - - if (!m_videoSampleGrabber) - return; - - m_videoSampleGrabber->stop(); - HRESULT hr = m_graph->RemoveFilter(m_videoSampleGrabber->filter()); - if (FAILED(hr)) { - qCWarning(qtDirectShowPlugin, "Failed to remove the video sample grabber!"); - return; - } - - m_videoSampleGrabber->deleteLater(); - m_videoSampleGrabber = nullptr; -} - -void DirectShowPlayerService::doReleaseAudioProbe(QMutexLocker<QMutex> *locker) -{ - Q_UNUSED(locker); - - if (!m_graph) - return; - - if (!m_audioSampleGrabber) - return; - - m_audioSampleGrabber->stop(); - HRESULT hr = m_graph->RemoveFilter(m_audioSampleGrabber->filter()); - if (FAILED(hr)) { - qCWarning(qtDirectShowPlugin, "Failed to remove the audio sample grabber!"); - return; - } - - m_audioSampleGrabber->deleteLater(); - m_audioSampleGrabber = nullptr; -} - -int DirectShowPlayerService::findStreamTypes(IBaseFilter *source) const -{ - QVarLengthArray<IBaseFilter *, 16> filters; - source->AddRef(); - filters.append(source); - - int streamTypes = 0; - - while (!filters.isEmpty()) { - IEnumPins *pins = nullptr; - IBaseFilter *filter = filters[filters.size() - 1]; - filters.removeLast(); - - if (SUCCEEDED(filter->EnumPins(&pins))) { - for (IPin *pin = nullptr; pins->Next(1, &pin, nullptr) == S_OK; pin->Release()) { - PIN_DIRECTION direction; - if (pin->QueryDirection(&direction) == S_OK && direction == PINDIR_OUTPUT) { - DirectShowMediaType connectionType; - if (SUCCEEDED(pin->ConnectionMediaType(&connectionType))) { - IPin *peer = nullptr; - - if (connectionType->majortype == MEDIATYPE_Audio) { - streamTypes |= AudioStream; - } else if (connectionType->majortype == MEDIATYPE_Video) { - streamTypes |= VideoStream; - } else if (SUCCEEDED(pin->ConnectedTo(&peer))) { - PIN_INFO peerInfo; - if (SUCCEEDED(peer->QueryPinInfo(&peerInfo))) - filters.append(peerInfo.pFilter); - peer->Release(); - } - } else { - streamTypes |= findStreamType(pin); - } - } - } - pins->Release(); - } - filter->Release(); - } - return streamTypes; -} - -int DirectShowPlayerService::findStreamType(IPin *pin) const -{ - IEnumMediaTypes *types; - - if (SUCCEEDED(pin->EnumMediaTypes(&types))) { - bool video = false; - bool audio = false; - bool other = false; - - for (AM_MEDIA_TYPE *type = nullptr; - types->Next(1, &type, nullptr) == S_OK; - DirectShowMediaType::deleteType(type)) { - if (type->majortype == MEDIATYPE_Audio) - audio = true; - else if (type->majortype == MEDIATYPE_Video) - video = true; - else - other = true; - } - types->Release(); - - if (other) - return 0; - else if (audio && !video) - return AudioStream; - else if (!audio && video) - return VideoStream; - else - return 0; - } else { - return 0; - } -} - -void DirectShowPlayerService::play() -{ - QMutexLocker locker(&m_mutex); - - m_pendingTasks &= ~Pause; - m_pendingTasks |= Play; - - if (m_executedTasks & Render) { - if (m_executedTasks & Stop) { - m_atEnd = false; - if (m_seekPosition == -1) { - m_dontCacheNextSeekResult = true; - m_seekPosition = 0; - m_position = 0; - m_pendingTasks |= Seek; - } - m_executedTasks ^= Stop; - } - - ::SetEvent(m_taskHandle); - } - - updateStatus(); -} - -void DirectShowPlayerService::doPlay(QMutexLocker<QMutex> *locker) -{ - // Invalidate if there is an error while loading. - if (m_error != QMediaPlayer::NoError) { - m_graphStatus = InvalidMedia; - if (!m_errorString.isEmpty()) - qWarning("%s", qPrintable(m_errorString)); - m_errorString = QString(); - QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Error))); - return; - } - - if (IMediaControl *control = com_cast<IMediaControl>(m_graph, IID_IMediaControl)) { - locker->unlock(); - HRESULT hr = control->Run(); - locker->relock(); - - control->Release(); - - if (SUCCEEDED(hr)) { - m_executedTasks |= Play; - - QCoreApplication::postEvent(this, new QEvent(QEvent::Type(StatusChange))); - } else { - m_error = QMediaPlayer::ResourceError; - m_errorString = QString(); - qWarning("DirectShowPlayerService::doPlay: Unresolved error code 0x%x (%s)", - uint(hr), qPrintable(comError(hr))); - - QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Error))); - } - } -} - -void DirectShowPlayerService::pause() -{ - QMutexLocker locker(&m_mutex); - - m_pendingTasks &= ~Play; - m_pendingTasks |= Pause; - - if (m_executedTasks & Render) { - if (m_executedTasks & Stop) { - if (m_seekPosition == -1) { - m_dontCacheNextSeekResult = true; - m_seekPosition = 0; - m_position = 0; - m_pendingTasks |= Seek; - } - m_executedTasks ^= Stop; - } - - ::SetEvent(m_taskHandle); - } - - updateStatus(); -} - -void DirectShowPlayerService::doPause(QMutexLocker<QMutex> *locker) -{ - if (IMediaControl *control = com_cast<IMediaControl>(m_graph, IID_IMediaControl)) { - locker->unlock(); - HRESULT hr = control->Pause(); - locker->relock(); - - control->Release(); - - if (SUCCEEDED(hr)) { - IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking); - if (!m_atEnd && seeking) { - LONGLONG position = 0; - - seeking->GetCurrentPosition(&position); - seeking->Release(); - - m_position = position / qt_directShowTimeScale; - } else { - m_position = 0; - m_atEnd = false; - } - - m_executedTasks |= Pause; - - QCoreApplication::postEvent(this, new QEvent(QEvent::Type(StatusChange))); - } else { - m_error = QMediaPlayer::ResourceError; - m_errorString = QString(); - qWarning("DirectShowPlayerService::doPause: Unresolved error code 0x%x (%s)", - uint(hr), qPrintable(comError(hr))); - - QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Error))); - } - } -} - -void DirectShowPlayerService::stop() -{ - QMutexLocker locker(&m_mutex); - - m_pendingTasks &= ~(Play | Pause | Seek); - - if ((m_executingTask | m_executedTasks) & (Play | Pause | Seek)) { - m_pendingTasks |= Stop; - if (m_videoProbeControl) - m_videoProbeControl->flushVideoFrame(); - - ::SetEvent(m_taskHandle); - - m_loop->wait(&m_mutex); - } - - updateStatus(); -} - -void DirectShowPlayerService::doStop(QMutexLocker<QMutex> *locker) -{ - Q_UNUSED(locker); - if (m_executedTasks & (Play | Pause)) { - if (IMediaControl *control = com_cast<IMediaControl>(m_graph, IID_IMediaControl)) { - control->Stop(); - control->Release(); - } - - m_seekPosition = 0; - m_position = 0; - m_dontCacheNextSeekResult = true; - m_pendingTasks |= Seek; - - m_executedTasks &= ~(Play | Pause); - - QCoreApplication::postEvent(this, new QEvent(QEvent::Type(StatusChange))); - } - - m_executedTasks |= Stop; - - m_loop->wake(); -} - -void DirectShowPlayerService::setRate(qreal rate) -{ - QMutexLocker locker(&m_mutex); - - m_rate = rate; - - m_pendingTasks |= SetRate; - - if (m_executedTasks & FinalizeLoad) - ::SetEvent(m_taskHandle); -} - -void DirectShowPlayerService::doSetRate(QMutexLocker<QMutex> *locker) -{ - if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) { - // Cache current values as we can't query IMediaSeeking during a seek due to the - // possibility of a deadlock when flushing the VideoSurfaceFilter. - LONGLONG currentPosition = 0; - seeking->GetCurrentPosition(¤tPosition); - m_position = currentPosition / qt_directShowTimeScale; - - LONGLONG minimum = 0; - LONGLONG maximum = 0; - m_playbackRange = SUCCEEDED(seeking->GetAvailable(&minimum, &maximum)) - ? QMediaTimeRange(minimum / qt_directShowTimeScale, maximum / qt_directShowTimeScale) - : QMediaTimeRange(); - - locker->unlock(); - HRESULT hr = seeking->SetRate(m_rate); - locker->relock(); - - if (!SUCCEEDED(hr)) { - qWarning("%s: Audio device or filter does not support rate: %.2f. " \ - "Falling back to previous value.", __FUNCTION__, m_rate); - - double rate = 0.0; - m_rate = SUCCEEDED(seeking->GetRate(&rate)) - ? rate - : 1.0; - } - - seeking->Release(); - } else if (m_rate != 1.0) { - m_rate = 1.0; - } - QCoreApplication::postEvent(this, new QEvent(QEvent::Type(RateChange))); -} - -qint64 DirectShowPlayerService::position() const -{ - QMutexLocker locker(const_cast<QMutex *>(&m_mutex)); - - if (m_graphStatus == Loaded) { - if (m_executingTask == Seek || m_executingTask == SetRate || (m_pendingTasks & Seek)) - return m_position; - if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) { - LONGLONG position = 0; - - seeking->GetCurrentPosition(&position); - seeking->Release(); - - const_cast<qint64 &>(m_position) = position / qt_directShowTimeScale; - - return m_position; - } - } - return 0; -} - -QMediaTimeRange DirectShowPlayerService::availablePlaybackRanges() const -{ - QMutexLocker locker(const_cast<QMutex *>(&m_mutex)); - - if (m_graphStatus == Loaded) { - if (m_executingTask == Seek || m_executingTask == SetRate || (m_pendingTasks & Seek)) - return m_playbackRange; - if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) { - LONGLONG minimum = 0; - LONGLONG maximum = 0; - - HRESULT hr = seeking->GetAvailable(&minimum, &maximum); - seeking->Release(); - - if (SUCCEEDED(hr)) - return QMediaTimeRange(minimum, maximum); - } - } - return QMediaTimeRange(); -} - -void DirectShowPlayerService::seek(qint64 position) -{ - QMutexLocker locker(&m_mutex); - - m_seekPosition = position; - - m_pendingTasks |= Seek; - - if (m_executedTasks & FinalizeLoad) - ::SetEvent(m_taskHandle); -} - -void DirectShowPlayerService::doSeek(QMutexLocker<QMutex> *locker) -{ - if (m_seekPosition == -1) - return; - - if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) { - LONGLONG seekPosition = LONGLONG(m_seekPosition) * qt_directShowTimeScale; - - // Cache current values as we can't query IMediaSeeking during a seek due to the - // possibility of a deadlock when flushing the VideoSurfaceFilter. - LONGLONG currentPosition = 0; - if (!m_dontCacheNextSeekResult) { - seeking->GetCurrentPosition(¤tPosition); - m_position = currentPosition / qt_directShowTimeScale; - } - - LONGLONG minimum = 0; - LONGLONG maximum = 0; - m_playbackRange = SUCCEEDED(seeking->GetAvailable(&minimum, &maximum)) - ? QMediaTimeRange( - minimum / qt_directShowTimeScale, maximum / qt_directShowTimeScale) - : QMediaTimeRange(); - - locker->unlock(); - seeking->SetPositions( - &seekPosition, AM_SEEKING_AbsolutePositioning, nullptr, AM_SEEKING_NoPositioning); - locker->relock(); - - if (!m_dontCacheNextSeekResult) { - seeking->GetCurrentPosition(¤tPosition); - m_position = currentPosition / qt_directShowTimeScale; - } - - seeking->Release(); - - QCoreApplication::postEvent(this, new QEvent(QEvent::Type(PositionChange))); - } - - m_seekPosition = -1; - m_dontCacheNextSeekResult = false; -} - -int DirectShowPlayerService::bufferStatus() const -{ -#if QT_CONFIG(wmsdk) - QMutexLocker locker(const_cast<QMutex *>(&m_mutex)); - - if (IWMReaderAdvanced2 *reader = com_cast<IWMReaderAdvanced2>( - m_source, IID_IWMReaderAdvanced2)) { - DWORD percentage = 0; - - reader->GetBufferProgress(&percentage, nullptr); - reader->Release(); - - return percentage; - } - return 0; -#else - return 0; -#endif -} - -void DirectShowPlayerService::setAudioOutput(IBaseFilter *filter) -{ - QMutexLocker locker(&m_mutex); - - if (m_graph) { - if (m_audioOutput) { - if (m_executedTasks & SetAudioOutput) { - m_pendingTasks |= ReleaseAudioOutput; - - ::SetEvent(m_taskHandle); - - m_loop->wait(&m_mutex); - } - m_audioOutput->Release(); - } - - m_audioOutput = filter; - - if (m_audioOutput) { - m_audioOutput->AddRef(); - - m_pendingTasks |= SetAudioOutput; - - if (m_executedTasks & SetSource) { - m_pendingTasks |= Render; - - ::SetEvent(m_taskHandle); - } - } else { - m_pendingTasks &= ~ SetAudioOutput; - } - } else { - if (m_audioOutput) - m_audioOutput->Release(); - - m_audioOutput = filter; - - if (m_audioOutput) - m_audioOutput->AddRef(); - } - - m_playerControl->updateAudioOutput(m_audioOutput); -} - -void DirectShowPlayerService::doReleaseAudioOutput(QMutexLocker<QMutex> *locker) -{ - Q_UNUSED(locker); - m_pendingTasks |= m_executedTasks & (Play | Pause); - - if (IMediaControl *control = com_cast<IMediaControl>(m_graph, IID_IMediaControl)) { - control->Stop(); - control->Release(); - } - - IBaseFilter *decoder = getConnected(m_audioOutput, PINDIR_INPUT); - if (!decoder) { - decoder = m_audioOutput; - decoder->AddRef(); - } - - // {DCFBDCF6-0DC2-45f5-9AB2-7C330EA09C29} - static const GUID iid_IFilterChain = { - 0xDCFBDCF6, 0x0DC2, 0x45f5, {0x9A, 0xB2, 0x7C, 0x33, 0x0E, 0xA0, 0x9C, 0x29} }; - - if (IFilterChain *chain = com_cast<IFilterChain>(m_graph, iid_IFilterChain)) { - chain->RemoveChain(decoder, m_audioOutput); - chain->Release(); - } else { - m_graph->RemoveFilter(m_audioOutput); - } - - decoder->Release(); - - m_executedTasks &= ~SetAudioOutput; - - m_loop->wake(); -} - -void DirectShowPlayerService::setVideoOutput(IBaseFilter *filter) -{ - QMutexLocker locker(&m_mutex); - - if (m_graph) { - if (m_videoOutput) { - if (m_executedTasks & SetVideoOutput) { - m_pendingTasks |= ReleaseVideoOutput; - - ::SetEvent(m_taskHandle); - - m_loop->wait(&m_mutex); - } - m_videoOutput->Release(); - } - - m_videoOutput = filter; - - if (m_videoOutput) { - m_videoOutput->AddRef(); - - m_pendingTasks |= SetVideoOutput; - - if (m_executedTasks & SetSource) { - m_pendingTasks |= Render; - - ::SetEvent(m_taskHandle); - } - } - } else { - if (m_videoOutput) - m_videoOutput->Release(); - - m_videoOutput = filter; - - if (m_videoOutput) - m_videoOutput->AddRef(); - } -} - -void DirectShowPlayerService::updateAudioProbe() -{ - QMutexLocker locker(&m_mutex); - - // Set/Activate the audio probe. - if (m_graph) { - // If we don't have a audio probe, then stop and release the audio sample grabber - if (!m_audioProbeControl && (m_executedTasks & SetAudioProbe)) { - m_pendingTasks |= ReleaseAudioProbe; - ::SetEvent(m_taskHandle); - m_loop->wait(&m_mutex); - } else if (m_audioProbeControl) { - m_pendingTasks |= SetAudioProbe; - } - } -} - -void DirectShowPlayerService::updateVideoProbe() -{ - QMutexLocker locker(&m_mutex); - - // Set/Activate the video probe. - if (m_graph) { - // If we don't have a video probe, then stop and release the video sample grabber - if (!m_videoProbeControl && (m_executedTasks & SetVideoProbe)) { - m_pendingTasks |= ReleaseVideoProbe; - ::SetEvent(m_taskHandle); - m_loop->wait(&m_mutex); - } else if (m_videoProbeControl){ - m_pendingTasks |= SetVideoProbe; - } - } -} - -void DirectShowPlayerService::doReleaseVideoOutput(QMutexLocker<QMutex> *locker) -{ - Q_UNUSED(locker); - m_pendingTasks |= m_executedTasks & (Play | Pause); - - if (IMediaControl *control = com_cast<IMediaControl>(m_graph, IID_IMediaControl)) { - control->Stop(); - control->Release(); - } - - IBaseFilter *intermediate = nullptr; - if (!SUCCEEDED(m_graph->FindFilterByName(L"Color Space Converter", &intermediate))) { - intermediate = m_videoOutput; - intermediate->AddRef(); - } - - IBaseFilter *decoder = getConnected(intermediate, PINDIR_INPUT); - if (!decoder) { - decoder = intermediate; - decoder->AddRef(); - } - - // {DCFBDCF6-0DC2-45f5-9AB2-7C330EA09C29} - static const GUID iid_IFilterChain = { - 0xDCFBDCF6, 0x0DC2, 0x45f5, {0x9A, 0xB2, 0x7C, 0x33, 0x0E, 0xA0, 0x9C, 0x29} }; - - if (IFilterChain *chain = com_cast<IFilterChain>(m_graph, iid_IFilterChain)) { - chain->RemoveChain(decoder, m_videoOutput); - chain->Release(); - } else { - m_graph->RemoveFilter(m_videoOutput); - } - - intermediate->Release(); - decoder->Release(); - - m_executedTasks &= ~SetVideoOutput; - - m_loop->wake(); -} - -void DirectShowPlayerService::customEvent(QEvent *event) -{ - if (event->type() == QEvent::Type(FinalizedLoad)) { - QMutexLocker locker(&m_mutex); - - m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable); - if (m_metadata.isEmpty()) - DirectShowMetaDataControl::updateMetadata(m_graph, m_source, m_metadata); - - m_metaDataControl->setMetadata(m_metadata); - m_metadata.clear(); - - updateStatus(); - } else if (event->type() == QEvent::Type(Error)) { - QMutexLocker locker(&m_mutex); - - if (m_error != QMediaPlayer::NoError) { - m_playerControl->updateError(m_error, m_errorString); - m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable); - m_playerControl->updateState(QMediaPlayer::StoppedState); - updateStatus(); - } - } else if (event->type() == QEvent::Type(RateChange)) { - QMutexLocker locker(&m_mutex); - - m_playerControl->updatePlaybackRate(m_rate); - } else if (event->type() == QEvent::Type(StatusChange)) { - QMutexLocker locker(&m_mutex); - - updateStatus(); - m_playerControl->updatePosition(m_position); - } else if (event->type() == QEvent::Type(DurationChange)) { - QMutexLocker locker(&m_mutex); - - m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable); - } else if (event->type() == QEvent::Type(EndOfMedia)) { - QMutexLocker locker(&m_mutex); - - if (m_atEnd) { - m_playerControl->updateState(QMediaPlayer::StoppedState); - m_playerControl->updateStatus(QMediaPlayer::EndOfMedia); - m_playerControl->updatePosition(m_position); - if (m_videoProbeControl) - m_videoProbeControl->flushVideoFrame(); - } - } else if (event->type() == QEvent::Type(PositionChange)) { - QMutexLocker locker(&m_mutex); - - if (m_playerControl->mediaStatus() == QMediaPlayer::EndOfMedia) - m_playerControl->updateStatus(QMediaPlayer::LoadedMedia); - m_playerControl->updatePosition(m_position); - // Emits only when seek has been performed. - if (m_videoRendererControl) - emit m_videoRendererControl->positionChanged(m_position); - } else { - QMediaService::customEvent(event); - } -} - -void DirectShowPlayerService::videoOutputChanged() -{ - setVideoOutput(m_videoRendererControl->filter()); -} - -QT_WARNING_PUSH -QT_WARNING_DISABLE_GCC("-Wmissing-field-initializers") - -void DirectShowPlayerService::onAudioBufferAvailable(double time, const QByteArray &data) -{ - QMutexLocker locker(&m_mutex); - if (!m_audioProbeControl || !m_audioSampleGrabber) - return; - - DirectShowMediaType mt(AM_MEDIA_TYPE { GUID_NULL }); - const bool ok = m_audioSampleGrabber->getConnectedMediaType(&mt); - if (!ok) - return; - - if (mt->majortype != MEDIATYPE_Audio) - return; - - if (mt->subtype != MEDIASUBTYPE_PCM) - return; - - const bool isWfx = ((mt->formattype == FORMAT_WaveFormatEx) && (mt->cbFormat >= sizeof(WAVEFORMATEX))); - WAVEFORMATEX *wfx = isWfx ? reinterpret_cast<WAVEFORMATEX *>(mt->pbFormat) : nullptr; - - if (!wfx) - return; - - if (wfx->wFormatTag != WAVE_FORMAT_PCM && wfx->wFormatTag != WAVE_FORMAT_EXTENSIBLE) - return; - - if ((wfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE) && (wfx->cbSize >= sizeof(WAVEFORMATEXTENSIBLE))) { - WAVEFORMATEXTENSIBLE *wfxe = reinterpret_cast<WAVEFORMATEXTENSIBLE *>(wfx); - if (wfxe->SubFormat != KSDATAFORMAT_SUBTYPE_PCM) - return; - } - - 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); - - const quint64 startTime = quint64(time * 1000.); - QAudioBuffer audioBuffer(data, - format, - startTime); - - Q_EMIT m_audioProbeControl->audioBufferProbed(audioBuffer); -} - -void DirectShowPlayerService::onVideoBufferAvailable(double time, const QByteArray &data) -{ - Q_UNUSED(time); - - QMutexLocker locker(&m_mutex); - if (!m_videoProbeControl || !m_videoSampleGrabber) - return; - - DirectShowMediaType mt(AM_MEDIA_TYPE { GUID_NULL }); - const bool ok = m_videoSampleGrabber->getConnectedMediaType(&mt); - if (!ok) - return; - - if (mt->majortype != MEDIATYPE_Video) - return; - - QVideoFrame::PixelFormat format = DirectShowMediaType::pixelFormatFromType(&mt); - if (format == QVideoFrame::Format_Invalid) { - qCWarning(qtDirectShowPlugin, "Invalid format, stopping video probes!"); - m_videoSampleGrabber->stop(); - return; - } - - const QVideoSurfaceFormat &videoFormat = DirectShowMediaType::videoFormatFromType(&mt); - if (!videoFormat.isValid()) - return; - - const QSize &size = videoFormat.frameSize(); - - const int bytesPerLine = DirectShowMediaType::bytesPerLine(videoFormat); - QVideoFrame frame(new QMemoryVideoBuffer(data, bytesPerLine), - size, - format); - - m_videoProbeControl->probeVideoFrame(frame); -} - -QT_WARNING_POP - -void DirectShowPlayerService::graphEvent(QMutexLocker<QMutex> *locker) -{ - Q_UNUSED(locker); - if (IMediaEvent *event = com_cast<IMediaEvent>(m_graph, IID_IMediaEvent)) { - long eventCode; - LONG_PTR param1; - LONG_PTR param2; - - while (event->GetEvent(&eventCode, ¶m1, ¶m2, 0) == S_OK) { - switch (eventCode) { - case EC_BUFFERING_DATA: - m_buffering = param1; - - QCoreApplication::postEvent(this, new QEvent(QEvent::Type(StatusChange))); - break; - case EC_COMPLETE: - m_executedTasks &= ~(Play | Pause); - m_executedTasks |= Stop; - - m_buffering = false; - m_atEnd = true; - - if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) { - LONGLONG position = 0; - - seeking->GetCurrentPosition(&position); - seeking->Release(); - - m_position = position / qt_directShowTimeScale; - } - - QCoreApplication::postEvent(this, new QEvent(QEvent::Type(EndOfMedia))); - break; - case EC_LENGTH_CHANGED: - if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) { - LONGLONG duration = 0; - seeking->GetDuration(&duration); - m_duration = duration / qt_directShowTimeScale; - - DWORD capabilities = 0; - seeking->GetCapabilities(&capabilities); - m_seekable = capabilities & AM_SEEKING_CanSeekAbsolute; - - seeking->Release(); - - QCoreApplication::postEvent(this, new QEvent(QEvent::Type(DurationChange))); - } - break; - default: - break; - } - - event->FreeEventParams(eventCode, param1, param2); - } - event->Release(); - } -} - -void DirectShowPlayerService::updateStatus() -{ - switch (m_graphStatus) { - case NoMedia: - m_playerControl->updateStatus(QMediaPlayer::NoMedia); - break; - case Loading: - m_playerControl->updateStatus(QMediaPlayer::LoadingMedia); - break; - case Loaded: - if ((m_executingTask | m_executedTasks) & (Play | Pause)) { - if (m_buffering) - m_playerControl->updateStatus(QMediaPlayer::BufferingMedia); - else - m_playerControl->updateStatus(QMediaPlayer::BufferedMedia); - } else { - m_playerControl->updateStatus(QMediaPlayer::LoadedMedia); - } - break; - case InvalidMedia: - m_playerControl->updateStatus(QMediaPlayer::InvalidMedia); - break; - default: - m_playerControl->updateStatus(QMediaPlayer::UnknownMediaStatus); - } -} - -bool DirectShowPlayerService::isConnected(IBaseFilter *filter, PIN_DIRECTION direction) const -{ - bool connected = false; - - IEnumPins *pins = nullptr; - - if (SUCCEEDED(filter->EnumPins(&pins))) { - for (IPin *pin = nullptr; pins->Next(1, &pin, nullptr) == S_OK; pin->Release()) { - PIN_DIRECTION dir; - if (SUCCEEDED(pin->QueryDirection(&dir)) && dir == direction) { - IPin *peer = nullptr; - if (SUCCEEDED(pin->ConnectedTo(&peer))) { - connected = true; - - peer->Release(); - } - } - } - pins->Release(); - } - return connected; -} - -IBaseFilter *DirectShowPlayerService::getConnected( - IBaseFilter *filter, PIN_DIRECTION direction) const -{ - IBaseFilter *connected = nullptr; - - IEnumPins *pins = nullptr; - - if (SUCCEEDED(filter->EnumPins(&pins))) { - for (IPin *pin = nullptr; pins->Next(1, &pin, nullptr) == S_OK; pin->Release()) { - PIN_DIRECTION dir; - if (SUCCEEDED(pin->QueryDirection(&dir)) && dir == direction) { - IPin *peer = nullptr; - if (SUCCEEDED(pin->ConnectedTo(&peer))) { - PIN_INFO info; - - if (SUCCEEDED(peer->QueryPinInfo(&info))) { - if (connected) { - qWarning("DirectShowPlayerService::getConnected: " - "Multiple connected filters"); - connected->Release(); - } - connected = info.pFilter; - } - peer->Release(); - } - } - } - pins->Release(); - } - return connected; -} - -void DirectShowPlayerService::run() -{ - QMutexLocker locker(&m_mutex); - - for (;;) { - while (m_pendingTasks == 0) { - DWORD result = 0; - - locker.unlock(); - if (m_eventHandle) { - HANDLE handles[] = { m_taskHandle, m_eventHandle }; - - result = ::WaitForMultipleObjects(2, handles, false, INFINITE); - } else { - result = ::WaitForSingleObject(m_taskHandle, INFINITE); - } - locker.relock(); - - if (result == WAIT_OBJECT_0 + 1) { - graphEvent(&locker); - } - } - - if (m_pendingTasks & ReleaseGraph) { - m_pendingTasks ^= ReleaseGraph; - m_executingTask = ReleaseGraph; - - doReleaseGraph(&locker); - //if the graph is released, we should not process other operations later - if (m_pendingTasks & Shutdown) { - m_pendingTasks = 0; - return; - } - m_pendingTasks = 0; - } else if (m_pendingTasks & Shutdown) { - return; - } else if (m_pendingTasks & ReleaseAudioOutput) { - m_pendingTasks ^= ReleaseAudioOutput; - m_executingTask = ReleaseAudioOutput; - - doReleaseAudioOutput(&locker); - } else if (m_pendingTasks & ReleaseVideoOutput) { - m_pendingTasks ^= ReleaseVideoOutput; - m_executingTask = ReleaseVideoOutput; - - doReleaseVideoOutput(&locker); - } else if (m_pendingTasks & ReleaseAudioProbe) { - m_pendingTasks ^= ReleaseAudioProbe; - m_executingTask = ReleaseAudioProbe; - - doReleaseAudioProbe(&locker); - } else if (m_pendingTasks & ReleaseVideoProbe) { - m_pendingTasks ^= ReleaseVideoProbe; - m_executingTask = ReleaseVideoProbe; - - doReleaseVideoProbe(&locker); - } else if (m_pendingTasks & SetUrlSource) { - m_pendingTasks ^= SetUrlSource; - m_executingTask = SetUrlSource; - - doSetUrlSource(&locker); - } else if (m_pendingTasks & SetStreamSource) { - m_pendingTasks ^= SetStreamSource; - m_executingTask = SetStreamSource; - - doSetStreamSource(&locker); - } else if (m_pendingTasks & SetAudioProbe) { - m_pendingTasks ^= SetAudioProbe; - m_executingTask = SetAudioProbe; - - doSetAudioProbe(&locker); - } else if (m_pendingTasks & SetVideoProbe) { - m_pendingTasks ^= SetVideoProbe; - m_executingTask = SetVideoProbe; - - doSetVideoProbe(&locker); - } else if (m_pendingTasks & Render) { - m_pendingTasks ^= Render; - m_executingTask = Render; - - doRender(&locker); - } else if (!(m_executedTasks & Render)) { - m_pendingTasks &= ~(FinalizeLoad | SetRate | Stop | Pause | Seek | Play); - } else if (m_pendingTasks & FinalizeLoad) { - m_pendingTasks ^= FinalizeLoad; - m_executingTask = FinalizeLoad; - - doFinalizeLoad(&locker); - } else if (m_pendingTasks & Stop) { - m_pendingTasks ^= Stop; - m_executingTask = Stop; - - doStop(&locker); - } else if (m_pendingTasks & SetRate) { - m_pendingTasks ^= SetRate; - m_executingTask = SetRate; - - doSetRate(&locker); - } else if (m_pendingTasks & Pause) { - m_pendingTasks ^= Pause; - m_executingTask = Pause; - - doPause(&locker); - } else if (m_pendingTasks & Seek) { - m_pendingTasks ^= Seek; - m_executingTask = Seek; - - doSeek(&locker); - } else if (m_pendingTasks & Play) { - m_pendingTasks ^= Play; - m_executingTask = Play; - - doPlay(&locker); - } - m_executingTask = 0; - } -} - -QT_END_NAMESPACE diff --git a/src/plugins/directshow/player/directshowplayerservice.h b/src/plugins/directshow/player/directshowplayerservice.h deleted file mode 100644 index 9631a2a70..000000000 --- a/src/plugins/directshow/player/directshowplayerservice.h +++ /dev/null @@ -1,240 +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 DIRECTSHOWPLAYERSERVICE_H -#define DIRECTSHOWPLAYERSERVICE_H - -#include <dshow.h> - -#include "qmediaplayer.h" -#include "qmediaservice.h" -#include "qmediatimerange.h" - -#include "directshoweventloop.h" -#include "directshowglobal.h" - -#include <QtCore/qcoreevent.h> -#include <QtCore/qmutex.h> -#include <QtCore/qurl.h> -#include <QtCore/qwaitcondition.h> - -QT_BEGIN_NAMESPACE - -class DirectShowAudioEndpointControl; -class DirectShowMetaDataControl; -class DirectShowPlayerControl; -class DirectShowVideoRendererControl; -class DirectShowAudioProbeControl; -class DirectShowVideoProbeControl; -class DirectShowSampleGrabber; - -class QMediaContent; -class QVideoWindowControl; - -class DirectShowPlayerService : public QMediaService -{ - Q_OBJECT -public: - enum StreamType - { - AudioStream = 0x01, - VideoStream = 0x02 - }; - - DirectShowPlayerService(QObject *parent = nullptr); - ~DirectShowPlayerService() override; - - QMediaControl *requestControl(const char *name) override; - void releaseControl(QMediaControl *control) override; - - void load(const QMediaContent &media, QIODevice *stream); - void play(); - void pause(); - void stop(); - - qint64 position() const; - QMediaTimeRange availablePlaybackRanges() const; - - void seek(qint64 position); - void setRate(qreal rate); - - int bufferStatus() const; - - void setAudioOutput(IBaseFilter *filter); - void setVideoOutput(IBaseFilter *filter); - -protected: - void customEvent(QEvent *event) override; - -private Q_SLOTS: - void videoOutputChanged(); - - void onAudioBufferAvailable(double time, const QByteArray &data); - void onVideoBufferAvailable(double time, const QByteArray &data); - -private: - void releaseGraph(); - void updateStatus(); - - void updateAudioProbe(); - void updateVideoProbe(); - - int findStreamTypes(IBaseFilter *source) const; - int findStreamType(IPin *pin) const; - - bool isConnected(IBaseFilter *filter, PIN_DIRECTION direction) const; - IBaseFilter *getConnected(IBaseFilter *filter, PIN_DIRECTION direction) const; - - void run(); - - void doSetUrlSource(QMutexLocker<QMutex> *locker); - void doSetStreamSource(QMutexLocker<QMutex> *locker); - void doRender(QMutexLocker<QMutex> *locker); - void doFinalizeLoad(QMutexLocker<QMutex> *locker); - void doSetRate(QMutexLocker<QMutex> *locker); - void doSeek(QMutexLocker<QMutex> *locker); - void doPlay(QMutexLocker<QMutex> *locker); - void doPause(QMutexLocker<QMutex> *locker); - void doStop(QMutexLocker<QMutex> *locker); - void doReleaseAudioOutput(QMutexLocker<QMutex> *locker); - void doReleaseVideoOutput(QMutexLocker<QMutex> *locker); - void doReleaseGraph(QMutexLocker<QMutex> *locker); - void doSetVideoProbe(QMutexLocker<QMutex> *locker); - void doSetAudioProbe(QMutexLocker<QMutex> *locker); - void doReleaseVideoProbe(QMutexLocker<QMutex> *locker); - void doReleaseAudioProbe(QMutexLocker<QMutex> *locker); - - void graphEvent(QMutexLocker<QMutex> *locker); - - enum Task - { - Shutdown = 0x00001, - SetUrlSource = 0x00002, - SetStreamSource = 0x00004, - SetSource = SetUrlSource | SetStreamSource, - SetAudioOutput = 0x00008, - SetVideoOutput = 0x00010, - SetOutputs = SetAudioOutput | SetVideoOutput, - SetAudioProbe = 0x00020, - SetVideoProbe = 0x00040, - SetProbes = SetAudioProbe | SetVideoProbe, - Render = 0x00080, - FinalizeLoad = 0x00100, - SetRate = 0x00200, - Seek = 0x00400, - Play = 0x00800, - Pause = 0x01000, - Stop = 0x02000, - ReleaseGraph = 0x04000, - ReleaseAudioOutput = 0x08000, - ReleaseVideoOutput = 0x10000, - ReleaseAudioProbe = 0x20000, - ReleaseVideoProbe = 0x40000, - ReleaseFilters = ReleaseGraph | ReleaseAudioOutput - | ReleaseVideoOutput | ReleaseAudioProbe - | ReleaseVideoProbe - }; - - enum Event - { - FinalizedLoad = QEvent::User, - Error, - RateChange, - Started, - Paused, - DurationChange, - StatusChange, - EndOfMedia, - PositionChange - }; - - enum GraphStatus - { - NoMedia, - Loading, - Loaded, - InvalidMedia - }; - - DirectShowPlayerControl *m_playerControl = nullptr; - DirectShowMetaDataControl *m_metaDataControl = nullptr; - DirectShowVideoRendererControl *m_videoRendererControl = nullptr; - QVideoWindowControl *m_videoWindowControl = nullptr; - DirectShowAudioEndpointControl *m_audioEndpointControl = nullptr; - DirectShowAudioProbeControl *m_audioProbeControl = nullptr; - DirectShowVideoProbeControl *m_videoProbeControl = nullptr; - DirectShowSampleGrabber *m_audioSampleGrabber = nullptr; - DirectShowSampleGrabber *m_videoSampleGrabber = nullptr; - - QThread *m_taskThread = nullptr; - DirectShowEventLoop *m_loop; - int m_pendingTasks = 0; - int m_executingTask = 0; - int m_executedTasks = 0; - int m_streamTypes = 0; - HANDLE m_taskHandle; - HANDLE m_eventHandle = nullptr; - GraphStatus m_graphStatus = NoMedia; - QMediaPlayer::Error m_error = QMediaPlayer::NoError; - QIODevice *m_stream = nullptr; - IFilterGraph2 *m_graph = nullptr; - ICaptureGraphBuilder2 *m_graphBuilder = nullptr; - IBaseFilter *m_source = nullptr; - IBaseFilter *m_audioOutput = nullptr; - IBaseFilter *m_videoOutput = nullptr; - qreal m_rate = 1; - qint64 m_position = 0; - qint64 m_seekPosition = -1; - qint64 m_duration = 0; - QMediaTimeRange m_playbackRange; - QUrl m_url; - QString m_errorString; - QMutex m_mutex; - bool m_buffering = false; - bool m_seekable = false; - bool m_atEnd = false; - bool m_dontCacheNextSeekResult = false; - QVariantMap m_metadata; - - friend class DirectShowPlayerServiceThread; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/plugins/directshow/player/directshowvideorenderercontrol.cpp b/src/plugins/directshow/player/directshowvideorenderercontrol.cpp deleted file mode 100644 index 0b1f0de2f..000000000 --- a/src/plugins/directshow/player/directshowvideorenderercontrol.cpp +++ /dev/null @@ -1,121 +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 <QtMultimedia/private/qtmultimediaglobal_p.h> -#include "directshowvideorenderercontrol.h" - -#include "videosurfacefilter.h" - -#if QT_CONFIG(evr) -#include "evrcustompresenter.h" -#endif - -#include <qabstractvideosurface.h> - -DirectShowVideoRendererControl::DirectShowVideoRendererControl(DirectShowEventLoop *loop, QObject *parent) - : QVideoRendererControl(parent) - , m_loop(loop) -{ -} - -DirectShowVideoRendererControl::~DirectShowVideoRendererControl() -{ -#if QT_CONFIG(evr) - if (m_evrPresenter) { - m_evrPresenter->setSurface(nullptr); - m_evrPresenter->Release(); - } -#endif - if (m_filter) - m_filter->Release(); -} - -QAbstractVideoSurface *DirectShowVideoRendererControl::surface() const -{ - return m_surface; -} - -void DirectShowVideoRendererControl::setSurface(QAbstractVideoSurface *surface) -{ - if (m_surface == surface) - return; - -#if QT_CONFIG(evr) - if (m_evrPresenter) { - m_evrPresenter->setSurface(nullptr); - m_evrPresenter->Release(); - m_evrPresenter = nullptr; - } -#endif - - if (m_filter) { - m_filter->Release(); - m_filter = nullptr; - } - - m_surface = surface; - - if (m_surface) { -#if QT_CONFIG(evr) - if (!qgetenv("QT_DIRECTSHOW_NO_EVR").toInt()) { - m_filter = com_new<IBaseFilter>(clsid_EnhancedVideoRenderer); - m_evrPresenter = new EVRCustomPresenter(m_surface); - connect(this, &DirectShowVideoRendererControl::positionChanged, m_evrPresenter, &EVRCustomPresenter::positionChanged); - if (!m_evrPresenter->isValid() || !qt_evr_setCustomPresenter(m_filter, m_evrPresenter)) { - m_filter->Release(); - m_filter = nullptr; - m_evrPresenter->Release(); - m_evrPresenter = nullptr; - } - } - - if (!m_filter) -#endif - { - m_filter = new VideoSurfaceFilter(m_surface, m_loop); - } - } - - emit filterChanged(); -} - -IBaseFilter *DirectShowVideoRendererControl::filter() -{ - return m_filter; -} diff --git a/src/plugins/directshow/player/directshowvideorenderercontrol.h b/src/plugins/directshow/player/directshowvideorenderercontrol.h deleted file mode 100644 index 9326a2748..000000000 --- a/src/plugins/directshow/player/directshowvideorenderercontrol.h +++ /dev/null @@ -1,84 +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 DIRECTSHOWVIDEORENDERERCONTROL_H -#define DIRECTSHOWVIDEORENDERERCONTROL_H - -#include <QtMultimedia/private/qtmultimediaglobal_p.h> -#include <dshow.h> - -#include "qvideorenderercontrol.h" - -#include <QtMultimedia/private/qtmultimedia-config_p.h> - -QT_BEGIN_NAMESPACE - -class DirectShowEventLoop; -#if QT_CONFIG(evr) -class EVRCustomPresenter; -#endif - -class DirectShowVideoRendererControl : public QVideoRendererControl -{ - Q_OBJECT -public: - DirectShowVideoRendererControl(DirectShowEventLoop *loop, QObject *parent = nullptr); - ~DirectShowVideoRendererControl() override; - - QAbstractVideoSurface *surface() const override; - void setSurface(QAbstractVideoSurface *surface) override; - - IBaseFilter *filter(); - -Q_SIGNALS: - void filterChanged(); - void positionChanged(qint64 position); - -private: - DirectShowEventLoop *m_loop; - QAbstractVideoSurface *m_surface = nullptr; - IBaseFilter *m_filter = nullptr; -#if QT_CONFIG(evr) - EVRCustomPresenter *m_evrPresenter = nullptr; -#endif -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/plugins/directshow/player/player.pri b/src/plugins/directshow/player/player.pri deleted file mode 100644 index ec1066db7..000000000 --- a/src/plugins/directshow/player/player.pri +++ /dev/null @@ -1,45 +0,0 @@ -INCLUDEPATH += $$PWD - -QMAKE_USE += directshow -LIBS += -lgdi32 - -mingw: LIBS_PRIVATE += -lksuser - -qtHaveModule(widgets): QT += widgets - -HEADERS += \ - $$PWD/directshowioreader.h \ - $$PWD/directshowiosource.h \ - $$PWD/directshowplayercontrol.h \ - $$PWD/directshowplayerservice.h \ - $$PWD/directshowvideorenderercontrol.h \ - $$PWD/videosurfacefilter.h \ - $$PWD/directshowaudioendpointcontrol.h \ - $$PWD/directshowmetadatacontrol.h \ - $$PWD/vmr9videowindowcontrol.h - -SOURCES += \ - $$PWD/directshowioreader.cpp \ - $$PWD/directshowiosource.cpp \ - $$PWD/directshowplayercontrol.cpp \ - $$PWD/directshowplayerservice.cpp \ - $$PWD/directshowvideorenderercontrol.cpp \ - $$PWD/videosurfacefilter.cpp \ - $$PWD/directshowaudioendpointcontrol.cpp \ - $$PWD/directshowmetadatacontrol.cpp \ - $$PWD/vmr9videowindowcontrol.cpp - -qtConfig(evr) { - include($$PWD/../../common/evr.pri) - - HEADERS += \ - $$PWD/directshowevrvideowindowcontrol.h - - SOURCES += \ - $$PWD/directshowevrvideowindowcontrol.cpp -} else { - LIBS += -lwinmm -} - -qtConfig(wshellitem): \ - QT += core-private diff --git a/src/plugins/directshow/player/videosurfacefilter.cpp b/src/plugins/directshow/player/videosurfacefilter.cpp deleted file mode 100644 index 4b7afc266..000000000 --- a/src/plugins/directshow/player/videosurfacefilter.cpp +++ /dev/null @@ -1,810 +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 "videosurfacefilter.h" - -#include "directshoweventloop.h" -#include "directshowglobal.h" -#include "directshowvideobuffer.h" - -#include <QtCore/qthread.h> -#include <QtCore/qloggingcategory.h> -#include <qabstractvideosurface.h> - -#include <mutex> - -#include <initguid.h> - -QT_BEGIN_NAMESPACE - -Q_LOGGING_CATEGORY(qLcRenderFilter, "qt.multimedia.plugins.directshow.renderfilter") - -// { e23cad72-153d-406c-bf3f-4c4b523d96f2 } -DEFINE_GUID(CLSID_VideoSurfaceFilter, -0xe23cad72, 0x153d, 0x406c, 0xbf, 0x3f, 0x4c, 0x4b, 0x52, 0x3d, 0x96, 0xf2); - -class VideoSurfaceInputPin : public DirectShowInputPin -{ - COM_REF_MIXIN -public: - VideoSurfaceInputPin(VideoSurfaceFilter *filter); - - STDMETHODIMP QueryInterface(REFIID riid, void **ppv) override; - - bool isMediaTypeSupported(const AM_MEDIA_TYPE *type) override; - bool setMediaType(const AM_MEDIA_TYPE *type) override; - - HRESULT completeConnection(IPin *pin) override; - HRESULT connectionEnded() override; - - // IPin - STDMETHODIMP ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt) override; - STDMETHODIMP Disconnect() override; - STDMETHODIMP EndOfStream() override; - STDMETHODIMP BeginFlush() override; - STDMETHODIMP EndFlush() override; - - // IMemInputPin - STDMETHODIMP GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps) override; - STDMETHODIMP Receive(IMediaSample *pMediaSample) override; - -private: - VideoSurfaceFilter *m_videoSurfaceFilter; -}; - -VideoSurfaceInputPin::VideoSurfaceInputPin(VideoSurfaceFilter *filter) - : DirectShowInputPin(filter, QStringLiteral("Input")) - , m_videoSurfaceFilter(filter) -{ -} - -HRESULT VideoSurfaceInputPin::QueryInterface(REFIID riid, void **ppv) -{ - if (ppv == nullptr) - return E_POINTER; - if (riid == IID_IUnknown) - *ppv = static_cast<IUnknown *>(static_cast<DirectShowPin *>(this)); - else if (riid == IID_IPin) - *ppv = static_cast<IPin *>(this); - else if (riid == IID_IMemInputPin) - *ppv =static_cast<IMemInputPin*>(this); - else - return E_NOINTERFACE; - AddRef(); - return S_OK; -} - -bool VideoSurfaceInputPin::isMediaTypeSupported(const AM_MEDIA_TYPE *type) -{ - return m_videoSurfaceFilter->isMediaTypeSupported(type); -} - -bool VideoSurfaceInputPin::setMediaType(const AM_MEDIA_TYPE *type) -{ - if (!DirectShowInputPin::setMediaType(type)) - return false; - - return m_videoSurfaceFilter->setMediaType(type); -} - -HRESULT VideoSurfaceInputPin::completeConnection(IPin *pin) -{ - HRESULT hr = DirectShowInputPin::completeConnection(pin); - if (FAILED(hr)) - return hr; - - return m_videoSurfaceFilter->completeConnection(pin); -} - -HRESULT VideoSurfaceInputPin::connectionEnded() -{ - HRESULT hr = DirectShowInputPin::connectionEnded(); - if (FAILED(hr)) - return hr; - - return m_videoSurfaceFilter->connectionEnded(); -} - -HRESULT VideoSurfaceInputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt) -{ - QMutexLocker lock(&m_videoSurfaceFilter->m_mutex); - return DirectShowInputPin::ReceiveConnection(pConnector, pmt); -} - -HRESULT VideoSurfaceInputPin::Disconnect() -{ - QMutexLocker lock(&m_videoSurfaceFilter->m_mutex); - return DirectShowInputPin::Disconnect(); -} - -HRESULT VideoSurfaceInputPin::EndOfStream() -{ - QMutexLocker lock(&m_videoSurfaceFilter->m_mutex); - const std::lock_guard<QRecursiveMutex> renderLocker(m_videoSurfaceFilter->m_renderMutex); - - HRESULT hr = DirectShowInputPin::EndOfStream(); - if (hr != S_OK) - return hr; - - return m_videoSurfaceFilter->EndOfStream(); -} - -HRESULT VideoSurfaceInputPin::BeginFlush() -{ - QMutexLocker lock(&m_videoSurfaceFilter->m_mutex); - { - const std::lock_guard<QRecursiveMutex> renderLocker(m_videoSurfaceFilter->m_renderMutex); - DirectShowInputPin::BeginFlush(); - m_videoSurfaceFilter->BeginFlush(); - } - m_videoSurfaceFilter->resetEOS(); - - return S_OK; -} - -HRESULT VideoSurfaceInputPin::EndFlush() -{ - QMutexLocker lock(&m_videoSurfaceFilter->m_mutex); - const std::lock_guard<QRecursiveMutex> renderLocker(m_videoSurfaceFilter->m_renderMutex); - - HRESULT hr = m_videoSurfaceFilter->EndFlush(); - if (SUCCEEDED(hr)) - hr = DirectShowInputPin::EndFlush(); - return hr; -} - -HRESULT VideoSurfaceInputPin::GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps) -{ - if (!pProps) - return E_POINTER; - - // We need at least two allocated buffers, one for holding the frame currently being - // rendered and another one to decode the following frame at the same time. - pProps->cBuffers = 2; - - return S_OK; -} - -HRESULT VideoSurfaceInputPin::Receive(IMediaSample *pMediaSample) -{ - HRESULT hr = m_videoSurfaceFilter->Receive(pMediaSample); - if (FAILED(hr)) { - QMutexLocker locker(&m_videoSurfaceFilter->m_mutex); - if (m_videoSurfaceFilter->state() != State_Stopped && !m_flushing && !m_inErrorState) { - m_videoSurfaceFilter->NotifyEvent(EC_ERRORABORT, hr, 0); - { - const std::lock_guard<QRecursiveMutex> renderLocker(m_videoSurfaceFilter->m_renderMutex); - if (m_videoSurfaceFilter->m_running && !m_videoSurfaceFilter->m_EOSDelivered) - m_videoSurfaceFilter->notifyEOS(); - } - m_inErrorState = true; - } - } - - return hr; -} - - -VideoSurfaceFilter::VideoSurfaceFilter(QAbstractVideoSurface *surface, DirectShowEventLoop *loop, QObject *parent) - : QObject(parent) - , m_loop(loop) - , m_surface(surface) - , m_renderEvent(CreateEvent(nullptr, FALSE, FALSE, nullptr)) - , m_flushEvent(CreateEvent(nullptr, TRUE, FALSE, nullptr)) -{ - supportedFormatsChanged(); - connect(surface, &QAbstractVideoSurface::supportedFormatsChanged, - this, &VideoSurfaceFilter::supportedFormatsChanged); -} - -VideoSurfaceFilter::~VideoSurfaceFilter() -{ - clearPendingSample(); - - if (m_pin) - m_pin->Release(); - - CloseHandle(m_flushEvent); - CloseHandle(m_renderEvent); -} - -HRESULT VideoSurfaceFilter::QueryInterface(REFIID riid, void **ppv) -{ - if (ppv == nullptr) - return E_POINTER; - if (riid == IID_IUnknown) - *ppv = static_cast<IUnknown *>(static_cast<DirectShowBaseFilter *>(this)); - else if (riid == IID_IPersist || riid == IID_IMediaFilter || riid == IID_IBaseFilter) - *ppv = static_cast<IBaseFilter *>(this); - else if (riid == IID_IAMFilterMiscFlags) - *ppv = static_cast<IAMFilterMiscFlags *>(this); - else - return E_NOINTERFACE; - AddRef(); - return S_OK; -} - -QList<DirectShowPin *> VideoSurfaceFilter::pins() -{ - if (!m_pin) - m_pin = new VideoSurfaceInputPin(this); - - return QList<DirectShowPin *>() << m_pin; -} - -HRESULT VideoSurfaceFilter::GetClassID(CLSID *pClassID) -{ - *pClassID = CLSID_VideoSurfaceFilter; - return S_OK; -} - -ULONG VideoSurfaceFilter::GetMiscFlags() -{ - return AM_FILTER_MISC_FLAGS_IS_RENDERER; -} - -void VideoSurfaceFilter::supportedFormatsChanged() -{ - QWriteLocker writeLocker(&m_typesLock); - - qCDebug(qLcRenderFilter, "supportedFormatChanged"); - - m_supportedTypes.clear(); - - const QList<QVideoFrame::PixelFormat> formats = m_surface->supportedPixelFormats(); - m_supportedTypes.reserve(formats.count()); - - for (QVideoFrame::PixelFormat format : formats) { - GUID subtype = DirectShowMediaType::convertPixelFormat(format); - if (!IsEqualGUID(subtype, MEDIASUBTYPE_None)) { - qCDebug(qLcRenderFilter) << " " << format; - m_supportedTypes.append(subtype); - } - } -} - -bool VideoSurfaceFilter::isMediaTypeSupported(const AM_MEDIA_TYPE *type) -{ - if (type->majortype != MEDIATYPE_Video || type->bFixedSizeSamples == FALSE) - return false; - - QReadLocker readLocker(&m_typesLock); - - for (const GUID &supportedType : m_supportedTypes) { - if (IsEqualGUID(supportedType, type->subtype)) - return true; - } - - return false; -} - -bool VideoSurfaceFilter::setMediaType(const AM_MEDIA_TYPE *type) -{ - if (!type) { - qCDebug(qLcRenderFilter, "clear media type"); - m_surfaceFormat = QVideoSurfaceFormat(); - m_bytesPerLine = 0; - return true; - } - m_surfaceFormat = DirectShowMediaType::videoFormatFromType(type); - m_bytesPerLine = DirectShowMediaType::bytesPerLine(m_surfaceFormat); - qCDebug(qLcRenderFilter) << "setMediaType -->" << m_surfaceFormat; - return m_surfaceFormat.isValid(); -} - -HRESULT VideoSurfaceFilter::completeConnection(IPin *pin) -{ - Q_UNUSED(pin); - - qCDebug(qLcRenderFilter, "completeConnection"); - - return startSurface() ? S_OK : VFW_E_TYPE_NOT_ACCEPTED; -} - -HRESULT VideoSurfaceFilter::connectionEnded() -{ - qCDebug(qLcRenderFilter, "connectionEnded"); - - stopSurface(); - - return S_OK; -} - -HRESULT VideoSurfaceFilter::Run(REFERENCE_TIME tStart) -{ - QMutexLocker locker(&m_mutex); - - if (m_state == State_Running) - return S_OK; - - qCDebug(qLcRenderFilter, "Run (start=%lli)", tStart); - - HRESULT hr = DirectShowBaseFilter::Run(tStart); - if (FAILED(hr)) - return hr; - - ResetEvent(m_flushEvent); - - IMemAllocator *allocator; - if (SUCCEEDED(m_pin->GetAllocator(&allocator))) { - allocator->Commit(); - allocator->Release(); - } - - const std::lock_guard<QRecursiveMutex> renderLocker(m_renderMutex); - - m_running = true; - - if (!m_pendingSample) - checkEOS(); - else if (!scheduleSample(m_pendingSample)) - SetEvent(m_renderEvent); // render immediately - - return S_OK; -} - -HRESULT VideoSurfaceFilter::Pause() -{ - QMutexLocker locker(&m_mutex); - - if (m_state == State_Paused) - return S_OK; - - qCDebug(qLcRenderFilter, "Pause"); - - HRESULT hr = DirectShowBaseFilter::Pause(); - if (FAILED(hr)) - return hr; - - m_renderMutex.lock(); - m_EOSDelivered = false; - m_running = false; - m_renderMutex.unlock(); - - resetEOSTimer(); - ResetEvent(m_flushEvent); - unscheduleSample(); - - IMemAllocator *allocator; - if (SUCCEEDED(m_pin->GetAllocator(&allocator))) { - allocator->Commit(); - allocator->Release(); - } - - return S_OK; -} - -HRESULT VideoSurfaceFilter::Stop() -{ - QMutexLocker locker(&m_mutex); - - if (m_state == State_Stopped) - return S_OK; - - qCDebug(qLcRenderFilter, "Stop"); - - DirectShowBaseFilter::Stop(); - - clearPendingSample(); - - m_renderMutex.lock(); - m_EOSDelivered = false; - m_running = false; - m_renderMutex.unlock(); - - SetEvent(m_flushEvent); - resetEOS(); - unscheduleSample(); - flushSurface(); - - IMemAllocator *allocator; - if (SUCCEEDED(m_pin->GetAllocator(&allocator))) { - allocator->Decommit(); - allocator->Release(); - } - - return S_OK; -} - -HRESULT VideoSurfaceFilter::EndOfStream() -{ - const std::lock_guard<QRecursiveMutex> renderLocker(m_renderMutex); - - qCDebug(qLcRenderFilter, "EndOfStream"); - - m_EOS = true; - - if (!m_pendingSample && m_running) - checkEOS(); - - stopSurface(); - return S_OK; -} - -HRESULT VideoSurfaceFilter::BeginFlush() -{ - qCDebug(qLcRenderFilter, "BeginFlush"); - - SetEvent(m_flushEvent); - unscheduleSample(); - clearPendingSample(); - - return S_OK; -} - -HRESULT VideoSurfaceFilter::EndFlush() -{ - qCDebug(qLcRenderFilter, "EndFlush"); - - ResetEvent(m_flushEvent); - return S_OK; -} - -HRESULT VideoSurfaceFilter::Receive(IMediaSample *pMediaSample) -{ - { - QMutexLocker locker(&m_mutex); - - qCDebug(qLcRenderFilter, "Receive (sample=%p)", pMediaSample); - - HRESULT hr = m_pin->DirectShowInputPin::Receive(pMediaSample); - if (hr != S_OK) { - qCDebug(qLcRenderFilter, " can't receive sample (error %X)", uint(hr)); - return E_FAIL; - } - - // If the format dynamically changed, the sample contains information about the new format. - // We need to reset the format and restart the QAbstractVideoSurface. - if (m_pin->currentSampleProperties()->pMediaType - && (!m_pin->setMediaType(m_pin->currentSampleProperties()->pMediaType) - || !restartSurface())) { - qCWarning(qLcRenderFilter, " dynamic format change failed, aborting rendering"); - NotifyEvent(EC_ERRORABORT, VFW_E_TYPE_NOT_ACCEPTED, 0); - return VFW_E_INVALIDMEDIATYPE; - } - - { - const std::lock_guard<QRecursiveMutex> locker(m_renderMutex); - - if (m_pendingSample || m_EOS) - return E_UNEXPECTED; - - if (m_running && !scheduleSample(pMediaSample)) { - qCWarning(qLcRenderFilter, " sample can't be scheduled, discarding it"); - return S_OK; - } - - m_pendingSample = pMediaSample; - m_pendingSample->AddRef(); - m_pendingSampleEndTime = m_pin->currentSampleProperties()->tStop; - } - - if (m_state == State_Paused) // Render immediately - renderPendingSample(); - } - - qCDebug(qLcRenderFilter, " waiting for render time"); - - // Wait for render time. The clock will wake us up whenever the time comes. - // It can also be interrupted by a flush, pause or stop. - HANDLE waitObjects[] = { m_flushEvent, m_renderEvent }; - DWORD result = WAIT_TIMEOUT; - while (result == WAIT_TIMEOUT) - result = WaitForMultipleObjects(2, waitObjects, FALSE, INFINITE); - - if (result == WAIT_OBJECT_0) { - // render interrupted (flush, pause, stop) - qCDebug(qLcRenderFilter, " rendering of sample %p interrupted", pMediaSample); - return S_OK; - } - - m_adviseCookie = 0; - - QMutexLocker locker(&m_mutex); - - // State might have changed just before the lock - if (m_state == State_Stopped) { - qCDebug(qLcRenderFilter, " state changed to Stopped, discarding sample (%p)", pMediaSample); - return S_OK; - } - - std::unique_lock<QRecursiveMutex> renderLocker(m_renderMutex); - - // Flush or pause might have happened just before the lock - if (m_pendingSample && m_running) { - renderLocker.unlock(); - renderPendingSample(); - renderLocker.lock(); - } else { - qCDebug(qLcRenderFilter, " discarding sample (%p)", pMediaSample); - } - - clearPendingSample(); - checkEOS(); - ResetEvent(m_renderEvent); - - return S_OK; -} - -bool VideoSurfaceFilter::scheduleSample(IMediaSample *sample) -{ - if (!sample) - return false; - - qCDebug(qLcRenderFilter, "scheduleSample (sample=%p)", sample); - - REFERENCE_TIME sampleStart, sampleEnd; - if (FAILED(sample->GetTime(&sampleStart, &sampleEnd)) || !m_clock) { - qCDebug(qLcRenderFilter, " render now"); - SetEvent(m_renderEvent); // Render immediately - return true; - } - - if (sampleEnd < sampleStart) { // incorrect times - qCWarning(qLcRenderFilter, " invalid sample times (start=%lli, end=%lli)", sampleStart, sampleEnd); - return false; - } - - HRESULT hr = m_clock->AdviseTime(m_startTime, sampleStart, (HEVENT)m_renderEvent, &m_adviseCookie); - if (FAILED(hr)) { - qCWarning(qLcRenderFilter, " clock failed to advise time (error=%X)", uint(hr)); - return false; - } - - return true; -} - -void VideoSurfaceFilter::unscheduleSample() -{ - if (m_adviseCookie) { - qCDebug(qLcRenderFilter, "unscheduleSample"); - m_clock->Unadvise(m_adviseCookie); - m_adviseCookie = 0; - } - - ResetEvent(m_renderEvent); -} - -void VideoSurfaceFilter::clearPendingSample() -{ - const std::lock_guard<QRecursiveMutex> locker(m_renderMutex); - if (m_pendingSample) { - qCDebug(qLcRenderFilter, "clearPendingSample"); - m_pendingSample->Release(); - m_pendingSample = nullptr; - } -} - -void QT_WIN_CALLBACK EOSTimerCallback(UINT, UINT, DWORD_PTR dwUser, DWORD_PTR, DWORD_PTR) -{ - VideoSurfaceFilter *that = reinterpret_cast<VideoSurfaceFilter *>(dwUser); - that->onEOSTimerTimeout(); -} - -void VideoSurfaceFilter::onEOSTimerTimeout() -{ - const std::lock_guard<QRecursiveMutex> locker(m_renderMutex); - - if (m_EOSTimer) { - m_EOSTimer = 0; - checkEOS(); - } -} - -void VideoSurfaceFilter::checkEOS() -{ - const std::lock_guard<QRecursiveMutex> locker(m_renderMutex); - - if (!m_EOS || m_EOSDelivered || m_EOSTimer) - return; - - if (!m_clock) { - notifyEOS(); - return; - } - - REFERENCE_TIME eosTime = m_startTime + m_pendingSampleEndTime; - REFERENCE_TIME currentTime; - m_clock->GetTime(¤tTime); - LONG delay = LONG((eosTime - currentTime) / 10000); - - if (delay < 1) { - notifyEOS(); - } else { - qCDebug(qLcRenderFilter, "will trigger EOS in %li", delay); - - m_EOSTimer = timeSetEvent(delay, - 1, - EOSTimerCallback, - reinterpret_cast<DWORD_PTR>(this), - TIME_ONESHOT | TIME_CALLBACK_FUNCTION | TIME_KILL_SYNCHRONOUS); - - if (!m_EOSTimer) { - qDebug("Error with timer"); - notifyEOS(); - } - } -} - -void VideoSurfaceFilter::notifyEOS() -{ - const std::lock_guard<QRecursiveMutex> locker(m_renderMutex); - - if (!m_running) - return; - - qCDebug(qLcRenderFilter, "notifyEOS, delivering EC_COMPLETE event"); - - m_EOSTimer = 0; - m_EOSDelivered = true; - NotifyEvent(EC_COMPLETE, S_OK, (LONG_PTR)(IBaseFilter *)this); -} - -void VideoSurfaceFilter::resetEOS() -{ - resetEOSTimer(); - - const std::lock_guard<QRecursiveMutex> locker(m_renderMutex); - - if (m_EOS) - qCDebug(qLcRenderFilter, "resetEOS (delivered=%s)", m_EOSDelivered ? "true" : "false"); - - m_EOS = false; - m_EOSDelivered = false; - m_pendingSampleEndTime = 0; -} - -void VideoSurfaceFilter::resetEOSTimer() -{ - if (m_EOSTimer) { - timeKillEvent(m_EOSTimer); - m_EOSTimer = 0; - } -} - -bool VideoSurfaceFilter::startSurface() -{ - if (QThread::currentThread() != thread()) { - m_loop->postEvent(this, new QEvent(QEvent::Type(StartSurface))); - m_waitSurface.wait(&m_mutex); - return m_surfaceStarted; - } - m_surfaceStarted = m_surface->start(m_surfaceFormat); - qCDebug(qLcRenderFilter, "startSurface %s", m_surfaceStarted ? "succeeded" : "failed"); - return m_surfaceStarted; -} - -void VideoSurfaceFilter::stopSurface() -{ - if (!m_surfaceStarted) - return; - - if (QThread::currentThread() != thread()) { - m_loop->postEvent(this, new QEvent(QEvent::Type(StopSurface))); - m_waitSurface.wait(&m_mutex); - } else { - qCDebug(qLcRenderFilter, "stopSurface"); - m_surface->stop(); - m_surfaceStarted = false; - } -} - -bool VideoSurfaceFilter::restartSurface() -{ - if (QThread::currentThread() != thread()) { - m_loop->postEvent(this, new QEvent(QEvent::Type(RestartSurface))); - m_waitSurface.wait(&m_mutex); - return m_surfaceStarted; - } - m_surface->stop(); - m_surfaceStarted = m_surface->start(m_surfaceFormat); - qCDebug(qLcRenderFilter, "restartSurface %s", m_surfaceStarted ? "succeeded" : "failed"); - return m_surfaceStarted; -} - -void VideoSurfaceFilter::flushSurface() -{ - if (QThread::currentThread() != thread()) { - m_loop->postEvent(this, new QEvent(QEvent::Type(FlushSurface))); - m_waitSurface.wait(&m_mutex); - } else { - qCDebug(qLcRenderFilter, "flushSurface"); - m_surface->present(QVideoFrame()); - } -} - -void VideoSurfaceFilter::renderPendingSample() -{ - if (QThread::currentThread() != thread()) { - m_loop->postEvent(this, new QEvent(QEvent::Type(RenderSample))); - m_waitSurface.wait(&m_mutex); - } else { - const std::lock_guard<QRecursiveMutex> locker(m_renderMutex); - if (!m_pendingSample) - return; - - qCDebug(qLcRenderFilter, "presentSample (sample=%p)", m_pendingSample); - - m_surface->present(QVideoFrame(new DirectShowVideoBuffer(m_pendingSample, m_bytesPerLine), - m_surfaceFormat.frameSize(), - m_surfaceFormat.pixelFormat())); - } -} - -bool VideoSurfaceFilter::event(QEvent *e) -{ - switch (e->type()) { - case StartSurface: { - QMutexLocker locker(&m_mutex); - startSurface(); - m_waitSurface.wakeAll(); - return true; - } - case StopSurface: { - QMutexLocker locker(&m_mutex); - stopSurface(); - m_waitSurface.wakeAll(); - return true; - } - case RestartSurface: { - QMutexLocker locker(&m_mutex); - restartSurface(); - m_waitSurface.wakeAll(); - return true; - } - case FlushSurface: { - QMutexLocker locker(&m_mutex); - flushSurface(); - m_waitSurface.wakeAll(); - return true; - } - case RenderSample: { - QMutexLocker locker(&m_mutex); - renderPendingSample(); - m_waitSurface.wakeAll(); - return true; - } - default: - break; - } - - return QObject::event(e); -} - -QT_END_NAMESPACE diff --git a/src/plugins/directshow/player/videosurfacefilter.h b/src/plugins/directshow/player/videosurfacefilter.h deleted file mode 100644 index 9e56f4b65..000000000 --- a/src/plugins/directshow/player/videosurfacefilter.h +++ /dev/null @@ -1,161 +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 VIDEOSURFACEFILTER_H -#define VIDEOSURFACEFILTER_H - -#include "directshowbasefilter.h" - -#include <QtCore/qcoreevent.h> -#include <QtCore/qmutex.h> -#include <qreadwritelock.h> -#include <qsemaphore.h> -#include <qwaitcondition.h> - -QT_BEGIN_NAMESPACE - -class QAbstractVideoSurface; - -class DirectShowEventLoop; -class VideoSurfaceInputPin; - -class VideoSurfaceFilter : public QObject - , public DirectShowBaseFilter - , public IAMFilterMiscFlags -{ - Q_OBJECT - COM_REF_MIXIN -public: - VideoSurfaceFilter(QAbstractVideoSurface *surface, DirectShowEventLoop *loop, QObject *parent = nullptr); - ~VideoSurfaceFilter(); - - STDMETHODIMP QueryInterface(REFIID riid, void **ppv) override; - - // DirectShowBaseFilter - QList<DirectShowPin *> pins() override; - - // IPersist - STDMETHODIMP GetClassID(CLSID *pClassID) override; - - // IMediaFilter - STDMETHODIMP Run(REFERENCE_TIME tStart) override; - STDMETHODIMP Pause() override; - STDMETHODIMP Stop() override; - - // IAMFilterMiscFlags - STDMETHODIMP_(ULONG) GetMiscFlags() override; - - // DirectShowPin (delegate) - bool isMediaTypeSupported(const AM_MEDIA_TYPE *type); - bool setMediaType(const AM_MEDIA_TYPE *type); - HRESULT completeConnection(IPin *pin); - HRESULT connectionEnded(); - - // IPin (delegate) - HRESULT EndOfStream(); - HRESULT BeginFlush(); - HRESULT EndFlush(); - - // IMemInputPin (delegate) - HRESULT Receive(IMediaSample *pMediaSample); - -private Q_SLOTS: - void supportedFormatsChanged(); - void checkEOS(); - -private: - enum Events { - StartSurface = QEvent::User, - StopSurface = QEvent::User + 1, - RestartSurface = QEvent::User + 2, - FlushSurface = QEvent::User + 3, - RenderSample = QEvent::User + 4 - }; - - bool event(QEvent *) override; - - bool startSurface(); - void stopSurface(); - bool restartSurface(); - void flushSurface(); - - bool scheduleSample(IMediaSample *sample); - void unscheduleSample(); - void renderPendingSample(); - void clearPendingSample(); - - void notifyEOS(); - void resetEOS(); - void resetEOSTimer(); - void onEOSTimerTimeout(); - - friend void QT_WIN_CALLBACK EOSTimerCallback(UINT, UINT, DWORD_PTR dwUser, DWORD_PTR, DWORD_PTR); - - QMutex m_mutex; - - DirectShowEventLoop *m_loop; - VideoSurfaceInputPin *m_pin = nullptr; - - QWaitCondition m_waitSurface; - QAbstractVideoSurface *m_surface; - QVideoSurfaceFormat m_surfaceFormat; - int m_bytesPerLine = 0; - bool m_surfaceStarted = false; - - QList<GUID> m_supportedTypes; - QReadWriteLock m_typesLock; - - QRecursiveMutex m_renderMutex; - bool m_running = false; - IMediaSample *m_pendingSample = nullptr; - REFERENCE_TIME m_pendingSampleEndTime = 0; - HANDLE m_renderEvent; - HANDLE m_flushEvent; - DWORD_PTR m_adviseCookie = 0; - - bool m_EOS = false; - bool m_EOSDelivered = false; - UINT m_EOSTimer = 0; - - friend class VideoSurfaceInputPin; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/plugins/directshow/player/vmr9videowindowcontrol.cpp b/src/plugins/directshow/player/vmr9videowindowcontrol.cpp deleted file mode 100644 index 63c945622..000000000 --- a/src/plugins/directshow/player/vmr9videowindowcontrol.cpp +++ /dev/null @@ -1,326 +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 "vmr9videowindowcontrol.h" - -#include "directshowglobal.h" - -#ifndef QT_NO_WIDGETS -#include <QtGui/QPalette> -#include <QtWidgets/QWidget> -#endif - -Vmr9VideoWindowControl::Vmr9VideoWindowControl(QObject *parent) - : QVideoWindowControl(parent) - , m_filter(com_new<IBaseFilter>(CLSID_VideoMixingRenderer9)) -{ - if (IVMRFilterConfig9 *config = com_cast<IVMRFilterConfig9>(m_filter, IID_IVMRFilterConfig9)) { - config->SetRenderingMode(VMR9Mode_Windowless); - config->SetNumberOfStreams(1); - config->Release(); - } -} - -Vmr9VideoWindowControl::~Vmr9VideoWindowControl() -{ - if (m_filter) - m_filter->Release(); -} - - -WId Vmr9VideoWindowControl::winId() const -{ - return m_windowId; - -} - -void Vmr9VideoWindowControl::setWinId(WId id) -{ - m_windowId = id; - -#ifndef QT_NO_WIDGETS - if (QWidget *widget = QWidget::find(m_windowId)) { - const QColor color = widget->palette().color(QPalette::Window); - - m_windowColor = RGB(color.red(), color.green(), color.blue()); - } -#endif - - if (IVMRWindowlessControl9 *control = com_cast<IVMRWindowlessControl9>( - m_filter, IID_IVMRWindowlessControl9)) { - control->SetVideoClippingWindow(reinterpret_cast<HWND>(m_windowId)); - control->SetBorderColor(m_windowColor); - control->Release(); - } -} - -QRect Vmr9VideoWindowControl::displayRect() const -{ - return m_displayRect; -} - -void Vmr9VideoWindowControl::setDisplayRect(const QRect &rect) -{ - m_displayRect = rect; - - if (IVMRWindowlessControl9 *control = com_cast<IVMRWindowlessControl9>( - m_filter, IID_IVMRWindowlessControl9)) { - RECT sourceRect = { 0, 0, 0, 0 }; - RECT displayRect = { rect.left(), rect.top(), rect.right() + 1, rect.bottom() + 1 }; - - control->GetNativeVideoSize(&sourceRect.right, &sourceRect.bottom, nullptr, nullptr); - - if (m_aspectRatioMode == Qt::KeepAspectRatioByExpanding) { - QSize clippedSize = rect.size(); - clippedSize.scale(sourceRect.right, sourceRect.bottom, Qt::KeepAspectRatio); - - sourceRect.left = (sourceRect.right - clippedSize.width()) / 2; - sourceRect.top = (sourceRect.bottom - clippedSize.height()) / 2; - sourceRect.right = sourceRect.left + clippedSize.width(); - sourceRect.bottom = sourceRect.top + clippedSize.height(); - } - - control->SetVideoPosition(&sourceRect, &displayRect); - control->Release(); - } -} - -bool Vmr9VideoWindowControl::isFullScreen() const -{ - return m_fullScreen; -} - -void Vmr9VideoWindowControl::setFullScreen(bool fullScreen) -{ - emit fullScreenChanged(m_fullScreen = fullScreen); -} - -void Vmr9VideoWindowControl::repaint() -{ - PAINTSTRUCT paint; - - if (HDC dc = ::BeginPaint(reinterpret_cast<HWND>(m_windowId), &paint)) { - HRESULT hr = E_FAIL; - - if (IVMRWindowlessControl9 *control = com_cast<IVMRWindowlessControl9>( - m_filter, IID_IVMRWindowlessControl9)) { - hr = control->RepaintVideo(reinterpret_cast<HWND>(m_windowId), dc); - control->Release(); - } - - if (!SUCCEEDED(hr)) { - HPEN pen = ::CreatePen(PS_SOLID, 1, m_windowColor); - HBRUSH brush = ::CreateSolidBrush(m_windowColor); - ::SelectObject(dc, pen); - ::SelectObject(dc, brush); - - ::Rectangle( - dc, - m_displayRect.left(), - m_displayRect.top(), - m_displayRect.right() + 1, - m_displayRect.bottom() + 1); - - ::DeleteObject(pen); - ::DeleteObject(brush); - } - ::EndPaint(reinterpret_cast<HWND>(m_windowId), &paint); - } -} - -QSize Vmr9VideoWindowControl::nativeSize() const -{ - QSize size; - - if (IVMRWindowlessControl9 *control = com_cast<IVMRWindowlessControl9>( - m_filter, IID_IVMRWindowlessControl9)) { - LONG width; - LONG height; - - if (control->GetNativeVideoSize(&width, &height, nullptr, nullptr) == S_OK) - size = QSize(width, height); - control->Release(); - } - return size; -} - -Qt::AspectRatioMode Vmr9VideoWindowControl::aspectRatioMode() const -{ - return m_aspectRatioMode; -} - -void Vmr9VideoWindowControl::setAspectRatioMode(Qt::AspectRatioMode mode) -{ - m_aspectRatioMode = mode; - - if (IVMRWindowlessControl9 *control = com_cast<IVMRWindowlessControl9>( - m_filter, IID_IVMRWindowlessControl9)) { - switch (mode) { - case Qt::IgnoreAspectRatio: - control->SetAspectRatioMode(VMR9ARMode_None); - break; - case Qt::KeepAspectRatio: - control->SetAspectRatioMode(VMR9ARMode_LetterBox); - break; - case Qt::KeepAspectRatioByExpanding: - control->SetAspectRatioMode(VMR9ARMode_LetterBox); - setDisplayRect(m_displayRect); - break; - default: - break; - } - control->Release(); - } -} - -int Vmr9VideoWindowControl::brightness() const -{ - return m_brightness; -} - -void Vmr9VideoWindowControl::setBrightness(int brightness) -{ - m_brightness = brightness; - - m_dirtyValues |= ProcAmpControl9_Brightness; - - setProcAmpValues(); - - emit brightnessChanged(brightness); -} - -int Vmr9VideoWindowControl::contrast() const -{ - return m_contrast; -} - -void Vmr9VideoWindowControl::setContrast(int contrast) -{ - m_contrast = contrast; - - m_dirtyValues |= ProcAmpControl9_Contrast; - - setProcAmpValues(); - - emit contrastChanged(contrast); -} - -int Vmr9VideoWindowControl::hue() const -{ - return m_hue; -} - -void Vmr9VideoWindowControl::setHue(int hue) -{ - m_hue = hue; - - m_dirtyValues |= ProcAmpControl9_Hue; - - setProcAmpValues(); - - emit hueChanged(hue); -} - -int Vmr9VideoWindowControl::saturation() const -{ - return m_saturation; -} - -void Vmr9VideoWindowControl::setSaturation(int saturation) -{ - m_saturation = saturation; - - m_dirtyValues |= ProcAmpControl9_Saturation; - - setProcAmpValues(); - - emit saturationChanged(saturation); -} - -void Vmr9VideoWindowControl::setProcAmpValues() -{ - if (IVMRMixerControl9 *control = com_cast<IVMRMixerControl9>(m_filter, IID_IVMRMixerControl9)) { - VMR9ProcAmpControl procAmp; - procAmp.dwSize = sizeof(VMR9ProcAmpControl); - procAmp.dwFlags = m_dirtyValues; - - if (m_dirtyValues & ProcAmpControl9_Brightness) { - procAmp.Brightness = scaleProcAmpValue( - control, ProcAmpControl9_Brightness, m_brightness); - } - if (m_dirtyValues & ProcAmpControl9_Contrast) { - procAmp.Contrast = scaleProcAmpValue( - control, ProcAmpControl9_Contrast, m_contrast); - } - if (m_dirtyValues & ProcAmpControl9_Hue) { - procAmp.Hue = scaleProcAmpValue( - control, ProcAmpControl9_Hue, m_hue); - } - if (m_dirtyValues & ProcAmpControl9_Saturation) { - procAmp.Saturation = scaleProcAmpValue( - control, ProcAmpControl9_Saturation, m_saturation); - } - - if (SUCCEEDED(control->SetProcAmpControl(0, &procAmp))) { - m_dirtyValues = 0; - } - - control->Release(); - } -} - -float Vmr9VideoWindowControl::scaleProcAmpValue( - IVMRMixerControl9 *control, VMR9ProcAmpControlFlags property, int value) const -{ - float scaledValue = 0.0; - - VMR9ProcAmpControlRange range; - range.dwSize = sizeof(VMR9ProcAmpControlRange); - range.dwProperty = property; - - if (SUCCEEDED(control->GetProcAmpControlRange(0, &range))) { - scaledValue = range.DefaultValue; - if (value > 0) - scaledValue += float(value) * (range.MaxValue - range.DefaultValue) / 100; - else if (value < 0) - scaledValue -= float(value) * (range.MinValue - range.DefaultValue) / 100; - } - - return scaledValue; -} diff --git a/src/plugins/directshow/player/vmr9videowindowcontrol.h b/src/plugins/directshow/player/vmr9videowindowcontrol.h deleted file mode 100644 index 2a6f008f3..000000000 --- a/src/plugins/directshow/player/vmr9videowindowcontrol.h +++ /dev/null @@ -1,108 +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 VMR9VIDEOWINDOWCONTROL_H -#define VMR9VIDEOWINDOWCONTROL_H - -#include "qvideowindowcontrol.h" - -#include <dshow.h> -#include <d3d9.h> -#include <vmr9.h> - -QT_BEGIN_NAMESPACE - -class Vmr9VideoWindowControl : public QVideoWindowControl -{ - Q_OBJECT -public: - Vmr9VideoWindowControl(QObject *parent = nullptr); - ~Vmr9VideoWindowControl() override; - - IBaseFilter *filter() const { return m_filter; } - - WId winId() const override; - void setWinId(WId id) override; - - QRect displayRect() const override; - void setDisplayRect(const QRect &rect) override; - - bool isFullScreen() const override; - void setFullScreen(bool fullScreen) override; - - void repaint() override; - - QSize nativeSize() const override; - - Qt::AspectRatioMode aspectRatioMode() const override; - void setAspectRatioMode(Qt::AspectRatioMode mode) override; - - int brightness() const override; - void setBrightness(int brightness) override; - - int contrast() const override; - void setContrast(int contrast) override; - - int hue() const override; - void setHue(int hue) override; - - int saturation() const override; - void setSaturation(int saturation) override; - -private: - void setProcAmpValues(); - float scaleProcAmpValue( - IVMRMixerControl9 *control, VMR9ProcAmpControlFlags property, int value) const; - - IBaseFilter *m_filter; - WId m_windowId = 0; - COLORREF m_windowColor = RGB(0, 0, 0); - DWORD m_dirtyValues = 0; - Qt::AspectRatioMode m_aspectRatioMode = Qt::KeepAspectRatio; - QRect m_displayRect; - int m_brightness = 0; - int m_contrast = 0; - int m_hue = 0; - int m_saturation = 0; - bool m_fullScreen = false; -}; - -QT_END_NAMESPACE - -#endif |