summaryrefslogtreecommitdiffstats
path: root/src/plugins/directshow/player
diff options
context:
space:
mode:
authorYoann Lopes <yoann.lopes@theqtcompany.com>2016-01-29 15:18:33 +0100
committerYoann Lopes <yoann.lopes@qt.io>2016-07-06 14:14:23 +0000
commit631b89ddde44dfc8b72b904d8c41368b2c02d037 (patch)
tree572f74f306ef76cffac8a6ea47b90dbb836d95a8 /src/plugins/directshow/player
parentc2f15b6071778c776b61d8807251a69adb96882e (diff)
DirectShow: refactor custom renderer filter
Refactor out some of the filter and pin logic into the DirectShowBaseFilter and DirectShowPin abstract classes. This will avoid code duplication when implementing the probe filter. The existing source filter (for qrc files) can also be refactored to use these abstract classes. Change-Id: Iaf141472dea82579ad085b3318624f9a57aa46d8 Reviewed-by: Christian Stromme <christian.stromme@qt.io>
Diffstat (limited to 'src/plugins/directshow/player')
-rw-r--r--src/plugins/directshow/player/directshoweventloop.cpp148
-rw-r--r--src/plugins/directshow/player/directshoweventloop.h76
-rw-r--r--src/plugins/directshow/player/directshowglobal.h150
-rw-r--r--src/plugins/directshow/player/directshowiosource.cpp9
-rw-r--r--src/plugins/directshow/player/directshowiosource.h5
-rw-r--r--src/plugins/directshow/player/directshowmediatype.cpp207
-rw-r--r--src/plugins/directshow/player/directshowmediatype.h76
-rw-r--r--src/plugins/directshow/player/directshowmediatypelist.cpp228
-rw-r--r--src/plugins/directshow/player/directshowmediatypelist.h68
-rw-r--r--src/plugins/directshow/player/directshowpinenum.cpp132
-rw-r--r--src/plugins/directshow/player/directshowpinenum.h71
-rw-r--r--src/plugins/directshow/player/directshowsamplescheduler.cpp435
-rw-r--r--src/plugins/directshow/player/directshowsamplescheduler.h115
-rw-r--r--src/plugins/directshow/player/mediasamplevideobuffer.cpp84
-rw-r--r--src/plugins/directshow/player/mediasamplevideobuffer.h67
-rw-r--r--src/plugins/directshow/player/player.pri13
-rw-r--r--src/plugins/directshow/player/videosurfacefilter.cpp919
-rw-r--r--src/plugins/directshow/player/videosurfacefilter.h170
18 files changed, 609 insertions, 2364 deletions
diff --git a/src/plugins/directshow/player/directshoweventloop.cpp b/src/plugins/directshow/player/directshoweventloop.cpp
deleted file mode 100644
index 87f969e42..000000000
--- a/src/plugins/directshow/player/directshoweventloop.cpp
+++ /dev/null
@@ -1,148 +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 <directshoweventloop.h>
-
-#include <QtCore/qcoreapplication.h>
-#include <QtCore/qcoreevent.h>
-
-class DirectShowPostedEvent
-{
-public:
- DirectShowPostedEvent(QObject *receiver, QEvent *event)
- : receiver(receiver)
- , event(event)
- , next(0)
- {
- }
-
- ~DirectShowPostedEvent()
- {
- delete event;
- }
-
- QObject *receiver;
- QEvent *event;
- DirectShowPostedEvent *next;
-};
-
-DirectShowEventLoop::DirectShowEventLoop(QObject *parent)
- : QObject(parent)
- , m_postsHead(0)
- , m_postsTail(0)
- , m_eventHandle(::CreateEvent(0, 0, 0, 0))
- , m_waitHandle(::CreateEvent(0, 0, 0, 0))
-{
-}
-
-DirectShowEventLoop::~DirectShowEventLoop()
-{
- ::CloseHandle(m_eventHandle);
- ::CloseHandle(m_waitHandle);
-
- for (DirectShowPostedEvent *post = m_postsHead; post; post = m_postsHead) {
- m_postsHead = m_postsHead->next;
-
- delete post;
- }
-}
-
-void DirectShowEventLoop::wait(QMutex *mutex)
-{
- ::ResetEvent(m_waitHandle);
-
- mutex->unlock();
-
- HANDLE handles[] = { m_eventHandle, m_waitHandle };
- while (::WaitForMultipleObjects(2, handles, false, INFINITE) == WAIT_OBJECT_0)
- processEvents();
-
- mutex->lock();
-}
-
-void DirectShowEventLoop::wake()
-{
- ::SetEvent(m_waitHandle);
-}
-
-void DirectShowEventLoop::postEvent(QObject *receiver, QEvent *event)
-{
- QMutexLocker locker(&m_mutex);
-
- DirectShowPostedEvent *post = new DirectShowPostedEvent(receiver, event);
-
- if (m_postsTail)
- m_postsTail->next = post;
- else
- m_postsHead = post;
-
- m_postsTail = post;
-
- QCoreApplication::postEvent(this, new QEvent(QEvent::User));
- ::SetEvent(m_eventHandle);
-}
-
-void DirectShowEventLoop::customEvent(QEvent *event)
-{
- if (event->type() == QEvent::User) {
- processEvents();
- } else {
- QObject::customEvent(event);
- }
-}
-
-void DirectShowEventLoop::processEvents()
-{
- QMutexLocker locker(&m_mutex);
-
- ::ResetEvent(m_eventHandle);
-
- while(m_postsHead) {
- DirectShowPostedEvent *post = m_postsHead;
- m_postsHead = m_postsHead->next;
-
- if (!m_postsHead)
- m_postsTail = 0;
-
- locker.unlock();
- QCoreApplication::sendEvent(post->receiver, post->event);
- delete post;
- locker.relock();
- }
-}
diff --git a/src/plugins/directshow/player/directshoweventloop.h b/src/plugins/directshow/player/directshoweventloop.h
deleted file mode 100644
index 09d986de7..000000000
--- a/src/plugins/directshow/player/directshoweventloop.h
+++ /dev/null
@@ -1,76 +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 DIRECTSHOWEVENTLOOP_H
-#define DIRECTSHOWEVENTLOOP_H
-
-#include <QtCore/qmutex.h>
-#include <QtCore/qobject.h>
-#include <QtCore/qwaitcondition.h>
-
-#include <qt_windows.h>
-
-class DirectShowPostedEvent;
-
-class DirectShowEventLoop : public QObject
-{
- Q_OBJECT
-public:
- DirectShowEventLoop(QObject *parent = 0);
- ~DirectShowEventLoop();
-
- void wait(QMutex *mutex);
- void wake();
-
- void postEvent(QObject *object, QEvent *event);
-
-protected:
- void customEvent(QEvent *event);
-
-private:
- void processEvents();
-
- DirectShowPostedEvent *m_postsHead;
- DirectShowPostedEvent *m_postsTail;
- HANDLE m_eventHandle;
- HANDLE m_waitHandle;
- QMutex m_mutex;
-};
-
-#endif
diff --git a/src/plugins/directshow/player/directshowglobal.h b/src/plugins/directshow/player/directshowglobal.h
deleted file mode 100644
index f7890c52b..000000000
--- a/src/plugins/directshow/player/directshowglobal.h
+++ /dev/null
@@ -1,150 +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 DIRECTSHOWGLOBAL_H
-#define DIRECTSHOWGLOBAL_H
-
-#include <dshow.h>
-
-#include <QtCore/qglobal.h>
-
-template <typename T> T *com_cast(IUnknown *unknown, const IID &iid)
-{
- T *iface = 0;
- return unknown && unknown->QueryInterface(iid, reinterpret_cast<void **>(&iface)) == S_OK
- ? iface
- : 0;
-}
-
-template <typename T> T *com_new(const IID &clsid)
-{
- T *object = 0;
- return CoCreateInstance(
- clsid,
- NULL,
- CLSCTX_INPROC_SERVER,
- IID_PPV_ARGS(&object)) == S_OK
- ? object
- : 0;
-}
-
-template <typename T> T *com_new(const IID &clsid, const IID &iid)
-{
- T *object = 0;
- return CoCreateInstance(
- clsid,
- NULL,
- CLSCTX_INPROC_SERVER,
- iid,
- reinterpret_cast<void **>(&object)) == S_OK
- ? object
- : 0;
-}
-
-#ifndef __IFilterGraph2_INTERFACE_DEFINED__
-#define __IFilterGraph2_INTERFACE_DEFINED__
-#define INTERFACE IFilterGraph2
-DECLARE_INTERFACE_(IFilterGraph2 ,IGraphBuilder)
-{
- STDMETHOD(AddSourceFilterForMoniker)(THIS_ IMoniker *, IBindCtx *, LPCWSTR,IBaseFilter **) PURE;
- STDMETHOD(ReconnectEx)(THIS_ IPin *, const AM_MEDIA_TYPE *) PURE;
- STDMETHOD(RenderEx)(IPin *, DWORD, DWORD *) PURE;
-};
-#undef INTERFACE
-#endif
-
-#ifndef __IAMFilterMiscFlags_INTERFACE_DEFINED__
-#define __IAMFilterMiscFlags_INTERFACE_DEFINED__
-#define INTERFACE IAMFilterMiscFlags
-DECLARE_INTERFACE_(IAMFilterMiscFlags ,IUnknown)
-{
- STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
- STDMETHOD_(ULONG,AddRef)(THIS) PURE;
- STDMETHOD_(ULONG,Release)(THIS) PURE;
- STDMETHOD_(ULONG,GetMiscFlags)(THIS) PURE;
-};
-#undef INTERFACE
-#endif
-
-#ifndef __IFileSourceFilter_INTERFACE_DEFINED__
-#define __IFileSourceFilter_INTERFACE_DEFINED__
-#define INTERFACE IFileSourceFilter
-DECLARE_INTERFACE_(IFileSourceFilter ,IUnknown)
-{
- STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
- STDMETHOD_(ULONG,AddRef)(THIS) PURE;
- STDMETHOD_(ULONG,Release)(THIS) PURE;
- STDMETHOD(Load)(THIS_ LPCOLESTR, const AM_MEDIA_TYPE *) PURE;
- STDMETHOD(GetCurFile)(THIS_ LPOLESTR *ppszFileName, AM_MEDIA_TYPE *) PURE;
-};
-#undef INTERFACE
-#endif
-
-#ifndef __IAMOpenProgress_INTERFACE_DEFINED__
-#define __IAMOpenProgress_INTERFACE_DEFINED__
-#undef INTERFACE
-#define INTERFACE IAMOpenProgress
-DECLARE_INTERFACE_(IAMOpenProgress ,IUnknown)
-{
- STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
- STDMETHOD_(ULONG,AddRef)(THIS) PURE;
- STDMETHOD_(ULONG,Release)(THIS) PURE;
- STDMETHOD(QueryProgress)(THIS_ LONGLONG *, LONGLONG *) PURE;
- STDMETHOD(AbortOperation)(THIS) PURE;
-};
-#undef INTERFACE
-#endif
-
-#ifndef __IFilterChain_INTERFACE_DEFINED__
-#define __IFilterChain_INTERFACE_DEFINED__
-#define INTERFACE IFilterChain
-DECLARE_INTERFACE_(IFilterChain ,IUnknown)
-{
- STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
- STDMETHOD_(ULONG,AddRef)(THIS) PURE;
- STDMETHOD_(ULONG,Release)(THIS) PURE;
- STDMETHOD(StartChain)(IBaseFilter *, IBaseFilter *) PURE;
- STDMETHOD(PauseChain)(IBaseFilter *, IBaseFilter *) PURE;
- STDMETHOD(StopChain)(IBaseFilter *, IBaseFilter *) PURE;
- STDMETHOD(RemoveChain)(IBaseFilter *, IBaseFilter *) PURE;
-};
-#undef INTERFACE
-#endif
-
-#endif
diff --git a/src/plugins/directshow/player/directshowiosource.cpp b/src/plugins/directshow/player/directshowiosource.cpp
index 6dee14fb0..9e71f34d0 100644
--- a/src/plugins/directshow/player/directshowiosource.cpp
+++ b/src/plugins/directshow/player/directshowiosource.cpp
@@ -41,6 +41,7 @@
#include "directshowglobal.h"
#include "directshowmediatype.h"
+#include "directshowmediatypeenum.h"
#include "directshowpinenum.h"
#include <QtCore/qcoreapplication.h>
@@ -64,8 +65,6 @@ DirectShowIOSource::DirectShowIOSource(DirectShowEventLoop *loop)
, m_peerPin(0)
, m_pinId(QLatin1String("Data"))
{
- QVector<AM_MEDIA_TYPE> mediaTypes;
-
AM_MEDIA_TYPE type =
{
MEDIATYPE_Stream, // majortype
@@ -83,10 +82,8 @@ DirectShowIOSource::DirectShowIOSource(DirectShowEventLoop *loop)
for (int i = 0; i < count; ++i) {
type.subtype = directshow_subtypes[i];
- mediaTypes.append(type);
+ m_supportedMediaTypes.append(type);
}
-
- setMediaTypes(mediaTypes);
}
DirectShowIOSource::~DirectShowIOSource()
@@ -566,7 +563,7 @@ HRESULT DirectShowIOSource::EnumMediaTypes(IEnumMediaTypes **ppEnum)
if (!ppEnum) {
return E_POINTER;
} else {
- *ppEnum = createMediaTypeEnum();
+ *ppEnum = new DirectShowMediaTypeEnum(m_supportedMediaTypes);
return S_OK;
}
diff --git a/src/plugins/directshow/player/directshowiosource.h b/src/plugins/directshow/player/directshowiosource.h
index bb90ba398..c2add6062 100644
--- a/src/plugins/directshow/player/directshowiosource.h
+++ b/src/plugins/directshow/player/directshowiosource.h
@@ -43,13 +43,11 @@
#include "directshowglobal.h"
#include "directshowioreader.h"
#include "directshowmediatype.h"
-#include "directshowmediatypelist.h"
#include <QtCore/qfile.h>
class DirectShowIOSource
- : public DirectShowMediaTypeList
- , public IBaseFilter
+ : public IBaseFilter
, public IAMFilterMiscFlags
, public IPin
{
@@ -128,6 +126,7 @@ private:
IMemAllocator *m_allocator;
IPin *m_peerPin;
DirectShowMediaType m_mediaType;
+ QList<DirectShowMediaType> m_supportedMediaTypes;
QString m_filterName;
const QString m_pinId;
QMutex m_mutex;
diff --git a/src/plugins/directshow/player/directshowmediatype.cpp b/src/plugins/directshow/player/directshowmediatype.cpp
deleted file mode 100644
index cbe1753ae..000000000
--- a/src/plugins/directshow/player/directshowmediatype.cpp
+++ /dev/null
@@ -1,207 +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 "directshowmediatype.h"
-
-namespace
-{
- struct TypeLookup
- {
- QVideoFrame::PixelFormat pixelFormat;
- GUID mediaType;
- };
-
- static const TypeLookup qt_typeLookup[] =
- {
- { QVideoFrame::Format_RGB32, /*MEDIASUBTYPE_RGB32*/ {0xe436eb7e, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}} },
- { QVideoFrame::Format_BGR24, /*MEDIASUBTYPE_RGB24*/ {0xe436eb7d, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}} },
- { QVideoFrame::Format_RGB565, /*MEDIASUBTYPE_RGB565*/ {0xe436eb7b, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}} },
- { QVideoFrame::Format_RGB555, /*MEDIASUBTYPE_RGB555*/ {0xe436eb7c, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}} },
- { QVideoFrame::Format_AYUV444, /*MEDIASUBTYPE_AYUV*/ {0x56555941, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
- { QVideoFrame::Format_YUYV, /*MEDIASUBTYPE_YUY2*/ {0x32595559, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
- { QVideoFrame::Format_UYVY, /*MEDIASUBTYPE_UYVY*/ {0x59565955, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
- { QVideoFrame::Format_IMC1, /*MEDIASUBTYPE_IMC1*/ {0x31434D49, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
- { QVideoFrame::Format_IMC2, /*MEDIASUBTYPE_IMC2*/ {0x32434D49, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
- { QVideoFrame::Format_IMC3, /*MEDIASUBTYPE_IMC3*/ {0x33434D49, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
- { QVideoFrame::Format_IMC4, /*MEDIASUBTYPE_IMC4*/ {0x34434D49, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
- { QVideoFrame::Format_YV12, /*MEDIASUBTYPE_YV12*/ {0x32315659, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
- { QVideoFrame::Format_NV12, /*MEDIASUBTYPE_NV12*/ {0x3231564E, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
- { QVideoFrame::Format_YUV420P, /*MEDIASUBTYPE_IYUV*/ {0x56555949, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} }
- };
-}
-
-void DirectShowMediaType::copy(AM_MEDIA_TYPE *target, const AM_MEDIA_TYPE &source)
-{
- *target = source;
-
- if (source.cbFormat > 0) {
- target->pbFormat = reinterpret_cast<PBYTE>(CoTaskMemAlloc(source.cbFormat));
- memcpy(target->pbFormat, source.pbFormat, source.cbFormat);
- }
- if (target->pUnk)
- target->pUnk->AddRef();
-}
-
-void DirectShowMediaType::deleteType(AM_MEDIA_TYPE *type)
-{
- freeData(type);
-
- CoTaskMemFree(type);
-}
-
-void DirectShowMediaType::freeData(AM_MEDIA_TYPE *type)
-{
- if (type->cbFormat > 0)
- CoTaskMemFree(type->pbFormat);
-
- if (type->pUnk)
- type->pUnk->Release();
-}
-
-
-GUID DirectShowMediaType::convertPixelFormat(QVideoFrame::PixelFormat format)
-{
- // MEDIASUBTYPE_None;
- static const GUID none = {
- 0xe436eb8e, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70} };
-
- const int count = sizeof(qt_typeLookup) / sizeof(TypeLookup);
-
- for (int i = 0; i < count; ++i)
- if (qt_typeLookup[i].pixelFormat == format)
- return qt_typeLookup[i].mediaType;
- return none;
-}
-
-QVideoSurfaceFormat DirectShowMediaType::formatFromType(const AM_MEDIA_TYPE &type)
-{
- const int count = sizeof(qt_typeLookup) / sizeof(TypeLookup);
-
- for (int i = 0; i < count; ++i) {
- if (IsEqualGUID(qt_typeLookup[i].mediaType, type.subtype) && type.cbFormat > 0) {
- if (IsEqualGUID(type.formattype, FORMAT_VideoInfo)) {
- VIDEOINFOHEADER *header = reinterpret_cast<VIDEOINFOHEADER *>(type.pbFormat);
-
- QVideoSurfaceFormat format(
- QSize(header->bmiHeader.biWidth, qAbs(header->bmiHeader.biHeight)),
- qt_typeLookup[i].pixelFormat);
-
- if (header->AvgTimePerFrame > 0)
- format.setFrameRate(10000 /header->AvgTimePerFrame);
-
- format.setScanLineDirection(scanLineDirection(format.pixelFormat(), header->bmiHeader));
-
- return format;
- } else if (IsEqualGUID(type.formattype, FORMAT_VideoInfo2)) {
- VIDEOINFOHEADER2 *header = reinterpret_cast<VIDEOINFOHEADER2 *>(type.pbFormat);
-
- QVideoSurfaceFormat format(
- QSize(header->bmiHeader.biWidth, qAbs(header->bmiHeader.biHeight)),
- qt_typeLookup[i].pixelFormat);
-
- if (header->AvgTimePerFrame > 0)
- format.setFrameRate(10000 / header->AvgTimePerFrame);
-
- format.setScanLineDirection(scanLineDirection(format.pixelFormat(), header->bmiHeader));
-
- return format;
- }
- }
- }
- return QVideoSurfaceFormat();
-}
-
-#define PAD_TO_DWORD(x) (((x) + 3) & ~3)
-int DirectShowMediaType::bytesPerLine(const QVideoSurfaceFormat &format)
-{
- switch (format.pixelFormat()) {
- // 32 bpp packed formats.
- case QVideoFrame::Format_RGB32:
- case QVideoFrame::Format_AYUV444:
- return format.frameWidth() * 4;
- // 24 bpp packed formats.
- case QVideoFrame::Format_RGB24:
- return PAD_TO_DWORD(format.frameWidth() * 3);
- // 16 bpp packed formats.
- case QVideoFrame::Format_RGB565:
- case QVideoFrame::Format_RGB555:
- case QVideoFrame::Format_YUYV:
- case QVideoFrame::Format_UYVY:
- return PAD_TO_DWORD(format.frameWidth() * 2);
- // Planar formats.
- case QVideoFrame::Format_IMC1:
- case QVideoFrame::Format_IMC2:
- case QVideoFrame::Format_IMC3:
- case QVideoFrame::Format_IMC4:
- case QVideoFrame::Format_YV12:
- case QVideoFrame::Format_NV12:
- case QVideoFrame::Format_YUV420P:
- return PAD_TO_DWORD(format.frameWidth());
- default:
- return 0;
- }
-}
-
-QVideoSurfaceFormat::Direction DirectShowMediaType::scanLineDirection(QVideoFrame::PixelFormat pixelFormat, const BITMAPINFOHEADER &bmiHeader)
-{
- /* MSDN http://msdn.microsoft.com/en-us/library/windows/desktop/dd318229(v=vs.85).aspx */
- /* For uncompressed RGB bitmaps:
- * if biHeight is positive, the bitmap is a bottom-up DIB with the origin at the lower left corner.
- * If biHeight is negative, the bitmap is a top-down DIB with the origin at the upper left corner.
- *
- * For YUV bitmaps:
- * the bitmap is always top-down, regardless of the sign of biHeight.
- * Decoders should offer YUV formats with postive biHeight, but for backward compatibility they should accept YUV formats with either positive or negative biHeight.
- *
- * For compressed formats:
- * biHeight must be positive, regardless of image orientation.
- */
- switch (pixelFormat)
- {
- case QVideoFrame::Format_RGB32:
- case QVideoFrame::Format_BGR24:
- case QVideoFrame::Format_RGB565:
- case QVideoFrame::Format_RGB555:
- return bmiHeader.biHeight < 0
- ? QVideoSurfaceFormat::TopToBottom
- : QVideoSurfaceFormat::BottomToTop;
- default:
- return QVideoSurfaceFormat::TopToBottom;
- }
-}
diff --git a/src/plugins/directshow/player/directshowmediatype.h b/src/plugins/directshow/player/directshowmediatype.h
deleted file mode 100644
index cf5ac73aa..000000000
--- a/src/plugins/directshow/player/directshowmediatype.h
+++ /dev/null
@@ -1,76 +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 DIRECTSHOWMEDIATYPE_H
-#define DIRECTSHOWMEDIATYPE_H
-
-#include <dshow.h>
-
-#include <qvideosurfaceformat.h>
-
-#include <dvdmedia.h>
-
-class DirectShowMediaType : public AM_MEDIA_TYPE
-{
-public:
- DirectShowMediaType() { memset(this, 0, sizeof(DirectShowMediaType)); }
- DirectShowMediaType(const AM_MEDIA_TYPE &type) { copy(this, type); }
- DirectShowMediaType(const DirectShowMediaType &other) { copy(this, other); }
- DirectShowMediaType &operator =(const AM_MEDIA_TYPE &type) {
- freeData(this); copy(this, type); return *this; }
- DirectShowMediaType &operator =(const DirectShowMediaType &other) {
- freeData(this); copy(this, other); return *this; }
- ~DirectShowMediaType() { freeData(this); }
-
- void clear() { freeData(this); memset(this, 0, sizeof(DirectShowMediaType)); }
-
- static void copy(AM_MEDIA_TYPE *target, const AM_MEDIA_TYPE &source);
- static void freeData(AM_MEDIA_TYPE *type);
- static void deleteType(AM_MEDIA_TYPE *type);
-
- static GUID convertPixelFormat(QVideoFrame::PixelFormat format);
- static QVideoSurfaceFormat formatFromType(const AM_MEDIA_TYPE &type);
-
- static int bytesPerLine(const QVideoSurfaceFormat &format);
-
-private:
- static QVideoSurfaceFormat::Direction scanLineDirection(QVideoFrame::PixelFormat pixelFormat, const BITMAPINFOHEADER &bmiHeader);
-};
-
-#endif
diff --git a/src/plugins/directshow/player/directshowmediatypelist.cpp b/src/plugins/directshow/player/directshowmediatypelist.cpp
deleted file mode 100644
index 8d5e572ca..000000000
--- a/src/plugins/directshow/player/directshowmediatypelist.cpp
+++ /dev/null
@@ -1,228 +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 "directshowmediatypelist.h"
-
-#include "directshowmediatype.h"
-#include "videosurfacefilter.h"
-
-
-class DirectShowMediaTypeEnum : public IEnumMediaTypes
-{
-public:
- DirectShowMediaTypeEnum(DirectShowMediaTypeList *list, int token, int index = 0);
- virtual ~DirectShowMediaTypeEnum();
-
- // IUnknown
- HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
- ULONG STDMETHODCALLTYPE AddRef();
- ULONG STDMETHODCALLTYPE Release();
-
- // IEnumMediaTypes
- HRESULT STDMETHODCALLTYPE Next(
- ULONG cMediaTypes, AM_MEDIA_TYPE **ppMediaTypes, ULONG *pcFetched);
- HRESULT STDMETHODCALLTYPE Skip(ULONG cMediaTypes);
- HRESULT STDMETHODCALLTYPE Reset();
-
- HRESULT STDMETHODCALLTYPE Clone(IEnumMediaTypes **ppEnum);
-
-private:
- LONG m_ref;
- DirectShowMediaTypeList *m_list;
- int m_mediaTypeToken;
- int m_index;
-};
-
-
-DirectShowMediaTypeEnum::DirectShowMediaTypeEnum(
- DirectShowMediaTypeList *list, int token, int index)
- : m_ref(1)
- , m_list(list)
- , m_mediaTypeToken(token)
- , m_index(index)
-{
- m_list->AddRef();
-}
-
-DirectShowMediaTypeEnum::~DirectShowMediaTypeEnum()
-{
- m_list->Release();
-}
-
-HRESULT DirectShowMediaTypeEnum::QueryInterface(REFIID riid, void **ppvObject)
-{
- if (!ppvObject) {
- return E_POINTER;
- } else if (riid == IID_IUnknown
- || riid == IID_IEnumMediaTypes) {
- *ppvObject = static_cast<IEnumMediaTypes *>(this);
- } else {
- *ppvObject = 0;
-
- return E_NOINTERFACE;
- }
-
- AddRef();
-
- return S_OK;
-}
-
-ULONG DirectShowMediaTypeEnum::AddRef()
-{
- return InterlockedIncrement(&m_ref);
-}
-
-ULONG DirectShowMediaTypeEnum::Release()
-{
- ULONG ref = InterlockedDecrement(&m_ref);
-
- if (ref == 0) {
- delete this;
- }
-
- return ref;
-}
-
-HRESULT DirectShowMediaTypeEnum::Next(
- ULONG cMediaTypes, AM_MEDIA_TYPE **ppMediaTypes, ULONG *pcFetched)
-{
- return m_list->nextMediaType(m_mediaTypeToken, &m_index, cMediaTypes, ppMediaTypes, pcFetched);
-}
-
-HRESULT DirectShowMediaTypeEnum::Skip(ULONG cMediaTypes)
-{
- return m_list->skipMediaType(m_mediaTypeToken, &m_index, cMediaTypes);
-}
-
-HRESULT DirectShowMediaTypeEnum::Reset()
-{
- m_mediaTypeToken = m_list->currentMediaTypeToken();
- m_index = 0;
-
- return S_OK;
-}
-
-HRESULT DirectShowMediaTypeEnum::Clone(IEnumMediaTypes **ppEnum)
-{
- return m_list->cloneMediaType(m_mediaTypeToken, m_index, ppEnum);
-}
-
-
-DirectShowMediaTypeList::DirectShowMediaTypeList()
- : m_mediaTypeToken(0)
-{
-}
-
-DirectShowMediaTypeList::~DirectShowMediaTypeList()
-{
-}
-
-IEnumMediaTypes *DirectShowMediaTypeList::createMediaTypeEnum()
-{
- return new DirectShowMediaTypeEnum(this, m_mediaTypeToken, 0);
-}
-
-
-void DirectShowMediaTypeList::setMediaTypes(const QVector<AM_MEDIA_TYPE> &types)
-{
- ++m_mediaTypeToken;
-
- m_mediaTypes = types;
-}
-
-
-int DirectShowMediaTypeList::currentMediaTypeToken()
-{
- return m_mediaTypeToken;
-}
-
-HRESULT DirectShowMediaTypeList::nextMediaType(
- int token, int *index, ULONG count, AM_MEDIA_TYPE **types, ULONG *fetchedCount)
-{
- if (!types || (count != 1 && !fetchedCount)) {
- return E_POINTER;
- } else if (m_mediaTypeToken != token) {
- return VFW_E_ENUM_OUT_OF_SYNC;
- } else {
- int boundedCount = qBound<int>(0, count, m_mediaTypes.count() - *index);
-
- for (int i = 0; i < boundedCount; ++i, ++(*index)) {
- types[i] = reinterpret_cast<AM_MEDIA_TYPE *>(CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE)));
-
- if (types[i]) {
- DirectShowMediaType::copy(types[i], m_mediaTypes.at(*index));
- } else {
- for (--i; i >= 0; --i)
- CoTaskMemFree(types[i]);
-
- if (fetchedCount)
- *fetchedCount = 0;
-
- return E_OUTOFMEMORY;
- }
- }
- if (fetchedCount)
- *fetchedCount = boundedCount;
-
- return boundedCount == int(count) ? S_OK : S_FALSE;
- }
-}
-
-HRESULT DirectShowMediaTypeList::skipMediaType(int token, int *index, ULONG count)
-{
- if (m_mediaTypeToken != token) {
- return VFW_E_ENUM_OUT_OF_SYNC;
- } else {
- *index = qMin<int>(*index + count, m_mediaTypes.size());
-
- return *index < m_mediaTypes.size() ? S_OK : S_FALSE;
- }
-}
-
-HRESULT DirectShowMediaTypeList::cloneMediaType(int token, int index, IEnumMediaTypes **enumeration)
-{
- if (m_mediaTypeToken != token) {
- return VFW_E_ENUM_OUT_OF_SYNC;
- } else {
- *enumeration = new DirectShowMediaTypeEnum(this, token, index);
-
- return S_OK;
- }
-}
-
diff --git a/src/plugins/directshow/player/directshowmediatypelist.h b/src/plugins/directshow/player/directshowmediatypelist.h
deleted file mode 100644
index c6dac0e9b..000000000
--- a/src/plugins/directshow/player/directshowmediatypelist.h
+++ /dev/null
@@ -1,68 +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 DIRECTSHOWMEDIATYPELIST_H
-#define DIRECTSHOWMEDIATYPELIST_H
-
-#include <dshow.h>
-
-#include <QtCore/qvector.h>
-
-class DirectShowMediaTypeList : public IUnknown
-{
-public:
- DirectShowMediaTypeList();
- virtual ~DirectShowMediaTypeList();
-
- IEnumMediaTypes *createMediaTypeEnum();
-
- void setMediaTypes(const QVector<AM_MEDIA_TYPE> &types);
-
- virtual int currentMediaTypeToken();
- virtual HRESULT nextMediaType(
- int token, int *index, ULONG count, AM_MEDIA_TYPE **types, ULONG *fetchedCount);
- virtual HRESULT skipMediaType(int token, int *index, ULONG count);
- virtual HRESULT cloneMediaType(int token, int index, IEnumMediaTypes **enumeration);
-
-private:
- int m_mediaTypeToken;
- QVector<AM_MEDIA_TYPE> m_mediaTypes;
-};
-
-#endif
diff --git a/src/plugins/directshow/player/directshowpinenum.cpp b/src/plugins/directshow/player/directshowpinenum.cpp
deleted file mode 100644
index 7ef986a26..000000000
--- a/src/plugins/directshow/player/directshowpinenum.cpp
+++ /dev/null
@@ -1,132 +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 "directshowpinenum.h"
-
-
-DirectShowPinEnum::DirectShowPinEnum(const QList<IPin *> &pins)
- : m_ref(1)
- , m_pins(pins)
- , m_index(0)
-{
- for (IPin *pin : qAsConst(m_pins))
- pin->AddRef();
-}
-
-DirectShowPinEnum::~DirectShowPinEnum()
-{
- for (IPin *pin : qAsConst(m_pins))
- pin->Release();
-}
-
-HRESULT DirectShowPinEnum::QueryInterface(REFIID riid, void **ppvObject)
-{
- if (riid == IID_IUnknown
- || riid == IID_IEnumPins) {
- AddRef();
-
- *ppvObject = static_cast<IEnumPins *>(this);
-
- return S_OK;
- } else {
- *ppvObject = 0;
-
- return E_NOINTERFACE;
- }
-}
-
-ULONG DirectShowPinEnum::AddRef()
-{
- return InterlockedIncrement(&m_ref);
-}
-
-ULONG DirectShowPinEnum::Release()
-{
- ULONG ref = InterlockedDecrement(&m_ref);
-
- if (ref == 0) {
- delete this;
- }
-
- return ref;
-}
-
-HRESULT DirectShowPinEnum::Next(ULONG cPins, IPin **ppPins, ULONG *pcFetched)
-{
- if (ppPins && (pcFetched || cPins == 1)) {
- ULONG count = qBound<ULONG>(0, cPins, m_pins.count() - m_index);
-
- for (ULONG i = 0; i < count; ++i, ++m_index) {
- ppPins[i] = m_pins.at(m_index);
- ppPins[i]->AddRef();
- }
-
- if (pcFetched)
- *pcFetched = count;
-
- return count == cPins ? S_OK : S_FALSE;
- } else {
- return E_POINTER;
- }
-}
-
-HRESULT DirectShowPinEnum::Skip(ULONG cPins)
-{
- m_index = qMin(int(m_index + cPins), m_pins.count());
-
- return m_index < m_pins.count() ? S_OK : S_FALSE;
-}
-
-HRESULT DirectShowPinEnum::Reset()
-{
- m_index = 0;
-
- return S_OK;
-}
-
-HRESULT DirectShowPinEnum::Clone(IEnumPins **ppEnum)
-{
- if (ppEnum) {
- *ppEnum = new DirectShowPinEnum(m_pins);
-
- return S_OK;
- } else {
- return E_POINTER;
- }
-}
diff --git a/src/plugins/directshow/player/directshowpinenum.h b/src/plugins/directshow/player/directshowpinenum.h
deleted file mode 100644
index 8859f49a5..000000000
--- a/src/plugins/directshow/player/directshowpinenum.h
+++ /dev/null
@@ -1,71 +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 DIRECTSHOWPINENUM_H
-#define DIRECTSHOWPINENUM_H
-
-#include <dshow.h>
-
-#include <QtCore/qlist.h>
-
-
-class DirectShowPinEnum : public IEnumPins
-{
-public:
- DirectShowPinEnum(const QList<IPin *> &pins);
- virtual ~DirectShowPinEnum();
-
- // IUnknown
- HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
- ULONG STDMETHODCALLTYPE AddRef();
- ULONG STDMETHODCALLTYPE Release();
-
- // IEnumPins
- HRESULT STDMETHODCALLTYPE Next(ULONG cPins, IPin **ppPins, ULONG *pcFetched);
- HRESULT STDMETHODCALLTYPE Skip(ULONG cPins);
- HRESULT STDMETHODCALLTYPE Reset();
- HRESULT STDMETHODCALLTYPE Clone(IEnumPins **ppEnum);
-
-private:
- LONG m_ref;
- QList<IPin *> m_pins;
- int m_index;
-};
-
-#endif
diff --git a/src/plugins/directshow/player/directshowsamplescheduler.cpp b/src/plugins/directshow/player/directshowsamplescheduler.cpp
deleted file mode 100644
index 0aa257f7f..000000000
--- a/src/plugins/directshow/player/directshowsamplescheduler.cpp
+++ /dev/null
@@ -1,435 +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 "directshowsamplescheduler.h"
-
-#include <QtCore/qcoreapplication.h>
-#include <QtCore/qcoreevent.h>
-
-class DirectShowTimedSample
-{
-public:
- DirectShowTimedSample(IMediaSample *sample)
- : m_next(0)
- , m_sample(sample)
- , m_cookie(0)
- , m_lastSample(false)
- {
- m_sample->AddRef();
- }
-
- ~DirectShowTimedSample()
- {
- m_sample->Release();
- }
-
- IMediaSample *sample() const { return m_sample; }
-
- DirectShowTimedSample *nextSample() const { return m_next; }
- void setNextSample(DirectShowTimedSample *sample) { Q_ASSERT(!m_next); m_next = sample; }
-
- DirectShowTimedSample *remove() {
- DirectShowTimedSample *next = m_next; delete this; return next; }
-
- bool schedule(IReferenceClock *clock, REFERENCE_TIME startTime, HANDLE handle);
- void unschedule(IReferenceClock *clock);
-
- bool isReady(IReferenceClock *clock) const;
-
- bool isLast() const { return m_lastSample; }
- void setLast() { m_lastSample = true; }
-
-private:
- DirectShowTimedSample *m_next;
- IMediaSample *m_sample;
- DWORD_PTR m_cookie;
- bool m_lastSample;
-};
-
-bool DirectShowTimedSample::schedule(
- IReferenceClock *clock, REFERENCE_TIME startTime, HANDLE handle)
-{
- REFERENCE_TIME sampleStartTime;
- REFERENCE_TIME sampleEndTime;
- if (m_sample->GetTime(&sampleStartTime, &sampleEndTime) == S_OK) {
- if (clock->AdviseTime(
- startTime, sampleStartTime, reinterpret_cast<HEVENT>(handle), &m_cookie) == S_OK) {
- return true;
- }
- }
- return false;
-}
-
-void DirectShowTimedSample::unschedule(IReferenceClock *clock)
-{
- clock->Unadvise(m_cookie);
-}
-
-bool DirectShowTimedSample::isReady(IReferenceClock *clock) const
-{
- REFERENCE_TIME sampleStartTime;
- REFERENCE_TIME sampleEndTime;
- REFERENCE_TIME currentTime;
- if (m_sample->GetTime(&sampleStartTime, &sampleEndTime) == S_OK) {
- if (clock->GetTime(&currentTime) == S_OK)
- return currentTime >= sampleStartTime;
- }
- return true;
-}
-
-DirectShowSampleScheduler::DirectShowSampleScheduler(IUnknown *pin, QObject *parent)
- : QObject(parent)
- , m_pin(pin)
- , m_clock(0)
- , m_allocator(0)
- , m_head(0)
- , m_tail(0)
- , m_maximumSamples(1)
- , m_state(Stopped)
- , m_startTime(0)
- , m_timeoutEvent(::CreateEvent(0, 0, 0, 0))
- , m_flushEvent(::CreateEvent(0, 0, 0, 0))
-{
- m_semaphore.release(m_maximumSamples);
-}
-
-DirectShowSampleScheduler::~DirectShowSampleScheduler()
-{
- ::CloseHandle(m_timeoutEvent);
- ::CloseHandle(m_flushEvent);
-
- Q_ASSERT(!m_clock);
- Q_ASSERT(!m_allocator);
-}
-
-HRESULT DirectShowSampleScheduler::QueryInterface(REFIID riid, void **ppvObject)
-{
- return m_pin->QueryInterface(riid, ppvObject);
-}
-
-ULONG DirectShowSampleScheduler::AddRef()
-{
- return m_pin->AddRef();
-}
-
-ULONG DirectShowSampleScheduler::Release()
-{
- return m_pin->Release();
-}
-
-// IMemInputPin
-HRESULT DirectShowSampleScheduler::GetAllocator(IMemAllocator **ppAllocator)
-{
- if (!ppAllocator) {
- return E_POINTER;
- } else {
- QMutexLocker locker(&m_mutex);
-
- if (!m_allocator) {
- return VFW_E_NO_ALLOCATOR;
- } else {
- *ppAllocator = m_allocator;
-
- return S_OK;
- }
- }
-}
-
-HRESULT DirectShowSampleScheduler::NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly)
-{
- Q_UNUSED(bReadOnly);
-
- HRESULT hr;
- ALLOCATOR_PROPERTIES properties;
-
- if (!pAllocator) {
- if (m_allocator)
- m_allocator->Release();
-
- m_allocator = 0;
-
- return S_OK;
- } else if ((hr = pAllocator->GetProperties(&properties)) != S_OK) {
- return hr;
- } else {
- if (properties.cBuffers == 1) {
- ALLOCATOR_PROPERTIES actual;
-
- properties.cBuffers = 2;
- if ((hr = pAllocator->SetProperties(&properties, &actual)) != S_OK)
- return hr;
- }
-
- QMutexLocker locker(&m_mutex);
-
- if (m_allocator)
- m_allocator->Release();
-
- m_allocator = pAllocator;
- m_allocator->AddRef();
-
- return S_OK;
- }
-}
-
-HRESULT DirectShowSampleScheduler::GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps)
-{
- if (!pProps)
- return E_POINTER;
-
- pProps->cBuffers = 2;
-
- return S_OK;
-}
-
-HRESULT DirectShowSampleScheduler::Receive(IMediaSample *pSample)
-{
- if (!pSample)
- return E_POINTER;
-
- m_semaphore.acquire(1);
-
- QMutexLocker locker(&m_mutex);
-
- if (m_state & Flushing) {
- m_semaphore.release(1);
-
- return S_FALSE;
- } else if (m_state == Stopped) {
- m_semaphore.release();
-
- return VFW_E_WRONG_STATE;
- } else {
- DirectShowTimedSample *timedSample = new DirectShowTimedSample(pSample);
-
- if (m_tail)
- m_tail->setNextSample(timedSample);
- else
- m_head = timedSample;
-
- m_tail = timedSample;
-
- if (m_state == Running) {
- if (!timedSample->schedule(m_clock, m_startTime, m_timeoutEvent)) {
- // Timing information is unavailable, so schedule frames immediately.
- QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
- } else {
- locker.unlock();
- HANDLE handles[] = { m_flushEvent, m_timeoutEvent };
- DWORD result = ::WaitForMultipleObjects(2, handles, FALSE, INFINITE);
- locker.relock();
-
- if (result == WAIT_OBJECT_0 + 1)
- QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
- }
- } else if (m_tail == m_head) {
- // If this is the first frame make it available.
- QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
-
- if (m_state == Paused) {
- ::ResetEvent(m_timeoutEvent);
-
- locker.unlock();
- HANDLE handles[] = { m_flushEvent, m_timeoutEvent };
- ::WaitForMultipleObjects(2, handles, FALSE, INFINITE);
- locker.relock();
- }
- }
-
- return S_OK;
- }
-}
-
-HRESULT DirectShowSampleScheduler::ReceiveMultiple(
- IMediaSample **pSamples, long nSamples, long *nSamplesProcessed)
-{
- if (!pSamples || !nSamplesProcessed)
- return E_POINTER;
-
- for (*nSamplesProcessed = 0; *nSamplesProcessed < nSamples; ++(*nSamplesProcessed)) {
- HRESULT hr = Receive(pSamples[*nSamplesProcessed]);
-
- if (hr != S_OK)
- return hr;
- }
- return S_OK;
-}
-
-HRESULT DirectShowSampleScheduler::ReceiveCanBlock()
-{
- return S_OK;
-}
-
-void DirectShowSampleScheduler::run(REFERENCE_TIME startTime)
-{
- QMutexLocker locker(&m_mutex);
-
- m_state = (m_state & Flushing) | Running;
- m_startTime = startTime;
-
- for (DirectShowTimedSample *sample = m_head; sample; sample = sample->nextSample()) {
- sample->schedule(m_clock, m_startTime, m_timeoutEvent);
- }
-
- if (!(m_state & Flushing))
- ::ResetEvent(m_flushEvent);
-
- if (!m_head)
- ::SetEvent(m_timeoutEvent);
-
-}
-
-void DirectShowSampleScheduler::pause()
-{
- QMutexLocker locker(&m_mutex);
-
- m_state = (m_state & Flushing) | Paused;
-
- for (DirectShowTimedSample *sample = m_head; sample; sample = sample->nextSample())
- sample->unschedule(m_clock);
-
- if (!(m_state & Flushing))
- ::ResetEvent(m_flushEvent);
-}
-
-void DirectShowSampleScheduler::stop()
-{
- QMutexLocker locker(&m_mutex);
-
- m_state = m_state & Flushing;
-
- for (DirectShowTimedSample *sample = m_head; sample; sample = sample->remove()) {
- sample->unschedule(m_clock);
-
- m_semaphore.release(1);
- }
-
- m_head = 0;
- m_tail = 0;
-
- ::SetEvent(m_flushEvent);
-}
-
-void DirectShowSampleScheduler::setFlushing(bool flushing)
-{
- QMutexLocker locker(&m_mutex);
-
- const bool isFlushing = m_state & Flushing;
-
- if (isFlushing != flushing) {
- if (flushing) {
- m_state |= Flushing;
-
- for (DirectShowTimedSample *sample = m_head; sample; sample = sample->remove()) {
- sample->unschedule(m_clock);
-
- m_semaphore.release(1);
- }
- m_head = 0;
- m_tail = 0;
-
- ::SetEvent(m_flushEvent);
- } else {
- m_state &= ~Flushing;
-
- if (m_state != Stopped)
- ::ResetEvent(m_flushEvent);
- }
- }
-}
-
-void DirectShowSampleScheduler::setClock(IReferenceClock *clock)
-{
- QMutexLocker locker(&m_mutex);
-
- if (m_clock)
- m_clock->Release();
-
- m_clock = clock;
-
- if (m_clock)
- m_clock->AddRef();
-}
-
-IMediaSample *DirectShowSampleScheduler::takeSample(bool *eos)
-{
- QMutexLocker locker(&m_mutex);
-
- if (m_head && m_head->isReady(m_clock)) {
- IMediaSample *sample = m_head->sample();
- sample->AddRef();
-
- *eos = m_head->isLast();
-
- m_head = m_head->remove();
-
- if (!m_head)
- m_tail = 0;
-
- m_semaphore.release(1);
-
- return sample;
- } else {
- return 0;
- }
-}
-
-bool DirectShowSampleScheduler::scheduleEndOfStream()
-{
- QMutexLocker locker(&m_mutex);
-
- if (m_tail) {
- m_tail->setLast();
-
- return true;
- } else {
- return false;
- }
-}
-
-bool DirectShowSampleScheduler::event(QEvent *event)
-{
- if (event->type() == QEvent::UpdateRequest) {
- emit sampleReady();
-
- return true;
- } else {
- return QObject::event(event);
- }
-}
diff --git a/src/plugins/directshow/player/directshowsamplescheduler.h b/src/plugins/directshow/player/directshowsamplescheduler.h
deleted file mode 100644
index 1670d23ed..000000000
--- a/src/plugins/directshow/player/directshowsamplescheduler.h
+++ /dev/null
@@ -1,115 +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 DIRECTSHOWSAMPLESCHEDULER_H
-#define DIRECTSHOWSAMPLESCHEDULER_H
-
-#include <dshow.h>
-
-#include <QtCore/qmutex.h>
-#include <QtCore/qobject.h>
-#include <QtCore/qsemaphore.h>
-
-class DirectShowTimedSample;
-
-class DirectShowSampleScheduler : public QObject, public IMemInputPin
-{
- Q_OBJECT
-public:
-
- enum State
- {
- Stopped = 0x00,
- Running = 0x01,
- Paused = 0x02,
- RunMask = 0x03,
- Flushing = 0x04
- };
-
- DirectShowSampleScheduler(IUnknown *pin, QObject *parent = 0);
- ~DirectShowSampleScheduler();
-
- // IUnknown
- HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
- ULONG STDMETHODCALLTYPE AddRef();
- ULONG STDMETHODCALLTYPE Release();
-
- // IMemInputPin
- HRESULT STDMETHODCALLTYPE GetAllocator(IMemAllocator **ppAllocator);
- HRESULT STDMETHODCALLTYPE NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly);
- HRESULT STDMETHODCALLTYPE GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps);
-
- HRESULT STDMETHODCALLTYPE Receive(IMediaSample *pSample);
- HRESULT STDMETHODCALLTYPE ReceiveMultiple(IMediaSample **pSamples, long nSamples, long *nSamplesProcessed);
- HRESULT STDMETHODCALLTYPE ReceiveCanBlock();
-
- void run(REFERENCE_TIME startTime);
- void pause();
- void stop();
- void setFlushing(bool flushing);
-
- IReferenceClock *clock() const { return m_clock; }
- void setClock(IReferenceClock *clock);
-
- bool schedule(IMediaSample *sample);
- bool scheduleEndOfStream();
-
- IMediaSample *takeSample(bool *eos);
-
- bool event(QEvent *event);
-
-Q_SIGNALS:
- void sampleReady();
-
-private:
- IUnknown *m_pin;
- IReferenceClock *m_clock;
- IMemAllocator *m_allocator;
- DirectShowTimedSample *m_head;
- DirectShowTimedSample *m_tail;
- int m_maximumSamples;
- int m_state;
- REFERENCE_TIME m_startTime;
- HANDLE m_timeoutEvent;
- HANDLE m_flushEvent;
- QSemaphore m_semaphore;
- QMutex m_mutex;
-};
-
-#endif
diff --git a/src/plugins/directshow/player/mediasamplevideobuffer.cpp b/src/plugins/directshow/player/mediasamplevideobuffer.cpp
deleted file mode 100644
index 58b146a89..000000000
--- a/src/plugins/directshow/player/mediasamplevideobuffer.cpp
+++ /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$
-**
-****************************************************************************/
-
-#include "mediasamplevideobuffer.h"
-
-MediaSampleVideoBuffer::MediaSampleVideoBuffer(IMediaSample *sample, int bytesPerLine)
- : QAbstractVideoBuffer(NoHandle)
- , m_sample(sample)
- , m_bytesPerLine(bytesPerLine)
- , m_mapMode(NotMapped)
-{
- m_sample->AddRef();
-}
-
-MediaSampleVideoBuffer::~MediaSampleVideoBuffer()
-{
- m_sample->Release();
-}
-
-uchar *MediaSampleVideoBuffer::map(MapMode mode, int *numBytes, int *bytesPerLine)
-{
- if (m_mapMode == NotMapped && mode != NotMapped) {
- if (numBytes)
- *numBytes = m_sample->GetActualDataLength();
-
- if (bytesPerLine)
- *bytesPerLine = m_bytesPerLine;
-
- BYTE *bytes = 0;
-
- if (m_sample->GetPointer(&bytes) == S_OK) {
- m_mapMode = mode;
-
- return reinterpret_cast<uchar *>(bytes);
- }
- }
- return 0;
-}
-
-void MediaSampleVideoBuffer::unmap()
-{
- m_mapMode = NotMapped;
-}
-
-QAbstractVideoBuffer::MapMode MediaSampleVideoBuffer::mapMode() const
-{
- return m_mapMode;
-}
diff --git a/src/plugins/directshow/player/mediasamplevideobuffer.h b/src/plugins/directshow/player/mediasamplevideobuffer.h
deleted file mode 100644
index 6ec1470c5..000000000
--- a/src/plugins/directshow/player/mediasamplevideobuffer.h
+++ /dev/null
@@ -1,67 +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 MEDIASAMPLEVIDEOBUFFER_H
-#define MEDIASAMPLEVIDEOBUFFER_H
-
-#include <dshow.h>
-
-#include <qabstractvideobuffer.h>
-
-class MediaSampleVideoBuffer : public QAbstractVideoBuffer
-{
-public:
- MediaSampleVideoBuffer(IMediaSample *sample, int bytesPerLine);
- ~MediaSampleVideoBuffer();
-
- IMediaSample *sample() { return m_sample; }
-
- uchar *map(MapMode mode, int *numBytes, int *bytesPerLine);
- void unmap();
-
- MapMode mapMode() const;
-
-private:
- IMediaSample *m_sample;
- int m_bytesPerLine;
- MapMode m_mapMode;
-};
-
-
-#endif
diff --git a/src/plugins/directshow/player/player.pri b/src/plugins/directshow/player/player.pri
index 0bc9c6d0a..8b4bb70b7 100644
--- a/src/plugins/directshow/player/player.pri
+++ b/src/plugins/directshow/player/player.pri
@@ -8,35 +8,22 @@ qtHaveModule(widgets): QT += widgets
DEFINES += QMEDIA_DIRECTSHOW_PLAYER
HEADERS += \
- $$PWD/directshoweventloop.h \
- $$PWD/directshowglobal.h \
$$PWD/directshowioreader.h \
$$PWD/directshowiosource.h \
- $$PWD/directshowmediatype.h \
- $$PWD/directshowmediatypelist.h \
- $$PWD/directshowpinenum.h \
$$PWD/directshowplayercontrol.h \
$$PWD/directshowplayerservice.h \
- $$PWD/directshowsamplescheduler.h \
$$PWD/directshowvideorenderercontrol.h \
- $$PWD/mediasamplevideobuffer.h \
$$PWD/videosurfacefilter.h \
$$PWD/directshowaudioendpointcontrol.h \
$$PWD/directshowmetadatacontrol.h \
$$PWD/vmr9videowindowcontrol.h
SOURCES += \
- $$PWD/directshoweventloop.cpp \
$$PWD/directshowioreader.cpp \
$$PWD/directshowiosource.cpp \
- $$PWD/directshowmediatype.cpp \
- $$PWD/directshowmediatypelist.cpp \
- $$PWD/directshowpinenum.cpp \
$$PWD/directshowplayercontrol.cpp \
$$PWD/directshowplayerservice.cpp \
- $$PWD/directshowsamplescheduler.cpp \
$$PWD/directshowvideorenderercontrol.cpp \
- $$PWD/mediasamplevideobuffer.cpp \
$$PWD/videosurfacefilter.cpp \
$$PWD/directshowaudioendpointcontrol.cpp \
$$PWD/directshowmetadatacontrol.cpp \
diff --git a/src/plugins/directshow/player/videosurfacefilter.cpp b/src/plugins/directshow/player/videosurfacefilter.cpp
index b7b0d3aa8..4cb97be39 100644
--- a/src/plugins/directshow/player/videosurfacefilter.cpp
+++ b/src/plugins/directshow/player/videosurfacefilter.cpp
@@ -41,226 +41,220 @@
#include "directshoweventloop.h"
#include "directshowglobal.h"
-#include "directshowpinenum.h"
-#include "mediasamplevideobuffer.h"
+#include "directshowvideobuffer.h"
-#include <QtCore/qcoreapplication.h>
-#include <QtCore/qcoreevent.h>
#include <QtCore/qthread.h>
+#include <QtCore/qloggingcategory.h>
#include <qabstractvideosurface.h>
#include <initguid.h>
+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);
-VideoSurfaceFilter::VideoSurfaceFilter(
- QAbstractVideoSurface *surface, DirectShowEventLoop *loop, QObject *parent)
- : QObject(parent)
- , m_ref(1)
- , m_state(State_Stopped)
- , m_surface(surface)
- , m_loop(loop)
- , m_graph(0)
- , m_peerPin(0)
- , m_bytesPerLine(0)
- , m_startResult(S_OK)
- , m_pinId(QString::fromLatin1("reference"))
- , m_sampleScheduler(static_cast<IPin *>(this))
+class VideoSurfaceInputPin : public DirectShowInputPin
{
- connect(surface, SIGNAL(supportedFormatsChanged()), this, SLOT(supportedFormatsChanged()));
- connect(&m_sampleScheduler, SIGNAL(sampleReady()), this, SLOT(sampleReady()));
-}
+ DIRECTSHOW_OBJECT
-VideoSurfaceFilter::~VideoSurfaceFilter()
-{
- Q_ASSERT(m_ref == 0);
-}
+public:
+ VideoSurfaceInputPin(VideoSurfaceFilter *filter);
-HRESULT VideoSurfaceFilter::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} };
+ // DirectShowPin
+ bool isMediaTypeSupported(const DirectShowMediaType *type);
+ bool setMediaType(const DirectShowMediaType *type);
- if (!ppvObject) {
- return E_POINTER;
- } else 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_IMemInputPin) {
- *ppvObject = static_cast<IMemInputPin *>(&m_sampleScheduler);
- } else {
- *ppvObject = 0;
+ HRESULT completeConnection(IPin *pin);
+ HRESULT connectionEnded();
- return E_NOINTERFACE;
- }
+ // IPin
+ STDMETHODIMP ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt);
+ STDMETHODIMP Disconnect();
+ STDMETHODIMP EndOfStream();
+ STDMETHODIMP BeginFlush();
+ STDMETHODIMP EndFlush();
- AddRef();
+ // IMemInputPin
+ STDMETHODIMP GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps);
+ STDMETHODIMP Receive(IMediaSample *pMediaSample);
- return S_OK;
+private:
+ VideoSurfaceFilter *m_videoSurfaceFilter;
+};
+
+VideoSurfaceInputPin::VideoSurfaceInputPin(VideoSurfaceFilter *filter)
+ : DirectShowInputPin(filter, QStringLiteral("Input"))
+ , m_videoSurfaceFilter(filter)
+{
}
-ULONG VideoSurfaceFilter::AddRef()
+bool VideoSurfaceInputPin::isMediaTypeSupported(const DirectShowMediaType *type)
{
- return InterlockedIncrement(&m_ref);
+ return m_videoSurfaceFilter->isMediaTypeSupported(type);
}
-ULONG VideoSurfaceFilter::Release()
+bool VideoSurfaceInputPin::setMediaType(const DirectShowMediaType *type)
{
- ULONG ref = InterlockedDecrement(&m_ref);
- if (ref == 0)
- delete this;
+ if (!DirectShowInputPin::setMediaType(type))
+ return false;
- return ref;
+ return m_videoSurfaceFilter->setMediaType(type);
}
-HRESULT VideoSurfaceFilter::GetClassID(CLSID *pClassID)
+HRESULT VideoSurfaceInputPin::completeConnection(IPin *pin)
{
- *pClassID = CLSID_VideoSurfaceFilter;
+ HRESULT hr = DirectShowInputPin::completeConnection(pin);
+ if (FAILED(hr))
+ return hr;
- return S_OK;
+ return m_videoSurfaceFilter->completeConnection(pin);
}
-HRESULT VideoSurfaceFilter::Run(REFERENCE_TIME tStart)
+HRESULT VideoSurfaceInputPin::connectionEnded()
{
- m_state = State_Running;
-
- m_sampleScheduler.run(tStart);
+ HRESULT hr = DirectShowInputPin::connectionEnded();
+ if (FAILED(hr))
+ return hr;
- return S_OK;
+ return m_videoSurfaceFilter->connectionEnded();
}
-HRESULT VideoSurfaceFilter::Pause()
+HRESULT VideoSurfaceInputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
{
- m_state = State_Paused;
-
- m_sampleScheduler.pause();
+ QMutexLocker lock(&m_videoSurfaceFilter->m_mutex);
+ return DirectShowInputPin::ReceiveConnection(pConnector, pmt);
+}
- return S_OK;
+HRESULT VideoSurfaceInputPin::Disconnect()
+{
+ QMutexLocker lock(&m_videoSurfaceFilter->m_mutex);
+ return DirectShowInputPin::Disconnect();
}
-HRESULT VideoSurfaceFilter::Stop()
+HRESULT VideoSurfaceInputPin::EndOfStream()
{
- m_state = State_Stopped;
+ QMutexLocker lock(&m_videoSurfaceFilter->m_mutex);
+ QMutexLocker renderLock(&m_videoSurfaceFilter->m_renderMutex);
- m_sampleScheduler.stop();
+ HRESULT hr = DirectShowInputPin::EndOfStream();
+ if (hr != S_OK)
+ return hr;
- if (thread() == QThread::currentThread()) {
- flush();
- } else {
- QMutexLocker locker(&m_mutex);
- m_loop->postEvent(this, new QEvent(QEvent::Type(FlushSurface)));
- m_wait.wait(&m_mutex);
+ return m_videoSurfaceFilter->EndOfStream();
+}
+
+HRESULT VideoSurfaceInputPin::BeginFlush()
+{
+ QMutexLocker lock(&m_videoSurfaceFilter->m_mutex);
+ {
+ QMutexLocker renderLock(&m_videoSurfaceFilter->m_renderMutex);
+ DirectShowInputPin::BeginFlush();
+ m_videoSurfaceFilter->BeginFlush();
}
+ m_videoSurfaceFilter->resetEOS();
return S_OK;
}
-HRESULT VideoSurfaceFilter::GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
+HRESULT VideoSurfaceInputPin::EndFlush()
{
- Q_UNUSED(dwMilliSecsTimeout)
- if (!pState)
- return E_POINTER;
-
- *pState = m_state;
+ QMutexLocker lock(&m_videoSurfaceFilter->m_mutex);
+ QMutexLocker renderLock(&m_videoSurfaceFilter->m_renderMutex);
- return S_OK;
+ HRESULT hr = m_videoSurfaceFilter->EndFlush();
+ if (SUCCEEDED(hr))
+ hr = DirectShowInputPin::EndFlush();
+ return hr;
}
-HRESULT VideoSurfaceFilter::SetSyncSource(IReferenceClock *pClock)
+HRESULT VideoSurfaceInputPin::GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps)
{
+ if (!pProps)
+ return E_POINTER;
- m_sampleScheduler.setClock(pClock);
+ // 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 VideoSurfaceFilter::GetSyncSource(IReferenceClock **ppClock)
+HRESULT VideoSurfaceInputPin::Receive(IMediaSample *pMediaSample)
{
- if (!ppClock) {
- return E_POINTER;
- } else {
- *ppClock = m_sampleScheduler.clock();
-
- if (*ppClock) {
- (*ppClock)->AddRef();
-
- return S_OK;
- } else {
- return S_FALSE;
+ 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);
+ {
+ QMutexLocker renderLocker(&m_videoSurfaceFilter->m_renderMutex);
+ if (m_videoSurfaceFilter->m_running && !m_videoSurfaceFilter->m_EOSDelivered)
+ m_videoSurfaceFilter->notifyEOS();
+ }
+ m_inErrorState = true;
}
}
+
+ return hr;
}
-HRESULT VideoSurfaceFilter::EnumPins(IEnumPins **ppEnum)
-{
- if (ppEnum) {
- *ppEnum = new DirectShowPinEnum(QList<IPin *>() << this);
- return S_OK;
- } else {
- return E_POINTER;
- }
+VideoSurfaceFilter::VideoSurfaceFilter(QAbstractVideoSurface *surface, DirectShowEventLoop *loop, QObject *parent)
+ : QObject(parent)
+ , m_loop(loop)
+ , m_pin(NULL)
+ , m_surface(surface)
+ , m_bytesPerLine(0)
+ , m_surfaceStarted(false)
+ , m_renderMutex(QMutex::Recursive)
+ , m_running(false)
+ , m_pendingSample(NULL)
+ , m_pendingSampleEndTime(0)
+ , m_renderEvent(CreateEvent(NULL, FALSE, FALSE, NULL))
+ , m_flushEvent(CreateEvent(NULL, TRUE, FALSE, NULL))
+ , m_adviseCookie(0)
+ , m_EOS(false)
+ , m_EOSDelivered(false)
+ , m_EOSTimer(0)
+{
+ supportedFormatsChanged();
+ connect(surface, &QAbstractVideoSurface::supportedFormatsChanged,
+ this, &VideoSurfaceFilter::supportedFormatsChanged);
}
-HRESULT VideoSurfaceFilter::FindPin(LPCWSTR pId, IPin **ppPin)
+VideoSurfaceFilter::~VideoSurfaceFilter()
{
- if (!ppPin || !pId) {
- return E_POINTER;
- } else if (QString::fromWCharArray(pId) == m_pinId) {
- AddRef();
+ clearPendingSample();
- *ppPin = this;
+ if (m_pin)
+ m_pin->Release();
- return S_OK;
- } else {
- return VFW_E_NOT_FOUND;
- }
+ CloseHandle(m_flushEvent);
+ CloseHandle(m_renderEvent);
}
-HRESULT VideoSurfaceFilter::JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName)
+HRESULT VideoSurfaceFilter::getInterface(const IID &riid, void **ppvObject)
{
- m_graph = pGraph;
- m_name = QString::fromWCharArray(pName);
-
- return S_OK;
+ if (riid == IID_IAMFilterMiscFlags)
+ return GetInterface(static_cast<IAMFilterMiscFlags*>(this), ppvObject);
+ else
+ return DirectShowBaseFilter::getInterface(riid, ppvObject);
}
-HRESULT VideoSurfaceFilter::QueryFilterInfo(FILTER_INFO *pInfo)
+QList<DirectShowPin *> VideoSurfaceFilter::pins()
{
- if (pInfo) {
- QString name = m_name;
-
- 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;
+ if (!m_pin)
+ m_pin = new VideoSurfaceInputPin(this);
- return S_OK;
- } else {
- return E_POINTER;
- }
+ return QList<DirectShowPin *>() << m_pin;
}
-HRESULT VideoSurfaceFilter::QueryVendorInfo(LPWSTR *pVendorInfo)
+HRESULT VideoSurfaceFilter::GetClassID(CLSID *pClassID)
{
- Q_UNUSED(pVendorInfo);
-
- return E_NOTIMPL;
+ *pClassID = CLSID_VideoSurfaceFilter;
+ return S_OK;
}
ULONG VideoSurfaceFilter::GetMiscFlags()
@@ -268,388 +262,527 @@ ULONG VideoSurfaceFilter::GetMiscFlags()
return AM_FILTER_MISC_FLAGS_IS_RENDERER;
}
-
-HRESULT VideoSurfaceFilter::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
-{
- Q_UNUSED(pReceivePin)
- Q_UNUSED(pmt)
- // This is an input pin, you shouldn't be calling Connect on it.
- return E_POINTER;
-}
-
-HRESULT VideoSurfaceFilter::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
+void VideoSurfaceFilter::supportedFormatsChanged()
{
- if (!pConnector) {
- return E_POINTER;
- } else if (!pmt) {
- return E_POINTER;
- } else {
- HRESULT hr;
- QMutexLocker locker(&m_mutex);
+ QWriteLocker writeLocker(&m_typesLock);
- if (m_peerPin) {
- hr = VFW_E_ALREADY_CONNECTED;
- } else if (pmt->majortype != MEDIATYPE_Video) {
- hr = VFW_E_TYPE_NOT_ACCEPTED;
- } else {
- m_surfaceFormat = DirectShowMediaType::formatFromType(*pmt);
- m_bytesPerLine = DirectShowMediaType::bytesPerLine(m_surfaceFormat);
+ qCDebug(qLcRenderFilter, "supportedFormatChanged");
- if (thread() == QThread::currentThread()) {
- hr = start();
- } else {
- m_loop->postEvent(this, new QEvent(QEvent::Type(StartSurface)));
+ m_supportedTypes.clear();
- m_wait.wait(&m_mutex);
+ const QList<QVideoFrame::PixelFormat> formats = m_surface->supportedPixelFormats();
+ m_supportedTypes.reserve(formats.count());
- hr = m_startResult;
- }
+ for (QVideoFrame::PixelFormat format : formats) {
+ GUID subtype = DirectShowMediaType::convertPixelFormat(format);
+ if (!IsEqualGUID(subtype, MEDIASUBTYPE_None)) {
+ qCDebug(qLcRenderFilter) << " " << format;
+ m_supportedTypes.append(subtype);
}
- if (hr == S_OK) {
- m_peerPin = pConnector;
- m_peerPin->AddRef();
+ }
+}
- DirectShowMediaType::copy(&m_mediaType, *pmt);
- }
- return hr;
+bool VideoSurfaceFilter::isMediaTypeSupported(const DirectShowMediaType *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;
}
-HRESULT VideoSurfaceFilter::start()
+bool VideoSurfaceFilter::setMediaType(const DirectShowMediaType *type)
{
- if (!m_surface->isFormatSupported(m_surfaceFormat)) {
- return VFW_E_TYPE_NOT_ACCEPTED;
+ if (!type) {
+ qCDebug(qLcRenderFilter, "clear media type");
+ m_surfaceFormat = QVideoSurfaceFormat();
+ m_bytesPerLine = 0;
+ return true;
+ } else {
+ m_surfaceFormat = DirectShowMediaType::formatFromType(*type);
+ m_bytesPerLine = DirectShowMediaType::bytesPerLine(m_surfaceFormat);
+ qCDebug(qLcRenderFilter) << "setMediaType -->" << m_surfaceFormat;
+ return m_surfaceFormat.isValid();
}
- if (!m_surface->start(m_surfaceFormat)) {
+}
+
+HRESULT VideoSurfaceFilter::completeConnection(IPin *pin)
+{
+ Q_UNUSED(pin);
+
+ qCDebug(qLcRenderFilter, "completeConnection");
+
+ if (!startSurface())
return VFW_E_TYPE_NOT_ACCEPTED;
- } else {
+ else
return S_OK;
- }
}
-HRESULT VideoSurfaceFilter::Disconnect()
+HRESULT VideoSurfaceFilter::connectionEnded()
+{
+ qCDebug(qLcRenderFilter, "connectionEnded");
+
+ stopSurface();
+
+ return S_OK;
+}
+
+HRESULT VideoSurfaceFilter::Run(REFERENCE_TIME tStart)
{
QMutexLocker locker(&m_mutex);
- if (!m_peerPin)
- return S_FALSE;
+ if (m_state == State_Running)
+ return S_OK;
- if (thread() == QThread::currentThread()) {
- stop();
- } else {
- m_loop->postEvent(this, new QEvent(QEvent::Type(StopSurface)));
+ qCDebug(qLcRenderFilter, "Run (start=%lli)", tStart);
+
+ HRESULT hr = DirectShowBaseFilter::Run(tStart);
+ if (FAILED(hr))
+ return hr;
+
+ ResetEvent(m_flushEvent);
- m_wait.wait(&m_mutex);
+ IMemAllocator *allocator;
+ if (SUCCEEDED(m_pin->GetAllocator(&allocator))) {
+ allocator->Commit();
+ allocator->Release();
}
- m_mediaType.clear();
+ QMutexLocker renderLocker(&m_renderMutex);
- m_sampleScheduler.NotifyAllocator(0, FALSE);
+ m_running = true;
- m_peerPin->Release();
- m_peerPin = 0;
+ if (!m_pendingSample)
+ checkEOS();
+ else if (!scheduleSample(m_pendingSample))
+ SetEvent(m_renderEvent); // render immediately
return S_OK;
}
-void VideoSurfaceFilter::stop()
+HRESULT VideoSurfaceFilter::Pause()
{
- m_surface->stop();
-}
+ QMutexLocker locker(&m_mutex);
-HRESULT VideoSurfaceFilter::ConnectedTo(IPin **ppPin)
-{
- if (!ppPin) {
- return E_POINTER;
- } else {
- QMutexLocker locker(&m_mutex);
+ if (m_state == State_Paused)
+ return S_OK;
- if (!m_peerPin) {
- return VFW_E_NOT_CONNECTED;
- } else {
- m_peerPin->AddRef();
+ qCDebug(qLcRenderFilter, "Pause");
- *ppPin = m_peerPin;
+ HRESULT hr = DirectShowBaseFilter::Pause();
+ if (FAILED(hr))
+ return hr;
- return S_OK;
- }
+ 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::ConnectionMediaType(AM_MEDIA_TYPE *pmt)
+HRESULT VideoSurfaceFilter::Stop()
{
- if (!pmt) {
- return E_POINTER;
- } else {
- QMutexLocker locker(&m_mutex);
+ QMutexLocker locker(&m_mutex);
- if (!m_peerPin) {
- return VFW_E_NOT_CONNECTED;
- } else {
- DirectShowMediaType::copy(pmt, m_mediaType);
+ if (m_state == State_Stopped)
+ return S_OK;
- return S_OK;
- }
- }
-}
+ qCDebug(qLcRenderFilter, "Stop");
-HRESULT VideoSurfaceFilter::QueryPinInfo(PIN_INFO *pInfo)
-{
- if (!pInfo) {
- return E_POINTER;
- } else {
- AddRef();
+ DirectShowBaseFilter::Stop();
- pInfo->pFilter = this;
- pInfo->dir = PINDIR_INPUT;
+ clearPendingSample();
- const int bytes = qMin(MAX_FILTER_NAME, (m_pinId.length() + 1) * 2);
+ m_renderMutex.lock();
+ m_EOSDelivered = false;
+ m_running = false;
+ m_renderMutex.unlock();
- ::memcpy(pInfo->achName, m_pinId.utf16(), bytes);
+ SetEvent(m_flushEvent);
+ resetEOS();
+ unscheduleSample();
+ flushSurface();
- return S_OK;
+ IMemAllocator *allocator;
+ if (SUCCEEDED(m_pin->GetAllocator(&allocator))) {
+ allocator->Decommit();
+ allocator->Release();
}
+
+ return S_OK;
}
-HRESULT VideoSurfaceFilter::QueryId(LPWSTR *Id)
+HRESULT VideoSurfaceFilter::EndOfStream()
{
- if (!Id) {
- return E_POINTER;
- } else {
- const int bytes = (m_pinId.length() + 1) * 2;
+ QMutexLocker renderLocker(&m_renderMutex);
- *Id = static_cast<LPWSTR>(::CoTaskMemAlloc(bytes));
+ qCDebug(qLcRenderFilter, "EndOfStream");
- ::memcpy(*Id, m_pinId.utf16(), bytes);
+ m_EOS = true;
- return S_OK;
- }
-}
+ if (!m_pendingSample && m_running)
+ checkEOS();
-HRESULT VideoSurfaceFilter::QueryAccept(const AM_MEDIA_TYPE *pmt)
-{
- return !m_surface->isFormatSupported(DirectShowMediaType::formatFromType(*pmt))
- ? S_OK
- : S_FALSE;
+ return S_OK;
}
-HRESULT VideoSurfaceFilter::EnumMediaTypes(IEnumMediaTypes **ppEnum)
+HRESULT VideoSurfaceFilter::BeginFlush()
{
- if (!ppEnum) {
- return E_POINTER;
- } else {
- QMutexLocker locker(&m_mutex);
+ qCDebug(qLcRenderFilter, "BeginFlush");
- *ppEnum = createMediaTypeEnum();
+ SetEvent(m_flushEvent);
+ unscheduleSample();
+ clearPendingSample();
- return S_OK;
- }
+ return S_OK;
}
-HRESULT VideoSurfaceFilter::QueryInternalConnections(IPin **apPin, ULONG *nPin)
+HRESULT VideoSurfaceFilter::EndFlush()
{
- Q_UNUSED(apPin);
- Q_UNUSED(nPin);
+ qCDebug(qLcRenderFilter, "EndFlush");
- return E_NOTIMPL;
+ ResetEvent(m_flushEvent);
+ return S_OK;
}
-HRESULT VideoSurfaceFilter::EndOfStream()
+HRESULT VideoSurfaceFilter::Receive(IMediaSample *pMediaSample)
{
- QMutexLocker locker(&m_mutex);
+ {
+ QMutexLocker locker(&m_mutex);
- if (!m_sampleScheduler.scheduleEndOfStream()) {
- if (IMediaEventSink *sink = com_cast<IMediaEventSink>(m_graph, IID_IMediaEventSink)) {
- sink->Notify(
- EC_COMPLETE,
- S_OK,
- reinterpret_cast<LONG_PTR>(static_cast<IBaseFilter *>(this)));
- sink->Release();
+ 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;
}
- }
- return S_OK;
-}
+ // 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(reinterpret_cast<const DirectShowMediaType *>(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;
+ }
-HRESULT VideoSurfaceFilter::BeginFlush()
-{
- QMutexLocker locker(&m_mutex);
+ {
+ QMutexLocker locker(&m_renderMutex);
- m_sampleScheduler.setFlushing(true);
+ if (m_pendingSample || m_EOS)
+ return E_UNEXPECTED;
- if (thread() == QThread::currentThread()) {
- flush();
- } else {
- m_loop->postEvent(this, new QEvent(QEvent::Type(FlushSurface)));
+ 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;
+ }
- m_wait.wait(&m_mutex);
+ if (m_state == State_Paused) // Render immediately
+ renderPendingSample();
}
- return S_OK;
-}
+ qCDebug(qLcRenderFilter, " waiting for render time");
-HRESULT VideoSurfaceFilter::EndFlush()
-{
- QMutexLocker locker(&m_mutex);
+ // 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);
- m_sampleScheduler.setFlushing(false);
+ if (result == WAIT_OBJECT_0) {
+ // render interrupted (flush, pause, stop)
+ qCDebug(qLcRenderFilter, " rendering of sample %p interrupted", pMediaSample);
+ return S_OK;
+ }
- return S_OK;
-}
+ m_adviseCookie = 0;
-void VideoSurfaceFilter::flush()
-{
- m_surface->present(QVideoFrame());
+ QMutexLocker locker(&m_mutex);
- m_wait.wakeAll();
-}
+ // 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;
+ }
-HRESULT VideoSurfaceFilter::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
-{
- Q_UNUSED(tStart);
- Q_UNUSED(tStop);
- Q_UNUSED(dRate);
+ QMutexLocker renderLock(&m_renderMutex);
+
+ // Flush or pause might have happened just before the lock
+ if (m_pendingSample && m_running) {
+ renderLock.unlock();
+ renderPendingSample();
+ renderLock.relock();
+ } else {
+ qCDebug(qLcRenderFilter, " discarding sample (%p)", pMediaSample);
+ }
+
+ clearPendingSample();
+ checkEOS();
+ ResetEvent(m_renderEvent);
return S_OK;
}
-HRESULT VideoSurfaceFilter::QueryDirection(PIN_DIRECTION *pPinDir)
+bool VideoSurfaceFilter::scheduleSample(IMediaSample *sample)
{
- if (!pPinDir) {
- return E_POINTER;
- } else {
- *pPinDir = PINDIR_INPUT;
+ if (!sample)
+ return false;
- return S_OK;
+ 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;
}
-}
-int VideoSurfaceFilter::currentMediaTypeToken()
-{
- QMutexLocker locker(&m_mutex);
+ 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 DirectShowMediaTypeList::currentMediaTypeToken();
+ return true;
}
-HRESULT VideoSurfaceFilter::nextMediaType(
- int token, int *index, ULONG count, AM_MEDIA_TYPE **types, ULONG *fetchedCount)
+void VideoSurfaceFilter::unscheduleSample()
{
- QMutexLocker locker(&m_mutex);
-
- return DirectShowMediaTypeList::nextMediaType(token, index, count, types, fetchedCount);
+ if (m_adviseCookie) {
+ qCDebug(qLcRenderFilter, "unscheduleSample");
+ m_clock->Unadvise(m_adviseCookie);
+ m_adviseCookie = 0;
+ }
+ ResetEvent(m_renderEvent);
}
-HRESULT VideoSurfaceFilter::skipMediaType(int token, int *index, ULONG count)
+void VideoSurfaceFilter::clearPendingSample()
{
- QMutexLocker locker(&m_mutex);
+ QMutexLocker locker(&m_renderMutex);
+ if (m_pendingSample) {
+ qCDebug(qLcRenderFilter, "clearPendingSample");
+ m_pendingSample->Release();
+ m_pendingSample = NULL;
+ }
+}
- return DirectShowMediaTypeList::skipMediaType(token, index, count);
+void QT_WIN_CALLBACK EOSTimerCallback(UINT, UINT, DWORD_PTR dwUser, DWORD_PTR, DWORD_PTR)
+{
+ VideoSurfaceFilter *that = reinterpret_cast<VideoSurfaceFilter *>(dwUser);
+ that->onEOSTimerTimeout();
}
-HRESULT VideoSurfaceFilter::cloneMediaType(int token, int index, IEnumMediaTypes **enumeration)
+void VideoSurfaceFilter::onEOSTimerTimeout()
{
- QMutexLocker locker(&m_mutex);
+ QMutexLocker locker(&m_renderMutex);
- return DirectShowMediaTypeList::cloneMediaType(token, index, enumeration);
+ if (m_EOSTimer) {
+ m_EOSTimer = 0;
+ checkEOS();
+ }
}
-void VideoSurfaceFilter::customEvent(QEvent *event)
+void VideoSurfaceFilter::checkEOS()
{
- const int type = event->type();
- if (type == StartSurface) {
- QMutexLocker locker(&m_mutex);
+ QMutexLocker locker(&m_renderMutex);
- m_startResult = start();
+ if (!m_EOS || m_EOSDelivered || m_EOSTimer)
+ return;
- m_wait.wakeAll();
- } else if (type == StopSurface) {
- QMutexLocker locker(&m_mutex);
+ if (!m_clock) {
+ notifyEOS();
+ return;
+ }
- stop();
+ REFERENCE_TIME eosTime = m_startTime + m_pendingSampleEndTime;
+ REFERENCE_TIME currentTime;
+ m_clock->GetTime(&currentTime);
+ LONG delay = LONG((eosTime - currentTime) / 10000);
- m_wait.wakeAll();
- } else if (type == FlushSurface) {
- QMutexLocker locker(&m_mutex);
+ if (delay < 1) {
+ notifyEOS();
+ } else {
+ qCDebug(qLcRenderFilter, "will trigger EOS in %li", delay);
- flush();
+ m_EOSTimer = timeSetEvent(delay,
+ 1,
+ EOSTimerCallback,
+ reinterpret_cast<DWORD_PTR>(this),
+ TIME_ONESHOT | TIME_CALLBACK_FUNCTION | TIME_KILL_SYNCHRONOUS);
- m_wait.wakeAll();
- } else {
- QObject::customEvent(event);
+ if (!m_EOSTimer) {
+ qDebug("Error with timer");
+ notifyEOS();
+ }
}
}
-void VideoSurfaceFilter::supportedFormatsChanged()
+void VideoSurfaceFilter::notifyEOS()
{
- QMutexLocker locker(&m_mutex);
+ QMutexLocker locker(&m_renderMutex);
- // MEDIASUBTYPE_None;
- static const GUID none = {
- 0xe436eb8e, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70} };
+ if (!m_running)
+ return;
- const QList<QVideoFrame::PixelFormat> formats = m_surface->supportedPixelFormats();
+ qCDebug(qLcRenderFilter, "notifyEOS, delivering EC_COMPLETE event");
- QVector<AM_MEDIA_TYPE> mediaTypes;
- mediaTypes.reserve(formats.count());
+ m_EOSTimer = 0;
+ m_EOSDelivered = true;
+ NotifyEvent(EC_COMPLETE, S_OK, (LONG_PTR)(IBaseFilter *)this);
+}
- AM_MEDIA_TYPE type;
- type.majortype = MEDIATYPE_Video;
- type.bFixedSizeSamples = TRUE;
- type.bTemporalCompression = FALSE;
- type.lSampleSize = 0;
- type.formattype = GUID_NULL;
- type.pUnk = 0;
- type.cbFormat = 0;
- type.pbFormat = 0;
+void VideoSurfaceFilter::resetEOS()
+{
+ resetEOSTimer();
- for (QVideoFrame::PixelFormat format : formats) {
- type.subtype = DirectShowMediaType::convertPixelFormat(format);
+ QMutexLocker locker(&m_renderMutex);
- if (type.subtype != none)
- mediaTypes.append(type);
- }
+ if (m_EOS)
+ qCDebug(qLcRenderFilter, "resetEOS (delivered=%s)", m_EOSDelivered ? "true" : "false");
- setMediaTypes(mediaTypes);
+ m_EOS = false;
+ m_EOSDelivered = false;
+ m_pendingSampleEndTime = 0;
}
-void VideoSurfaceFilter::sampleReady()
+void VideoSurfaceFilter::resetEOSTimer()
{
- bool eos = false;
+ if (m_EOSTimer) {
+ timeKillEvent(m_EOSTimer);
+ m_EOSTimer = 0;
+ }
+}
- IMediaSample *sample = m_sampleScheduler.takeSample(&eos);
+bool VideoSurfaceFilter::startSurface()
+{
+ if (QThread::currentThread() != thread()) {
+ m_loop->postEvent(this, new QEvent(QEvent::Type(StartSurface)));
+ m_waitSurface.wait(&m_mutex);
+ return m_surfaceStarted;
+ } else {
+ m_surfaceStarted = m_surface->start(m_surfaceFormat);
+ qCDebug(qLcRenderFilter, "startSurface %s", m_surfaceStarted ? "succeeded" : "failed");
+ return m_surfaceStarted;
+ }
+}
- if (sample) {
- QVideoFrame frame(new MediaSampleVideoBuffer(sample, m_bytesPerLine),
- m_surfaceFormat.frameSize(),
- m_surfaceFormat.pixelFormat());
+void VideoSurfaceFilter::stopSurface()
+{
+ if (!m_surfaceStarted)
+ return;
- if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) {
- LONGLONG position = 0;
- seeking->GetCurrentPosition(&position);
- seeking->Release();
+ 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;
+ }
+}
- frame.setStartTime(position * 0.1);
+bool VideoSurfaceFilter::restartSurface()
+{
+ if (QThread::currentThread() != thread()) {
+ m_loop->postEvent(this, new QEvent(QEvent::Type(RestartSurface)));
+ m_waitSurface.wait(&m_mutex);
+ return m_surfaceStarted;
+ } else {
+ m_surface->stop();
+ m_surfaceStarted = m_surface->start(m_surfaceFormat);
+ qCDebug(qLcRenderFilter, "restartSurface %s", m_surfaceStarted ? "succeeded" : "failed");
+ return m_surfaceStarted;
+ }
+}
- REFERENCE_TIME startTime = -1;
- REFERENCE_TIME endTime = -1;
- if (sample->GetTime(&startTime, &endTime) == S_OK)
- frame.setEndTime(frame.startTime() + (endTime - startTime) * 0.1);
- }
+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());
+ }
+}
- m_surface->present(frame);
+void VideoSurfaceFilter::renderPendingSample()
+{
+ if (QThread::currentThread() != thread()) {
+ m_loop->postEvent(this, new QEvent(QEvent::Type(RenderSample)));
+ m_waitSurface.wait(&m_mutex);
+ } else {
+ QMutexLocker locker(&m_renderMutex);
+ if (!m_pendingSample)
+ return;
- sample->Release();
+ qCDebug(qLcRenderFilter, "presentSample (sample=%p)", m_pendingSample);
- if (eos) {
- if (IMediaEventSink *sink = com_cast<IMediaEventSink>(m_graph, IID_IMediaEventSink)) {
- sink->Notify(
- EC_COMPLETE,
- S_OK,
- reinterpret_cast<LONG_PTR>(static_cast<IBaseFilter *>(this)));
- sink->Release();
- }
- }
+ m_surface->present(QVideoFrame(new DirectShowVideoBuffer(m_pendingSample, m_bytesPerLine),
+ m_surfaceFormat.frameSize(),
+ m_surfaceFormat.pixelFormat()));
}
}
+bool VideoSurfaceFilter::event(QEvent *e)
+{
+ if (e->type() == QEvent::Type(StartSurface)) {
+ QMutexLocker locker(&m_mutex);
+ startSurface();
+ m_waitSurface.wakeAll();
+ return true;
+ } else if (e->type() == QEvent::Type(StopSurface)) {
+ QMutexLocker locker(&m_mutex);
+ stopSurface();
+ m_waitSurface.wakeAll();
+ return true;
+ } else if (e->type() == QEvent::Type(RestartSurface)) {
+ QMutexLocker locker(&m_mutex);
+ restartSurface();
+ m_waitSurface.wakeAll();
+ return true;
+ } else if (e->type() == QEvent::Type(FlushSurface)) {
+ QMutexLocker locker(&m_mutex);
+ flushSurface();
+ m_waitSurface.wakeAll();
+ return true;
+ } else if (e->type() == QEvent::Type(RenderSample)) {
+ QMutexLocker locker(&m_mutex);
+ renderPendingSample();
+ m_waitSurface.wakeAll();
+ return true;
+ }
+
+ return QObject::event(e);
+}
diff --git a/src/plugins/directshow/player/videosurfacefilter.h b/src/plugins/directshow/player/videosurfacefilter.h
index 001e2804b..581e33c70 100644
--- a/src/plugins/directshow/player/videosurfacefilter.h
+++ b/src/plugins/directshow/player/videosurfacefilter.h
@@ -40,135 +40,121 @@
#ifndef VIDEOSURFACEFILTER_H
#define VIDEOSURFACEFILTER_H
-#include "directshowglobal.h"
-#include "directshowmediatypelist.h"
-#include "directshowsamplescheduler.h"
-#include "directshowmediatype.h"
+#include "directshowbasefilter.h"
-#include <QtCore/qbasictimer.h>
#include <QtCore/qcoreevent.h>
#include <QtCore/qmutex.h>
-#include <QtCore/qsemaphore.h>
-#include <QtCore/qstring.h>
-#include <QtCore/qwaitcondition.h>
-
-#include <dshow.h>
+#include <qreadwritelock.h>
+#include <qsemaphore.h>
+#include <qwaitcondition.h>
QT_BEGIN_NAMESPACE
class QAbstractVideoSurface;
QT_END_NAMESPACE
class DirectShowEventLoop;
+class VideoSurfaceInputPin;
-class VideoSurfaceFilter
- : public QObject
- , public DirectShowMediaTypeList
- , public IBaseFilter
- , public IAMFilterMiscFlags
- , public IPin
+class VideoSurfaceFilter : public QObject
+ , public DirectShowBaseFilter
+ , public IAMFilterMiscFlags
{
Q_OBJECT
+ DIRECTSHOW_OBJECT
public:
- VideoSurfaceFilter(
- QAbstractVideoSurface *surface, DirectShowEventLoop *loop, QObject *parent = 0);
+ VideoSurfaceFilter(QAbstractVideoSurface *surface, DirectShowEventLoop *loop, QObject *parent = 0);
~VideoSurfaceFilter();
- // IUnknown
- HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
- ULONG STDMETHODCALLTYPE AddRef();
- ULONG STDMETHODCALLTYPE Release();
+ // DirectShowObject
+ HRESULT getInterface(REFIID riid, void **ppvObject);
+
+ // DirectShowBaseFilter
+ QList<DirectShowPin *> pins();
// IPersist
- HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID);
+ STDMETHODIMP GetClassID(CLSID *pClassID);
// IMediaFilter
- HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME tStart);
- HRESULT STDMETHODCALLTYPE Pause();
- HRESULT STDMETHODCALLTYPE Stop();
-
- HRESULT STDMETHODCALLTYPE GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *pState);
-
- HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock *pClock);
- HRESULT STDMETHODCALLTYPE GetSyncSource(IReferenceClock **ppClock);
-
- // IBaseFilter
- HRESULT STDMETHODCALLTYPE EnumPins(IEnumPins **ppEnum);
- HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR Id, IPin **ppPin);
-
- HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName);
-
- HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO *pInfo);
- HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR *pVendorInfo);
+ STDMETHODIMP Run(REFERENCE_TIME tStart);
+ STDMETHODIMP Pause();
+ STDMETHODIMP Stop();
// IAMFilterMiscFlags
- ULONG STDMETHODCALLTYPE GetMiscFlags();
+ STDMETHODIMP_(ULONG) GetMiscFlags();
- // IPin
- HRESULT STDMETHODCALLTYPE Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt);
- HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt);
- HRESULT STDMETHODCALLTYPE Disconnect();
- HRESULT STDMETHODCALLTYPE ConnectedTo(IPin **ppPin);
+ // DirectShowPin (delegate)
+ bool isMediaTypeSupported(const DirectShowMediaType *type);
+ bool setMediaType(const DirectShowMediaType *type);
+ HRESULT completeConnection(IPin *pin);
+ HRESULT connectionEnded();
- HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE *pmt);
+ // IPin (delegate)
+ HRESULT EndOfStream();
+ HRESULT BeginFlush();
+ HRESULT EndFlush();
- HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO *pInfo);
- HRESULT STDMETHODCALLTYPE QueryId(LPWSTR *Id);
+ // IMemInputPin (delegate)
+ HRESULT Receive(IMediaSample *pMediaSample);
- HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE *pmt);
+private Q_SLOTS:
+ void supportedFormatsChanged();
+ void checkEOS();
- HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes **ppEnum);
+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 *);
- HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin **apPin, ULONG *nPin);
+ bool startSurface();
+ void stopSurface();
+ bool restartSurface();
+ void flushSurface();
- HRESULT STDMETHODCALLTYPE EndOfStream();
+ bool scheduleSample(IMediaSample *sample);
+ void unscheduleSample();
+ void renderPendingSample();
+ void clearPendingSample();
- HRESULT STDMETHODCALLTYPE BeginFlush();
- HRESULT STDMETHODCALLTYPE EndFlush();
+ void notifyEOS();
+ void resetEOS();
+ void resetEOSTimer();
+ void onEOSTimerTimeout();
- HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
+ friend void QT_WIN_CALLBACK EOSTimerCallback(UINT, UINT, DWORD_PTR dwUser, DWORD_PTR, DWORD_PTR);
- HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION *pPinDir);
+ QMutex m_mutex;
- int currentMediaTypeToken();
- HRESULT nextMediaType(
- int token, int *index, ULONG count, AM_MEDIA_TYPE **types, ULONG *fetchedCount);
- HRESULT skipMediaType(int token, int *index, ULONG count);
- HRESULT cloneMediaType(int token, int index, IEnumMediaTypes **enumeration);
+ DirectShowEventLoop *m_loop;
+ VideoSurfaceInputPin *m_pin;
-protected:
- void customEvent(QEvent *event);
+ QWaitCondition m_waitSurface;
+ QAbstractVideoSurface *m_surface;
+ QVideoSurfaceFormat m_surfaceFormat;
+ int m_bytesPerLine;
+ bool m_surfaceStarted;
-private Q_SLOTS:
- void supportedFormatsChanged();
- void sampleReady();
+ QList<GUID> m_supportedTypes;
+ QReadWriteLock m_typesLock;
-private:
- HRESULT start();
- void stop();
- void flush();
+ QMutex m_renderMutex;
+ bool m_running;
+ IMediaSample *m_pendingSample;
+ REFERENCE_TIME m_pendingSampleEndTime;
+ HANDLE m_renderEvent;
+ HANDLE m_flushEvent;
+ DWORD_PTR m_adviseCookie;
- enum
- {
- StartSurface = QEvent::User,
- StopSurface,
- FlushSurface
- };
+ bool m_EOS;
+ bool m_EOSDelivered;
+ UINT m_EOSTimer;
- LONG m_ref;
- FILTER_STATE m_state;
- QAbstractVideoSurface *m_surface;
- DirectShowEventLoop *m_loop;
- IFilterGraph *m_graph;
- IPin *m_peerPin;
- int m_bytesPerLine;
- HRESULT m_startResult;
- QString m_name;
- QString m_pinId;
- DirectShowMediaType m_mediaType;
- QVideoSurfaceFormat m_surfaceFormat;
- QMutex m_mutex;
- QWaitCondition m_wait;
- DirectShowSampleScheduler m_sampleScheduler;
+ friend class VideoSurfaceInputPin;
};
#endif