summaryrefslogtreecommitdiffstats
path: root/src/plugins/directshow/player
diff options
context:
space:
mode:
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