From 64e84dab2673020e4384ae36d9d1e9e4f0d8052d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Mon, 12 Dec 2016 18:06:54 +0100 Subject: Android: Run-time permission checks for camera The camera should ask for permission before being used. Normally this should be handle by the user, which can provide proper reasons for why the camera is used. To verify that we are allowed to open the camera, and as a good default, we'll check the permission and request access if needed. [ChangeLog][Android] Added run-time permission checks for accessing the camera. Task-number: QTBUG-55992 Change-Id: Ifb4e176728aab3076fdba292e17e17d33b1260a2 Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../android/src/mediacapture/qandroidcamerasession.cpp | 2 +- src/plugins/android/src/wrappers/jni/androidcamera.cpp | 14 ++++++++++++++ src/plugins/android/src/wrappers/jni/androidcamera.h | 1 + 3 files changed, 16 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp index b0dd7d900..a7f0254ee 100644 --- a/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp +++ b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp @@ -176,7 +176,7 @@ bool QAndroidCameraSession::open() m_status = QCamera::LoadingStatus; emit statusChanged(m_status); - m_camera = AndroidCamera::open(m_selectedCamera); + m_camera = AndroidCamera::requestCameraPermission() ? AndroidCamera::open(m_selectedCamera) : nullptr; if (m_camera) { connect(m_camera, SIGNAL(pictureExposed()), this, SLOT(onCameraPictureExposed())); diff --git a/src/plugins/android/src/wrappers/jni/androidcamera.cpp b/src/plugins/android/src/wrappers/jni/androidcamera.cpp index 0f2a43531..e3afddd59 100644 --- a/src/plugins/android/src/wrappers/jni/androidcamera.cpp +++ b/src/plugins/android/src/wrappers/jni/androidcamera.cpp @@ -42,6 +42,7 @@ #include "androidsurfacetexture.h" #include "androidsurfaceview.h" #include "qandroidmultimediautils.h" +#include "qandroidglobal.h" #include #include @@ -55,6 +56,11 @@ QT_BEGIN_NAMESPACE static const char QtCameraListenerClassName[] = "org/qtproject/qt5/android/multimedia/QtCameraListener"; +static QString cameraPermissionKey() +{ + return QStringLiteral("android.permission.CAMERA"); +} + typedef QHash CameraMap; Q_GLOBAL_STATIC(CameraMap, cameras) Q_GLOBAL_STATIC(QReadWriteLock, rwLock) @@ -756,6 +762,9 @@ QJNIObjectPrivate AndroidCamera::getCameraObject() int AndroidCamera::getNumberOfCameras() { + if (!requestCameraPermission()) + return 0; + return QJNIObjectPrivate::callStaticMethod("android/hardware/Camera", "getNumberOfCameras"); } @@ -790,6 +799,11 @@ void AndroidCamera::getCameraInfo(int id, AndroidCameraInfo *info) } } +bool AndroidCamera::requestCameraPermission() +{ + return qt_androidRequestPermission(cameraPermissionKey()); +} + void AndroidCamera::startPreview() { Q_D(AndroidCamera); diff --git a/src/plugins/android/src/wrappers/jni/androidcamera.h b/src/plugins/android/src/wrappers/jni/androidcamera.h index e58a81f8e..5ae141f01 100644 --- a/src/plugins/android/src/wrappers/jni/androidcamera.h +++ b/src/plugins/android/src/wrappers/jni/androidcamera.h @@ -201,6 +201,7 @@ public: static int getNumberOfCameras(); static void getCameraInfo(int id, AndroidCameraInfo *info); + static bool requestCameraPermission(); static bool initJNI(JNIEnv *env); -- cgit v1.2.3 From 56185dedd2a075e5b7e72c18e766a60b890c14a1 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 24 Apr 2017 13:22:15 +0200 Subject: DirectShow: Fix uninitialized memory read in DirectShowMediaTypeEnum::Next() Newly allocated memory was passed to DirectShowMediaType::copy(), which calls DirectShowMediaType::clear() on the target, which crashes when trying to release a COM pointer. Split out a DirectShowMediaType::copyToUninitialized() helper function which does not call clear() for this purpose. Task-number: QTBUG-59515 Change-Id: I2801f4ba2c8da618ff8a1c57c4cea215fff292b4 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/plugins/directshow/helpers/directshowmediatype.cpp | 5 +++++ src/plugins/directshow/helpers/directshowmediatype.h | 1 + src/plugins/directshow/helpers/directshowmediatypeenum.cpp | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/directshow/helpers/directshowmediatype.cpp b/src/plugins/directshow/helpers/directshowmediatype.cpp index d9ddf8248..65882806c 100644 --- a/src/plugins/directshow/helpers/directshowmediatype.cpp +++ b/src/plugins/directshow/helpers/directshowmediatype.cpp @@ -134,6 +134,11 @@ void DirectShowMediaType::copy(AM_MEDIA_TYPE *target, const AM_MEDIA_TYPE *sourc clear(*target); + copyToUninitialized(target, source); +} + +void DirectShowMediaType::copyToUninitialized(AM_MEDIA_TYPE *target, const AM_MEDIA_TYPE *source) +{ *target = *source; if (source->cbFormat > 0) { diff --git a/src/plugins/directshow/helpers/directshowmediatype.h b/src/plugins/directshow/helpers/directshowmediatype.h index 7849ca9b0..c590d406a 100644 --- a/src/plugins/directshow/helpers/directshowmediatype.h +++ b/src/plugins/directshow/helpers/directshowmediatype.h @@ -72,6 +72,7 @@ public: static void init(AM_MEDIA_TYPE *type); static void copy(AM_MEDIA_TYPE *target, const AM_MEDIA_TYPE *source); + static void copyToUninitialized(AM_MEDIA_TYPE *target, const AM_MEDIA_TYPE *source); static void move(AM_MEDIA_TYPE *target, AM_MEDIA_TYPE **source); static void move(AM_MEDIA_TYPE *target, AM_MEDIA_TYPE &source); static void clear(AM_MEDIA_TYPE &type); diff --git a/src/plugins/directshow/helpers/directshowmediatypeenum.cpp b/src/plugins/directshow/helpers/directshowmediatypeenum.cpp index a58993f7f..a42dfdca3 100644 --- a/src/plugins/directshow/helpers/directshowmediatypeenum.cpp +++ b/src/plugins/directshow/helpers/directshowmediatypeenum.cpp @@ -72,7 +72,7 @@ HRESULT DirectShowMediaTypeEnum::Next(ULONG cMediaTypes, AM_MEDIA_TYPE **ppMedia for (ULONG i = 0; i < count; ++i, ++m_index) { ppMediaTypes[i] = reinterpret_cast(CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE))); - DirectShowMediaType::copy(ppMediaTypes[i], &m_mediaTypes.at(m_index)); + DirectShowMediaType::copyToUninitialized(ppMediaTypes[i], &m_mediaTypes.at(m_index)); } if (pcFetched) -- cgit v1.2.3 From f97d5eaaa539e2569f3ca3b8eef6649827b07bc1 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 21 Apr 2017 15:37:59 +0200 Subject: DirectShow: Fix namespaced build with MinGW Remove QT_USE_NAMESPACE from headers and enclose headers/sources in QT_BEGIN/END_NAMESPACE. Fixes MinGW build error: qtbase/src/corelib/global/qtypeinfo.h:246:7: error: specialization of 'template class tn::QTypeInfo' in different namespace [-fpermissive] class QTypeInfo \ ^ qtbase/src/corelib/global/qtypeinfo.h:265:1: note: in expansion of macro 'Q_DECLARE_TYPEINFO_BODY' Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS) ^ helpers\directshowmediatype.h:92:1: note: in expansion of macro 'Q_DECLARE_TYPEINFO' Q_DECLARE_TYPEINFO(DirectShowMediaType, Q_MOVABLE_TYPE); ^ qtbase/src/corelib/global/qtypeinfo.h:57:7: error: from definition of 'template class tn::QTypeInfo' [-fpermissive] class QTypeInfo ^ Task-number: QTBUG-60118 Change-Id: Idfe7a49b50a0046a5cb17630a3ec99615ec6150a Reviewed-by: Christian Stromme --- src/plugins/common/evr/evrcustompresenter.cpp | 4 ++++ src/plugins/common/evr/evrcustompresenter.h | 8 ++++---- src/plugins/common/evr/evrd3dpresentengine.cpp | 4 ++++ src/plugins/common/evr/evrd3dpresentengine.h | 10 +++++----- src/plugins/common/evr/evrhelpers.cpp | 4 ++++ src/plugins/common/evr/evrhelpers.h | 4 +++- src/plugins/common/evr/evrvideowindowcontrol.h | 4 +++- src/plugins/directshow/dsserviceplugin.cpp | 5 ++--- src/plugins/directshow/dsserviceplugin.h | 4 +++- src/plugins/directshow/helpers/directshowbasefilter.cpp | 4 ++++ src/plugins/directshow/helpers/directshowbasefilter.h | 4 +++- src/plugins/directshow/helpers/directshoweventloop.cpp | 4 ++++ src/plugins/directshow/helpers/directshoweventloop.h | 4 ++++ src/plugins/directshow/helpers/directshowmediatype.h | 4 +++- src/plugins/directshow/helpers/directshowmediatypeenum.h | 4 +++- src/plugins/directshow/helpers/directshowobject.cpp | 3 +++ src/plugins/directshow/helpers/directshowobject.h | 4 +++- src/plugins/directshow/helpers/directshowpin.cpp | 4 ++++ src/plugins/directshow/helpers/directshowpin.h | 4 +++- src/plugins/directshow/helpers/directshowpinenum.cpp | 4 ++++ src/plugins/directshow/helpers/directshowpinenum.h | 4 +++- src/plugins/directshow/helpers/directshowutils.cpp | 4 ++++ src/plugins/directshow/helpers/directshowvideobuffer.cpp | 4 ++++ src/plugins/directshow/helpers/directshowvideobuffer.h | 3 +++ .../directshow/player/directshowaudioendpointcontrol.cpp | 4 ++++ src/plugins/directshow/player/directshowaudioendpointcontrol.h | 6 ++++-- .../directshow/player/directshowevrvideowindowcontrol.h | 4 +++- src/plugins/directshow/player/directshowioreader.cpp | 4 ++++ src/plugins/directshow/player/directshowioreader.h | 3 ++- src/plugins/directshow/player/directshowiosource.cpp | 4 ++++ src/plugins/directshow/player/directshowiosource.h | 4 ++++ src/plugins/directshow/player/directshowmetadatacontrol.h | 6 +++--- src/plugins/directshow/player/directshowplayercontrol.h | 4 +++- src/plugins/directshow/player/directshowplayerservice.cpp | 4 ++++ src/plugins/directshow/player/directshowplayerservice.h | 7 +++---- src/plugins/directshow/player/directshowvideorenderercontrol.h | 6 ++++-- src/plugins/directshow/player/videosurfacefilter.cpp | 4 ++++ src/plugins/directshow/player/videosurfacefilter.h | 4 +++- src/plugins/directshow/player/vmr9videowindowcontrol.h | 4 +++- 39 files changed, 136 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/plugins/common/evr/evrcustompresenter.cpp b/src/plugins/common/evr/evrcustompresenter.cpp index 7a26afd10..38e8c3a8f 100644 --- a/src/plugins/common/evr/evrcustompresenter.cpp +++ b/src/plugins/common/evr/evrcustompresenter.cpp @@ -53,6 +53,8 @@ #include #include +QT_BEGIN_NAMESPACE + const static MFRatio g_DefaultFrameRate = { 30, 1 }; static const DWORD SCHEDULER_TIMEOUT = 5000; static const MFTIME ONE_SECOND = 10000000; @@ -2044,3 +2046,5 @@ static QVideoFrame::PixelFormat pixelFormatFromMediaType(IMFMediaType *type) return QVideoFrame::Format_Invalid; } + +QT_END_NAMESPACE diff --git a/src/plugins/common/evr/evrcustompresenter.h b/src/plugins/common/evr/evrcustompresenter.h index 67ae61991..5c240ea95 100644 --- a/src/plugins/common/evr/evrcustompresenter.h +++ b/src/plugins/common/evr/evrcustompresenter.h @@ -49,14 +49,12 @@ #include "evrdefs.h" QT_BEGIN_NAMESPACE -class QAbstractVideoSurface; -QT_END_NAMESPACE - -QT_USE_NAMESPACE class EVRCustomPresenter; class D3DPresentEngine; +class QAbstractVideoSurface; + template class AsyncCallback : public IMFAsyncCallback { @@ -375,4 +373,6 @@ private: bool qt_evr_setCustomPresenter(IUnknown *evr, EVRCustomPresenter *presenter); +QT_END_NAMESPACE + #endif // EVRCUSTOMPRESENTER_H diff --git a/src/plugins/common/evr/evrd3dpresentengine.cpp b/src/plugins/common/evr/evrd3dpresentengine.cpp index ae3d69fc2..4bc2bac83 100644 --- a/src/plugins/common/evr/evrd3dpresentengine.cpp +++ b/src/plugins/common/evr/evrd3dpresentengine.cpp @@ -57,6 +57,8 @@ static const int PRESENTER_BUFFER_COUNT = 3; +QT_BEGIN_NAMESPACE + #ifdef MAYBE_ANGLE EGLWrapper::EGLWrapper() @@ -642,3 +644,5 @@ done: } #endif // MAYBE_ANGLE + +QT_END_NAMESPACE diff --git a/src/plugins/common/evr/evrd3dpresentengine.h b/src/plugins/common/evr/evrd3dpresentengine.h index d181689ec..18a7409fa 100644 --- a/src/plugins/common/evr/evrd3dpresentengine.h +++ b/src/plugins/common/evr/evrd3dpresentengine.h @@ -50,10 +50,6 @@ # define MAYBE_ANGLE #endif -QT_BEGIN_NAMESPACE -class QAbstractVideoSurface; -QT_END_NAMESPACE - struct IDirect3D9Ex; struct IDirect3DDevice9Ex; struct IDirect3DDeviceManager9; @@ -66,7 +62,9 @@ struct IMFMediaType; static const GUID MFSamplePresenter_SampleCounter = { 0xb0bb83cc, 0xf10f, 0x4e2e, { 0xaa, 0x2b, 0x29, 0xea, 0x5e, 0x92, 0xef, 0x85 } }; -QT_USE_NAMESPACE +QT_BEGIN_NAMESPACE + +class QAbstractVideoSurface; #ifdef MAYBE_ANGLE @@ -153,4 +151,6 @@ private: friend class IMFSampleVideoBuffer; }; +QT_END_NAMESPACE + #endif // EVRD3DPRESENTENGINE_H diff --git a/src/plugins/common/evr/evrhelpers.cpp b/src/plugins/common/evr/evrhelpers.cpp index 2e9d4fae6..f4710b1a0 100644 --- a/src/plugins/common/evr/evrhelpers.cpp +++ b/src/plugins/common/evr/evrhelpers.cpp @@ -46,6 +46,8 @@ #define D3DFMT_NV12 (D3DFORMAT)MAKEFOURCC ('N', 'V', '1', '2') #endif +QT_BEGIN_NAMESPACE + HRESULT qt_evr_getFourCC(IMFMediaType *type, DWORD *fourCC) { if (!fourCC) @@ -180,3 +182,5 @@ D3DFORMAT qt_evr_D3DFormatFromPixelFormat(QVideoFrame::PixelFormat format) return D3DFMT_UNKNOWN; } } + +QT_END_NAMESPACE diff --git a/src/plugins/common/evr/evrhelpers.h b/src/plugins/common/evr/evrhelpers.h index 54ab8b848..d2fdfdcae 100644 --- a/src/plugins/common/evr/evrhelpers.h +++ b/src/plugins/common/evr/evrhelpers.h @@ -43,7 +43,7 @@ #include "evrdefs.h" #include -QT_USE_NAMESPACE +QT_BEGIN_NAMESPACE template static inline void qt_evr_safe_release(T **unk) @@ -93,5 +93,7 @@ inline HRESULT qt_evr_getFrameRate(IMFMediaType *pType, MFRatio *pRatio) QVideoFrame::PixelFormat qt_evr_pixelFormatFromD3DFormat(D3DFORMAT format); D3DFORMAT qt_evr_D3DFormatFromPixelFormat(QVideoFrame::PixelFormat format); +QT_END_NAMESPACE + #endif // EVRHELPERS_H diff --git a/src/plugins/common/evr/evrvideowindowcontrol.h b/src/plugins/common/evr/evrvideowindowcontrol.h index 7994b1b5e..fcfe20958 100644 --- a/src/plugins/common/evr/evrvideowindowcontrol.h +++ b/src/plugins/common/evr/evrvideowindowcontrol.h @@ -44,7 +44,7 @@ #include "evrdefs.h" -QT_USE_NAMESPACE +QT_BEGIN_NAMESPACE class EvrVideoWindowControl : public QVideoWindowControl { @@ -104,4 +104,6 @@ private: IMFVideoProcessor *m_processor; }; +QT_END_NAMESPACE + #endif diff --git a/src/plugins/directshow/dsserviceplugin.cpp b/src/plugins/directshow/dsserviceplugin.cpp index 9060bac7c..51be7e500 100644 --- a/src/plugins/directshow/dsserviceplugin.cpp +++ b/src/plugins/directshow/dsserviceplugin.cpp @@ -75,9 +75,6 @@ extern const CLSID CLSID_VideoInputDeviceCategory; QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(qtDirectShowPlugin, "qt.multimedia.plugins.directshow") -QT_END_NAMESPACE - -QT_USE_NAMESPACE static int g_refCount = 0; void addRefCount() @@ -157,3 +154,5 @@ QString DSServicePlugin::deviceDescription(const QByteArray &service, const QByt } return QString(); } + +QT_END_NAMESPACE diff --git a/src/plugins/directshow/dsserviceplugin.h b/src/plugins/directshow/dsserviceplugin.h index b7ac6a86e..f57262e37 100644 --- a/src/plugins/directshow/dsserviceplugin.h +++ b/src/plugins/directshow/dsserviceplugin.h @@ -43,7 +43,7 @@ #include #include "qmediaserviceproviderplugin.h" -QT_USE_NAMESPACE +QT_BEGIN_NAMESPACE class DSServicePlugin : public QMediaServiceProviderPlugin @@ -74,4 +74,6 @@ public: QString deviceDescription(const QByteArray &service, const QByteArray &device); }; +QT_END_NAMESPACE + #endif // DSSERVICEPLUGIN_H diff --git a/src/plugins/directshow/helpers/directshowbasefilter.cpp b/src/plugins/directshow/helpers/directshowbasefilter.cpp index fbf0f6204..3ca7e205e 100644 --- a/src/plugins/directshow/helpers/directshowbasefilter.cpp +++ b/src/plugins/directshow/helpers/directshowbasefilter.cpp @@ -35,6 +35,8 @@ #include "directshowpinenum.h" +QT_BEGIN_NAMESPACE + DirectShowBaseFilter::DirectShowBaseFilter() : m_mutex(QMutex::Recursive) , m_state(State_Stopped) @@ -265,3 +267,5 @@ HRESULT DirectShowBaseFilter::QueryVendorInfo(LPWSTR *pVendorInfo) Q_UNUSED(pVendorInfo); return E_NOTIMPL; } + +QT_END_NAMESPACE diff --git a/src/plugins/directshow/helpers/directshowbasefilter.h b/src/plugins/directshow/helpers/directshowbasefilter.h index cc8588044..19c54233c 100644 --- a/src/plugins/directshow/helpers/directshowbasefilter.h +++ b/src/plugins/directshow/helpers/directshowbasefilter.h @@ -36,7 +36,7 @@ #include "directshowpin.h" -QT_USE_NAMESPACE +QT_BEGIN_NAMESPACE class DirectShowBaseFilter : public DirectShowObject , public IBaseFilter @@ -90,4 +90,6 @@ private: Q_DISABLE_COPY(DirectShowBaseFilter) }; +QT_END_NAMESPACE + #endif // DIRECTSHOWBASEFILTER_H diff --git a/src/plugins/directshow/helpers/directshoweventloop.cpp b/src/plugins/directshow/helpers/directshoweventloop.cpp index 87f969e42..ef85c0429 100644 --- a/src/plugins/directshow/helpers/directshoweventloop.cpp +++ b/src/plugins/directshow/helpers/directshoweventloop.cpp @@ -42,6 +42,8 @@ #include #include +QT_BEGIN_NAMESPACE + class DirectShowPostedEvent { public: @@ -146,3 +148,5 @@ void DirectShowEventLoop::processEvents() locker.relock(); } } + +QT_END_NAMESPACE diff --git a/src/plugins/directshow/helpers/directshoweventloop.h b/src/plugins/directshow/helpers/directshoweventloop.h index 09d986de7..609e53134 100644 --- a/src/plugins/directshow/helpers/directshoweventloop.h +++ b/src/plugins/directshow/helpers/directshoweventloop.h @@ -46,6 +46,8 @@ #include +QT_BEGIN_NAMESPACE + class DirectShowPostedEvent; class DirectShowEventLoop : public QObject @@ -73,4 +75,6 @@ private: QMutex m_mutex; }; +QT_END_NAMESPACE + #endif diff --git a/src/plugins/directshow/helpers/directshowmediatype.h b/src/plugins/directshow/helpers/directshowmediatype.h index c590d406a..7f495f3b2 100644 --- a/src/plugins/directshow/helpers/directshowmediatype.h +++ b/src/plugins/directshow/helpers/directshowmediatype.h @@ -47,7 +47,7 @@ #include #include -QT_USE_NAMESPACE +QT_BEGIN_NAMESPACE class DirectShowMediaType { @@ -92,4 +92,6 @@ private: Q_DECLARE_TYPEINFO(DirectShowMediaType, Q_MOVABLE_TYPE); +QT_END_NAMESPACE + #endif diff --git a/src/plugins/directshow/helpers/directshowmediatypeenum.h b/src/plugins/directshow/helpers/directshowmediatypeenum.h index 050df0881..c022677cc 100644 --- a/src/plugins/directshow/helpers/directshowmediatypeenum.h +++ b/src/plugins/directshow/helpers/directshowmediatypeenum.h @@ -37,7 +37,7 @@ #include "directshowobject.h" #include -QT_USE_NAMESPACE +QT_BEGIN_NAMESPACE class DirectShowPin; class DirectShowMediaType; @@ -69,4 +69,6 @@ private: int m_index; }; +QT_END_NAMESPACE + #endif // DIRECTSHOWMEDIATYPEENUM_H diff --git a/src/plugins/directshow/helpers/directshowobject.cpp b/src/plugins/directshow/helpers/directshowobject.cpp index b9d989f6e..db1817a8d 100644 --- a/src/plugins/directshow/helpers/directshowobject.cpp +++ b/src/plugins/directshow/helpers/directshowobject.cpp @@ -39,6 +39,8 @@ #include "directshowobject.h" +QT_BEGIN_NAMESPACE + DirectShowObject::DirectShowObject() : m_ref(1) { @@ -81,3 +83,4 @@ HRESULT GetInterface(IUnknown *pUnk, void **ppv) return S_OK; } +QT_END_NAMESPACE diff --git a/src/plugins/directshow/helpers/directshowobject.h b/src/plugins/directshow/helpers/directshowobject.h index 3aba06f46..4a8938635 100644 --- a/src/plugins/directshow/helpers/directshowobject.h +++ b/src/plugins/directshow/helpers/directshowobject.h @@ -36,7 +36,7 @@ #include "directshowglobal.h" -QT_USE_NAMESPACE +QT_BEGIN_NAMESPACE class DirectShowObject { @@ -71,4 +71,6 @@ public: \ return unref(); \ }; +QT_END_NAMESPACE + #endif // DIRECTSHOWOBJECT_H diff --git a/src/plugins/directshow/helpers/directshowpin.cpp b/src/plugins/directshow/helpers/directshowpin.cpp index f501747f9..44c6b1520 100644 --- a/src/plugins/directshow/helpers/directshowpin.cpp +++ b/src/plugins/directshow/helpers/directshowpin.cpp @@ -39,6 +39,8 @@ #include +QT_BEGIN_NAMESPACE + DirectShowPin::DirectShowPin(DirectShowBaseFilter *filter, const QString &name, PIN_DIRECTION direction) : m_mutex(QMutex::Recursive) , m_filter(filter) @@ -728,3 +730,5 @@ HRESULT DirectShowInputPin::ReceiveCanBlock() return outputPins == 0 ? S_OK : S_FALSE; } + +QT_END_NAMESPACE diff --git a/src/plugins/directshow/helpers/directshowpin.h b/src/plugins/directshow/helpers/directshowpin.h index b8207abae..d518726b4 100644 --- a/src/plugins/directshow/helpers/directshowpin.h +++ b/src/plugins/directshow/helpers/directshowpin.h @@ -40,7 +40,7 @@ #include #include -QT_USE_NAMESPACE +QT_BEGIN_NAMESPACE class DirectShowBaseFilter; @@ -181,4 +181,6 @@ private: Q_DISABLE_COPY(DirectShowInputPin) }; +QT_END_NAMESPACE + #endif // DIRECTSHOWPIN_H diff --git a/src/plugins/directshow/helpers/directshowpinenum.cpp b/src/plugins/directshow/helpers/directshowpinenum.cpp index 61aca8b9c..910bba77d 100644 --- a/src/plugins/directshow/helpers/directshowpinenum.cpp +++ b/src/plugins/directshow/helpers/directshowpinenum.cpp @@ -40,6 +40,8 @@ #include "directshowpinenum.h" #include "directshowbasefilter.h" +QT_BEGIN_NAMESPACE + DirectShowPinEnum::DirectShowPinEnum(DirectShowBaseFilter *filter) : m_filter(filter) , m_index(0) @@ -124,3 +126,5 @@ HRESULT DirectShowPinEnum::Clone(IEnumPins **ppEnum) return E_POINTER; } } + +QT_END_NAMESPACE diff --git a/src/plugins/directshow/helpers/directshowpinenum.h b/src/plugins/directshow/helpers/directshowpinenum.h index 84c2a7579..77214e376 100644 --- a/src/plugins/directshow/helpers/directshowpinenum.h +++ b/src/plugins/directshow/helpers/directshowpinenum.h @@ -45,7 +45,7 @@ #include #include "directshowpin.h" -QT_USE_NAMESPACE +QT_BEGIN_NAMESPACE class DirectShowBaseFilter; @@ -76,4 +76,6 @@ private: int m_index; }; +QT_END_NAMESPACE + #endif diff --git a/src/plugins/directshow/helpers/directshowutils.cpp b/src/plugins/directshow/helpers/directshowutils.cpp index d9701fd99..96fabd6da 100644 --- a/src/plugins/directshow/helpers/directshowutils.cpp +++ b/src/plugins/directshow/helpers/directshowutils.cpp @@ -39,6 +39,8 @@ #include "directshowutils.h" +QT_BEGIN_NAMESPACE + /** * @brief DirectShowUtils::isPinConnected * @param pin @@ -307,3 +309,5 @@ bool DirectShowUtils::connectFilters(IGraphBuilder *graph, return SUCCEEDED(*hrOut); } + +QT_END_NAMESPACE diff --git a/src/plugins/directshow/helpers/directshowvideobuffer.cpp b/src/plugins/directshow/helpers/directshowvideobuffer.cpp index 3204e9f7e..7f94da97e 100644 --- a/src/plugins/directshow/helpers/directshowvideobuffer.cpp +++ b/src/plugins/directshow/helpers/directshowvideobuffer.cpp @@ -39,6 +39,8 @@ #include "directshowvideobuffer.h" +QT_BEGIN_NAMESPACE + DirectShowVideoBuffer::DirectShowVideoBuffer(IMediaSample *sample, int bytesPerLine) : QAbstractVideoBuffer(NoHandle) , m_sample(sample) @@ -82,3 +84,5 @@ QAbstractVideoBuffer::MapMode DirectShowVideoBuffer::mapMode() const { return m_mapMode; } + +QT_END_NAMESPACE diff --git a/src/plugins/directshow/helpers/directshowvideobuffer.h b/src/plugins/directshow/helpers/directshowvideobuffer.h index 10089c75a..85e02b53d 100644 --- a/src/plugins/directshow/helpers/directshowvideobuffer.h +++ b/src/plugins/directshow/helpers/directshowvideobuffer.h @@ -44,6 +44,8 @@ #include +QT_BEGIN_NAMESPACE + class DirectShowVideoBuffer : public QAbstractVideoBuffer { public: @@ -63,5 +65,6 @@ private: MapMode m_mapMode; }; +QT_END_NAMESPACE #endif diff --git a/src/plugins/directshow/player/directshowaudioendpointcontrol.cpp b/src/plugins/directshow/player/directshowaudioendpointcontrol.cpp index f4e75f4e2..78733972a 100644 --- a/src/plugins/directshow/player/directshowaudioendpointcontrol.cpp +++ b/src/plugins/directshow/player/directshowaudioendpointcontrol.cpp @@ -42,6 +42,8 @@ #include "directshowglobal.h" #include "directshowplayerservice.h" +QT_BEGIN_NAMESPACE + DirectShowAudioEndpointControl::DirectShowAudioEndpointControl( DirectShowPlayerService *service, QObject *parent) : QAudioOutputSelectorControl(parent) @@ -157,3 +159,5 @@ void DirectShowAudioEndpointControl::updateEndpoints() oleMalloc->Release(); } } + +QT_END_NAMESPACE diff --git a/src/plugins/directshow/player/directshowaudioendpointcontrol.h b/src/plugins/directshow/player/directshowaudioendpointcontrol.h index 2d1763ea3..e0e6a1545 100644 --- a/src/plugins/directshow/player/directshowaudioendpointcontrol.h +++ b/src/plugins/directshow/player/directshowaudioendpointcontrol.h @@ -44,9 +44,9 @@ #include -class DirectShowPlayerService; +QT_BEGIN_NAMESPACE -QT_USE_NAMESPACE +class DirectShowPlayerService; class DirectShowAudioEndpointControl : public QAudioOutputSelectorControl { @@ -76,5 +76,7 @@ private: QString m_activeEndpoint; }; +QT_END_NAMESPACE + #endif diff --git a/src/plugins/directshow/player/directshowevrvideowindowcontrol.h b/src/plugins/directshow/player/directshowevrvideowindowcontrol.h index 5aa304bca..fb661780f 100644 --- a/src/plugins/directshow/player/directshowevrvideowindowcontrol.h +++ b/src/plugins/directshow/player/directshowevrvideowindowcontrol.h @@ -44,7 +44,7 @@ struct IBaseFilter; -QT_USE_NAMESPACE +QT_BEGIN_NAMESPACE class DirectShowEvrVideoWindowControl : public EvrVideoWindowControl { @@ -58,4 +58,6 @@ private: IBaseFilter *m_evrFilter; }; +QT_END_NAMESPACE + #endif // DIRECTSHOWEVRVIDEOWINDOWCONTROL_H diff --git a/src/plugins/directshow/player/directshowioreader.cpp b/src/plugins/directshow/player/directshowioreader.cpp index a35124b1e..7f3303633 100644 --- a/src/plugins/directshow/player/directshowioreader.cpp +++ b/src/plugins/directshow/player/directshowioreader.cpp @@ -48,6 +48,8 @@ #include #include +QT_BEGIN_NAMESPACE + class DirectShowSampleRequest { public: @@ -492,3 +494,5 @@ void DirectShowIOReader::flushRequests() m_readyHead = m_readyTail; } } + +QT_END_NAMESPACE diff --git a/src/plugins/directshow/player/directshowioreader.h b/src/plugins/directshow/player/directshowioreader.h index deb5d5327..2d62c0b95 100644 --- a/src/plugins/directshow/player/directshowioreader.h +++ b/src/plugins/directshow/player/directshowioreader.h @@ -48,7 +48,6 @@ QT_BEGIN_NAMESPACE class QIODevice; -QT_END_NAMESPACE class DirectShowEventLoop; class DirectShowIOSource; @@ -115,4 +114,6 @@ private: QWaitCondition m_wait; }; +QT_END_NAMESPACE + #endif diff --git a/src/plugins/directshow/player/directshowiosource.cpp b/src/plugins/directshow/player/directshowiosource.cpp index 96b4b14bf..b3aa3fab9 100644 --- a/src/plugins/directshow/player/directshowiosource.cpp +++ b/src/plugins/directshow/player/directshowiosource.cpp @@ -47,6 +47,8 @@ #include #include +QT_BEGIN_NAMESPACE + static const GUID directshow_subtypes[] = { MEDIASUBTYPE_NULL, @@ -581,3 +583,5 @@ HRESULT DirectShowIOSource::QueryDirection(PIN_DIRECTION *pPinDir) return S_OK; } } + +QT_END_NAMESPACE diff --git a/src/plugins/directshow/player/directshowiosource.h b/src/plugins/directshow/player/directshowiosource.h index 702bfed61..43df6c34f 100644 --- a/src/plugins/directshow/player/directshowiosource.h +++ b/src/plugins/directshow/player/directshowiosource.h @@ -46,6 +46,8 @@ #include +QT_BEGIN_NAMESPACE + class DirectShowIOSource : public IBaseFilter , public IAMFilterMiscFlags @@ -131,4 +133,6 @@ private: QMutex m_mutex; }; +QT_END_NAMESPACE + #endif diff --git a/src/plugins/directshow/player/directshowmetadatacontrol.h b/src/plugins/directshow/player/directshowmetadatacontrol.h index b42b48c67..3d2fa5e8e 100644 --- a/src/plugins/directshow/player/directshowmetadatacontrol.h +++ b/src/plugins/directshow/player/directshowmetadatacontrol.h @@ -48,9 +48,7 @@ #include -class DirectShowPlayerService; - -QT_USE_NAMESPACE +QT_BEGIN_NAMESPACE class DirectShowMetaDataControl : public QMetaDataReaderControl { @@ -83,4 +81,6 @@ private: bool m_available; }; +QT_END_NAMESPACE + #endif diff --git a/src/plugins/directshow/player/directshowplayercontrol.h b/src/plugins/directshow/player/directshowplayercontrol.h index 184951544..fd2c21c38 100644 --- a/src/plugins/directshow/player/directshowplayercontrol.h +++ b/src/plugins/directshow/player/directshowplayercontrol.h @@ -49,7 +49,7 @@ #include "directshowplayerservice.h" -QT_USE_NAMESPACE +QT_BEGIN_NAMESPACE class DirectShowPlayerControl : public QMediaPlayerControl { @@ -148,4 +148,6 @@ private: }; +QT_END_NAMESPACE + #endif diff --git a/src/plugins/directshow/player/directshowplayerservice.cpp b/src/plugins/directshow/player/directshowplayerservice.cpp index 5fbb6ef05..4a75c9551 100644 --- a/src/plugins/directshow/player/directshowplayerservice.cpp +++ b/src/plugins/directshow/player/directshowplayerservice.cpp @@ -77,6 +77,8 @@ # include #endif +QT_BEGIN_NAMESPACE + Q_GLOBAL_STATIC(DirectShowEventLoop, qt_directShowEventLoop) static QString comError(HRESULT hr) @@ -1454,3 +1456,5 @@ void DirectShowPlayerService::run() m_executingTask = 0; } } + +QT_END_NAMESPACE diff --git a/src/plugins/directshow/player/directshowplayerservice.h b/src/plugins/directshow/player/directshowplayerservice.h index d933bd660..dc0226001 100644 --- a/src/plugins/directshow/player/directshowplayerservice.h +++ b/src/plugins/directshow/player/directshowplayerservice.h @@ -55,17 +55,15 @@ #include #include +QT_BEGIN_NAMESPACE + class DirectShowAudioEndpointControl; class DirectShowMetaDataControl; class DirectShowPlayerControl; class DirectShowVideoRendererControl; -QT_BEGIN_NAMESPACE class QMediaContent; class QVideoWindowControl; -QT_END_NAMESPACE - -QT_USE_NAMESPACE class DirectShowPlayerService : public QMediaService { @@ -213,5 +211,6 @@ private: friend class DirectShowPlayerServiceThread; }; +QT_END_NAMESPACE #endif diff --git a/src/plugins/directshow/player/directshowvideorenderercontrol.h b/src/plugins/directshow/player/directshowvideorenderercontrol.h index 36c5b2248..ce515a329 100644 --- a/src/plugins/directshow/player/directshowvideorenderercontrol.h +++ b/src/plugins/directshow/player/directshowvideorenderercontrol.h @@ -47,13 +47,13 @@ #include +QT_BEGIN_NAMESPACE + class DirectShowEventLoop; #if QT_CONFIG(evr) class EVRCustomPresenter; #endif -QT_USE_NAMESPACE - class DirectShowVideoRendererControl : public QVideoRendererControl { Q_OBJECT @@ -78,4 +78,6 @@ private: #endif }; +QT_END_NAMESPACE + #endif diff --git a/src/plugins/directshow/player/videosurfacefilter.cpp b/src/plugins/directshow/player/videosurfacefilter.cpp index 13f767a85..656cd5a7c 100644 --- a/src/plugins/directshow/player/videosurfacefilter.cpp +++ b/src/plugins/directshow/player/videosurfacefilter.cpp @@ -49,6 +49,8 @@ #include +QT_BEGIN_NAMESPACE + Q_LOGGING_CATEGORY(qLcRenderFilter, "qt.multimedia.plugins.directshow.renderfilter") // { e23cad72-153d-406c-bf3f-4c4b523d96f2 } @@ -786,3 +788,5 @@ bool VideoSurfaceFilter::event(QEvent *e) return QObject::event(e); } + +QT_END_NAMESPACE diff --git a/src/plugins/directshow/player/videosurfacefilter.h b/src/plugins/directshow/player/videosurfacefilter.h index 6d6cc7593..ad253d564 100644 --- a/src/plugins/directshow/player/videosurfacefilter.h +++ b/src/plugins/directshow/player/videosurfacefilter.h @@ -49,8 +49,8 @@ #include QT_BEGIN_NAMESPACE + class QAbstractVideoSurface; -QT_END_NAMESPACE class DirectShowEventLoop; class VideoSurfaceInputPin; @@ -157,4 +157,6 @@ private: friend class VideoSurfaceInputPin; }; +QT_END_NAMESPACE + #endif diff --git a/src/plugins/directshow/player/vmr9videowindowcontrol.h b/src/plugins/directshow/player/vmr9videowindowcontrol.h index 6f6e55362..ed3b53233 100644 --- a/src/plugins/directshow/player/vmr9videowindowcontrol.h +++ b/src/plugins/directshow/player/vmr9videowindowcontrol.h @@ -46,7 +46,7 @@ #include #include -QT_USE_NAMESPACE +QT_BEGIN_NAMESPACE class Vmr9VideoWindowControl : public QVideoWindowControl { @@ -103,4 +103,6 @@ private: bool m_fullScreen; }; +QT_END_NAMESPACE + #endif -- cgit v1.2.3 From 9dbdd5db797fccb8932f49d7380fb5f5eda12cf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Thu, 6 Apr 2017 17:02:55 +0200 Subject: AVF: Fix mediaplayer state and status issues This fixes the issues that were causing the whole qmediaplayerbackend test to be blacklisted on macOS. Task-number: QTBUG-46368 Change-Id: I59a35dd50a9c07e4e4382c5facb391f5c8a27ee7 Reviewed-by: Timur Pocheptsov --- .../mediaplayer/avfmediaplayercontrol.mm | 5 +- .../mediaplayer/avfmediaplayersession.h | 4 +- .../mediaplayer/avfmediaplayersession.mm | 133 +++++++++++++-------- 3 files changed, 90 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/src/plugins/avfoundation/mediaplayer/avfmediaplayercontrol.mm b/src/plugins/avfoundation/mediaplayer/avfmediaplayercontrol.mm index 7f6168dea..5f7bae1c8 100644 --- a/src/plugins/avfoundation/mediaplayer/avfmediaplayercontrol.mm +++ b/src/plugins/avfoundation/mediaplayer/avfmediaplayercontrol.mm @@ -97,9 +97,12 @@ const QIODevice *AVFMediaPlayerControl::mediaStream() const void AVFMediaPlayerControl::setMedia(const QMediaContent &content, QIODevice *stream) { + const QMediaContent oldContent = m_session->media(); + m_session->setMedia(content, stream); - Q_EMIT mediaChanged(content); + if (content != oldContent) + Q_EMIT mediaChanged(content); } qint64 AVFMediaPlayerControl::position() const diff --git a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.h b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.h index 5696faf15..ef854e23f 100644 --- a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.h +++ b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.h @@ -99,10 +99,12 @@ public Q_SLOTS: void setMuted(bool muted); void processEOS(); - void processLoadStateChange(); + void processLoadStateChange(QMediaPlayer::State newState); void processPositionChange(); void processMediaLoadError(); + void processLoadStateChange(); + void processLoadStateFailure(); Q_SIGNALS: void positionChanged(qint64 position); void durationChanged(qint64 duration); diff --git a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm index e15c2e44a..f4eb8a4ea 100644 --- a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm +++ b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm @@ -324,7 +324,7 @@ static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMe [self assetFailedToPrepareForPlayback:playerItem.error]; if (self.session) - QMetaObject::invokeMethod(m_session, "processLoadStateChange", Qt::AutoConnection); + QMetaObject::invokeMethod(m_session, "processLoadStateFailure", Qt::AutoConnection); } break; } @@ -474,27 +474,29 @@ void AVFMediaPlayerSession::setMedia(const QMediaContent &content, QIODevice *st if (content.isNull() || content.canonicalUrl().isEmpty()) { m_mediaStatus = QMediaPlayer::NoMedia; - m_state = QMediaPlayer::StoppedState; - if (m_mediaStatus != oldMediaStatus) Q_EMIT mediaStatusChanged(m_mediaStatus); + m_state = QMediaPlayer::StoppedState; if (m_state != oldState) Q_EMIT stateChanged(m_state); return; - } else { - - m_mediaStatus = QMediaPlayer::LoadingMedia; - if (m_mediaStatus != oldMediaStatus) - Q_EMIT mediaStatusChanged(m_mediaStatus); } + m_mediaStatus = QMediaPlayer::LoadingMedia; + if (m_mediaStatus != oldMediaStatus) + Q_EMIT mediaStatusChanged(m_mediaStatus); + //Load AVURLAsset //initialize asset using content's URL NSString *urlString = [NSString stringWithUTF8String:content.canonicalUrl().toEncoded().constData()]; NSURL *url = [NSURL URLWithString:urlString]; [(AVFMediaPlayerSessionObserver*)m_observer setURL:url]; + + m_state = QMediaPlayer::StoppedState; + if (m_state != oldState) + Q_EMIT stateChanged(m_state); } qint64 AVFMediaPlayerSession::position() const @@ -639,7 +641,9 @@ void AVFMediaPlayerSession::setPosition(qint64 pos) m_requestedPosition = pos; Q_EMIT positionChanged(m_requestedPosition); return; - } else if (!isSeekable()) { + } + + if (!isSeekable()) { if (m_requestedPosition != -1) { m_requestedPosition = -1; Q_EMIT positionChanged(position()); @@ -655,9 +659,14 @@ void AVFMediaPlayerSession::setPosition(qint64 pos) newTime.value = (pos / 1000.0f) * newTime.timescale; [playerItem seekToTime:newTime]; - //reset the EndOfMedia status position is changed after playback is finished - if (m_mediaStatus == QMediaPlayer::EndOfMedia) - processLoadStateChange(); + Q_EMIT positionChanged(pos); + + // Reset media status if the current status is EndOfMedia + if (m_mediaStatus == QMediaPlayer::EndOfMedia) { + QMediaPlayer::MediaStatus newMediaStatus = (m_state == QMediaPlayer::PausedState) ? QMediaPlayer::BufferedMedia + : QMediaPlayer::LoadedMedia; + Q_EMIT mediaStatusChanged((m_mediaStatus = newMediaStatus)); + } } void AVFMediaPlayerSession::play() @@ -666,27 +675,28 @@ void AVFMediaPlayerSession::play() qDebug() << Q_FUNC_INFO << "currently: " << m_state; #endif - if (m_state == QMediaPlayer::PlayingState) + if (m_mediaStatus == QMediaPlayer::NoMedia || m_mediaStatus == QMediaPlayer::InvalidMedia) return; - m_state = QMediaPlayer::PlayingState; + if (m_state == QMediaPlayer::PlayingState) + return; if (m_videoOutput) { m_videoOutput->setLayer([(AVFMediaPlayerSessionObserver*)m_observer playerLayer]); } - //reset the EndOfMedia status if the same file is played again - if (m_mediaStatus == QMediaPlayer::EndOfMedia) { + // Reset media status if the current status is EndOfMedia + if (m_mediaStatus == QMediaPlayer::EndOfMedia) setPosition(0); - processLoadStateChange(); - } if (m_mediaStatus == QMediaPlayer::LoadedMedia || m_mediaStatus == QMediaPlayer::BufferedMedia) { // Setting the rate starts playback [[(AVFMediaPlayerSessionObserver*)m_observer player] setRate:m_rate]; } - //processLoadStateChange(); + m_state = QMediaPlayer::PlayingState; + processLoadStateChange(); + Q_EMIT stateChanged(m_state); } @@ -696,6 +706,9 @@ void AVFMediaPlayerSession::pause() qDebug() << Q_FUNC_INFO << "currently: " << m_state; #endif + if (m_mediaStatus == QMediaPlayer::NoMedia) + return; + if (m_state == QMediaPlayer::PausedState) return; @@ -705,13 +718,13 @@ void AVFMediaPlayerSession::pause() m_videoOutput->setLayer([(AVFMediaPlayerSessionObserver*)m_observer playerLayer]); } - //reset the EndOfMedia status if the same file is played again + [[(AVFMediaPlayerSessionObserver*)m_observer player] pause]; + + // Reset media status if the current status is EndOfMedia if (m_mediaStatus == QMediaPlayer::EndOfMedia) - processLoadStateChange(); + setPosition(0); - [[(AVFMediaPlayerSessionObserver*)m_observer player] pause]; - //processLoadStateChange(); Q_EMIT stateChanged(m_state); } @@ -724,7 +737,6 @@ void AVFMediaPlayerSession::stop() if (m_state == QMediaPlayer::StoppedState) return; - m_state = QMediaPlayer::StoppedState; // AVPlayer doesn't have stop(), only pause() and play(). [[(AVFMediaPlayerSessionObserver*)m_observer player] pause]; setPosition(0); @@ -733,9 +745,11 @@ void AVFMediaPlayerSession::stop() m_videoOutput->setLayer(0); } - processLoadStateChange(); - Q_EMIT stateChanged(m_state); + if (m_mediaStatus == QMediaPlayer::BufferedMedia) + Q_EMIT mediaStatusChanged((m_mediaStatus = QMediaPlayer::LoadedMedia)); + Q_EMIT positionChanged(position()); + Q_EMIT stateChanged((m_state = QMediaPlayer::StoppedState)); } void AVFMediaPlayerSession::setVolume(int volume) @@ -782,6 +796,8 @@ void AVFMediaPlayerSession::processEOS() #endif Q_EMIT positionChanged(position()); m_mediaStatus = QMediaPlayer::EndOfMedia; + Q_EMIT mediaStatusChanged(m_mediaStatus); + m_state = QMediaPlayer::StoppedState; // At this point, frames should not be rendered anymore. @@ -789,23 +805,26 @@ void AVFMediaPlayerSession::processEOS() if (m_videoOutput) m_videoOutput->setLayer(0); - Q_EMIT mediaStatusChanged(m_mediaStatus); Q_EMIT stateChanged(m_state); } -void AVFMediaPlayerSession::processLoadStateChange() +void AVFMediaPlayerSession::processLoadStateChange(QMediaPlayer::State newState) { AVPlayerStatus currentStatus = [[(AVFMediaPlayerSessionObserver*)m_observer player] status]; #ifdef QT_DEBUG_AVF - qDebug() << Q_FUNC_INFO << currentStatus; + qDebug() << Q_FUNC_INFO << currentStatus << ", " << m_mediaStatus << ", " << newState; #endif - QMediaPlayer::MediaStatus newStatus = QMediaPlayer::NoMedia; - bool isPlaying = (m_state != QMediaPlayer::StoppedState); + if (m_mediaStatus == QMediaPlayer::NoMedia) + return; if (currentStatus == AVPlayerStatusReadyToPlay) { + + QMediaPlayer::MediaStatus newStatus = m_mediaStatus; + AVPlayerItem *playerItem = [(AVFMediaPlayerSessionObserver*)m_observer playerItem]; + if (playerItem) { // Check each track for audio and video content AVAssetTrack *videoTrack = nil; @@ -832,35 +851,52 @@ void AVFMediaPlayerSession::processLoadStateChange() videoTrack.naturalSize.width, videoTrack.naturalSize.height); - if (m_videoOutput && m_state != QMediaPlayer::StoppedState) { + if (m_videoOutput && newState != QMediaPlayer::StoppedState) { m_videoOutput->setLayer(playerLayer); } } - } - qint64 currentDuration = duration(); - if (m_duration != currentDuration) - Q_EMIT durationChanged(m_duration = currentDuration); + qint64 currentDuration = duration(); + if (m_duration != currentDuration) + Q_EMIT durationChanged(m_duration = currentDuration); - if (m_requestedPosition != -1) { - setPosition(m_requestedPosition); - m_requestedPosition = -1; + if (m_requestedPosition != -1) { + setPosition(m_requestedPosition); + m_requestedPosition = -1; + } } - newStatus = isPlaying ? QMediaPlayer::BufferedMedia : QMediaPlayer::LoadedMedia; + newStatus = (newState != QMediaPlayer::StoppedState) ? QMediaPlayer::BufferedMedia + : QMediaPlayer::LoadedMedia; + + if (newStatus != m_mediaStatus) + Q_EMIT mediaStatusChanged((m_mediaStatus = newStatus)); - if (m_state == QMediaPlayer::PlayingState && [(AVFMediaPlayerSessionObserver*)m_observer player]) { - // Setting the rate is enough to start playback, no need to call play() - [[(AVFMediaPlayerSessionObserver*)m_observer player] setRate:m_rate]; - } } - if (newStatus != m_mediaStatus) - Q_EMIT mediaStatusChanged(m_mediaStatus = newStatus); + if (newState == QMediaPlayer::PlayingState && [(AVFMediaPlayerSessionObserver*)m_observer player]) { + // Setting the rate is enough to start playback, no need to call play() + [[(AVFMediaPlayerSessionObserver*)m_observer player] setRate:m_rate]; + } +} + + +void AVFMediaPlayerSession::processLoadStateChange() +{ + processLoadStateChange(m_state); +} + + +void AVFMediaPlayerSession::processLoadStateFailure() +{ + Q_EMIT stateChanged((m_state = QMediaPlayer::StoppedState)); } void AVFMediaPlayerSession::processPositionChange() { + if (m_state == QMediaPlayer::StoppedState) + return; + Q_EMIT positionChanged(position()); } @@ -871,10 +907,7 @@ void AVFMediaPlayerSession::processMediaLoadError() Q_EMIT positionChanged(position()); } - m_mediaStatus = QMediaPlayer::InvalidMedia; - m_state = QMediaPlayer::StoppedState; + Q_EMIT mediaStatusChanged((m_mediaStatus = QMediaPlayer::InvalidMedia)); Q_EMIT error(QMediaPlayer::FormatError, tr("Failed to load media")); - Q_EMIT mediaStatusChanged(m_mediaStatus); - Q_EMIT stateChanged(m_state); } -- cgit v1.2.3 From f7e5f12149b73b60c594be626eeac8c2aa34beda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Thu, 20 Apr 2017 17:23:11 +0200 Subject: Android: Fix crash caused by stale video-frame objects Make sure that the frame being processed is still valid, that is, the size is valid and correct, and that the frame buffer is accessible. Task-number: QTBUG-60115 Change-Id: Ic64b6f7d45d92b7923d97d6ecdc630da31abee17 Reviewed-by: Michael Dippold Reviewed-by: Eirik Aavitsland --- .../android/src/common/qandroidvideooutput.cpp | 52 +++++++++++++++------- .../android/src/common/qandroidvideooutput.h | 2 +- 2 files changed, 36 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/plugins/android/src/common/qandroidvideooutput.cpp b/src/plugins/android/src/common/qandroidvideooutput.cpp index 1d0df27f2..b425b9d89 100644 --- a/src/plugins/android/src/common/qandroidvideooutput.cpp +++ b/src/plugins/android/src/common/qandroidvideooutput.cpp @@ -86,11 +86,12 @@ void OpenGLResourcesDeleter::deleteShaderProgramHelper(void *prog) class AndroidTextureVideoBuffer : public QAbstractVideoBuffer { public: - AndroidTextureVideoBuffer(QAndroidTextureVideoOutput *output) + AndroidTextureVideoBuffer(QAndroidTextureVideoOutput *output, const QSize &size) : QAbstractVideoBuffer(GLTextureHandle) + , m_mapMode(NotMapped) , m_output(output) + , m_size(size) , m_textureUpdated(false) - , m_mapMode(NotMapped) { } @@ -100,8 +101,7 @@ public: uchar *map(MapMode mode, int *numBytes, int *bytesPerLine) { - if (m_mapMode == NotMapped && mode == ReadOnly) { - updateFrame(); + if (m_mapMode == NotMapped && mode == ReadOnly && updateFrame()) { m_mapMode = mode; m_image = m_output->m_fbo->toImage(); @@ -126,24 +126,41 @@ public: QVariant handle() const { AndroidTextureVideoBuffer *that = const_cast(this); - that->updateFrame(); + if (!that->updateFrame()) + return QVariant(); + return m_output->m_fbo->texture(); } private: - void updateFrame() + bool updateFrame() { - if (!m_textureUpdated) { - // update the video texture (called from the render thread) - m_output->renderFrameToFbo(); - m_textureUpdated = true; - } + // Even though the texture was updated in a previous call, we need to re-check + // that this has not become a stale buffer, e.g., if the output size changed or + // has since became invalid. + if (!m_output->m_nativeSize.isValid()) + return false; + + // Size changed + if (m_output->m_nativeSize != m_size) + return false; + + // In the unlikely event that we don't have a valid fbo, but have a valid size, + // force an update. + const bool forceUpdate = !m_output->m_fbo; + + if (m_textureUpdated && !forceUpdate) + return true; + + // update the video texture (called from the render thread) + return (m_textureUpdated = m_output->renderFrameToFbo()); } - QAndroidTextureVideoOutput *m_output; - bool m_textureUpdated; MapMode m_mapMode; + QAndroidTextureVideoOutput *m_output; QImage m_image; + QSize m_size; + bool m_textureUpdated; }; QAndroidTextureVideoOutput::QAndroidTextureVideoOutput(QObject *parent) @@ -267,7 +284,6 @@ AndroidSurfaceTexture *QAndroidTextureVideoOutput::surfaceTexture() void QAndroidTextureVideoOutput::setVideoSize(const QSize &size) { QMutexLocker locker(&m_mutex); - if (m_nativeSize == size) return; @@ -297,7 +313,7 @@ void QAndroidTextureVideoOutput::onFrameAvailable() if (!m_nativeSize.isValid() || !m_surface) return; - QAbstractVideoBuffer *buffer = new AndroidTextureVideoBuffer(this); + QAbstractVideoBuffer *buffer = new AndroidTextureVideoBuffer(this, m_nativeSize); QVideoFrame frame(buffer, m_nativeSize, QVideoFrame::Format_BGR32); if (m_surface->isActive() && (m_surface->surfaceFormat().pixelFormat() != frame.pixelFormat() @@ -316,12 +332,12 @@ void QAndroidTextureVideoOutput::onFrameAvailable() m_surface->present(frame); } -void QAndroidTextureVideoOutput::renderFrameToFbo() +bool QAndroidTextureVideoOutput::renderFrameToFbo() { QMutexLocker locker(&m_mutex); if (!m_nativeSize.isValid() || !m_surfaceTexture) - return; + return false; createGLResources(); @@ -376,6 +392,8 @@ void QAndroidTextureVideoOutput::renderFrameToFbo() glEnable(GL_SCISSOR_TEST); if (blendEnabled) glEnable(GL_BLEND); + + return true; } void QAndroidTextureVideoOutput::createGLResources() diff --git a/src/plugins/android/src/common/qandroidvideooutput.h b/src/plugins/android/src/common/qandroidvideooutput.h index a12db75a2..936e4c40b 100644 --- a/src/plugins/android/src/common/qandroidvideooutput.h +++ b/src/plugins/android/src/common/qandroidvideooutput.h @@ -112,7 +112,7 @@ private Q_SLOTS: private: bool initSurfaceTexture(); - void renderFrameToFbo(); + bool renderFrameToFbo(); void createGLResources(); QMutex m_mutex; -- cgit v1.2.3 From 03368d61c2cc809a2a3ba209694b71bb12d1c894 Mon Sep 17 00:00:00 2001 From: Jani Heikkinen Date: Tue, 2 May 2017 14:54:16 +0300 Subject: Fix licensing - Remove unused license files - Switch old LGPLv21 license headers with LGPL one Task-number: QTBUG-57147 Change-Id: If939b9a09e0cd5ccda7f12172363cbc8f78297e8 Reviewed-by: Yoann Lopes --- .../directshow/helpers/directshowbasefilter.cpp | 34 +++++++++++++--------- .../directshow/helpers/directshowbasefilter.h | 34 +++++++++++++--------- .../directshow/helpers/directshowmediatypeenum.cpp | 34 +++++++++++++--------- .../directshow/helpers/directshowmediatypeenum.h | 34 +++++++++++++--------- src/plugins/directshow/helpers/directshowobject.h | 34 +++++++++++++--------- src/plugins/directshow/helpers/directshowpin.cpp | 34 +++++++++++++--------- src/plugins/directshow/helpers/directshowpin.h | 34 +++++++++++++--------- 7 files changed, 140 insertions(+), 98 deletions(-) (limited to 'src') diff --git a/src/plugins/directshow/helpers/directshowbasefilter.cpp b/src/plugins/directshow/helpers/directshowbasefilter.cpp index 3ca7e205e..342f0c271 100644 --- a/src/plugins/directshow/helpers/directshowbasefilter.cpp +++ b/src/plugins/directshow/helpers/directshowbasefilter.cpp @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** 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 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** 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. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** 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$ ** diff --git a/src/plugins/directshow/helpers/directshowbasefilter.h b/src/plugins/directshow/helpers/directshowbasefilter.h index 19c54233c..9a2f44567 100644 --- a/src/plugins/directshow/helpers/directshowbasefilter.h +++ b/src/plugins/directshow/helpers/directshowbasefilter.h @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** 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 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** 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. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** 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$ ** diff --git a/src/plugins/directshow/helpers/directshowmediatypeenum.cpp b/src/plugins/directshow/helpers/directshowmediatypeenum.cpp index a42dfdca3..8fbdf7dea 100644 --- a/src/plugins/directshow/helpers/directshowmediatypeenum.cpp +++ b/src/plugins/directshow/helpers/directshowmediatypeenum.cpp @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** 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 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** 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. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** 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$ ** diff --git a/src/plugins/directshow/helpers/directshowmediatypeenum.h b/src/plugins/directshow/helpers/directshowmediatypeenum.h index c022677cc..9b058fc5b 100644 --- a/src/plugins/directshow/helpers/directshowmediatypeenum.h +++ b/src/plugins/directshow/helpers/directshowmediatypeenum.h @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** 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 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** 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. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** 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$ ** diff --git a/src/plugins/directshow/helpers/directshowobject.h b/src/plugins/directshow/helpers/directshowobject.h index 4a8938635..cfac16f61 100644 --- a/src/plugins/directshow/helpers/directshowobject.h +++ b/src/plugins/directshow/helpers/directshowobject.h @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** 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 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** 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. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** 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$ ** diff --git a/src/plugins/directshow/helpers/directshowpin.cpp b/src/plugins/directshow/helpers/directshowpin.cpp index 44c6b1520..b49c3f8a4 100644 --- a/src/plugins/directshow/helpers/directshowpin.cpp +++ b/src/plugins/directshow/helpers/directshowpin.cpp @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** 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 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** 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. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** 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$ ** diff --git a/src/plugins/directshow/helpers/directshowpin.h b/src/plugins/directshow/helpers/directshowpin.h index d518726b4..97e808384 100644 --- a/src/plugins/directshow/helpers/directshowpin.h +++ b/src/plugins/directshow/helpers/directshowpin.h @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** 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 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** 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. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** 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$ ** -- cgit v1.2.3 From 8e4d966f4e5546787257de046d2c3af8a19214b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Thu, 20 Oct 2016 18:32:48 +0200 Subject: DirectShow: Enable audio and video probes in DirectShow This change enables the video and audio probe functionality, so it can be used with the media player. [ChangeLog][DirectShow] Added support for audio and video probes in the mediaplayer. Task-number: QTBUG-56415 Change-Id: If6f36a693b1d22372eab130df07d435c9df5a796 Reviewed-by: Yoann Lopes --- .../directshow/player/directshowplayerservice.cpp | 340 ++++++++++++++++++++- .../directshow/player/directshowplayerservice.h | 56 +++- src/plugins/directshow/player/player.pri | 2 + 3 files changed, 381 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/plugins/directshow/player/directshowplayerservice.cpp b/src/plugins/directshow/player/directshowplayerservice.cpp index 4a75c9551..de427f781 100644 --- a/src/plugins/directshow/player/directshowplayerservice.cpp +++ b/src/plugins/directshow/player/directshowplayerservice.cpp @@ -53,7 +53,11 @@ #include "directshowiosource.h" #include "directshowplayercontrol.h" #include "directshowvideorenderercontrol.h" - +#include "directshowutils.h" +#include "directshowglobal.h" +#include "directshowaudioprobecontrol.h" +#include "directshowvideoprobecontrol.h" +#include "directshowsamplegrabber.h" #if QT_CONFIG(evr) #include "directshowevrvideowindowcontrol.h" @@ -68,6 +72,11 @@ #include #include #include +#include + +#include +#include +#include #if QT_CONFIG(wmsdk) # include @@ -117,6 +126,10 @@ DirectShowPlayerService::DirectShowPlayerService(QObject *parent) , m_videoRendererControl(0) , m_videoWindowControl(0) , m_audioEndpointControl(0) + , m_audioProbeControl(nullptr) + , m_videoProbeControl(nullptr) + , m_audioSampleGrabber(nullptr) + , m_videoSampleGrabber(nullptr) , m_taskThread(0) , m_loop(qt_directShowEventLoop()) , m_pendingTasks(0) @@ -176,6 +189,8 @@ DirectShowPlayerService::~DirectShowPlayerService() delete m_metaDataControl; delete m_videoRendererControl; delete m_videoWindowControl; + delete m_audioProbeControl; + delete m_videoProbeControl; ::CloseHandle(m_taskHandle); } @@ -219,6 +234,18 @@ QMediaControl *DirectShowPlayerService::requestControl(const char *name) return m_videoWindowControl; } + } else if (qstrcmp(name, QMediaAudioProbeControl_iid) == 0) { + if (!m_audioProbeControl) + m_audioProbeControl = new DirectShowAudioProbeControl(); + m_audioProbeControl->ref(); + updateAudioProbe(); + return m_audioProbeControl; + } else if (qstrcmp(name, QMediaVideoProbeControl_iid) == 0) { + if (!m_videoProbeControl) + m_videoProbeControl = new DirectShowVideoProbeControl(); + m_videoProbeControl->ref(); + updateVideoProbe(); + return m_videoProbeControl; } return 0; } @@ -240,6 +267,20 @@ void DirectShowPlayerService::releaseControl(QMediaControl *control) delete m_videoWindowControl; m_videoWindowControl = 0; + } else if (control == m_audioProbeControl) { + if (!m_audioProbeControl->deref()) { + DirectShowAudioProbeControl *old = m_audioProbeControl; + m_audioProbeControl = nullptr; + updateAudioProbe(); + delete old; + } + } else if (control == m_videoProbeControl) { + if (!m_videoProbeControl->deref()) { + DirectShowVideoProbeControl *old = m_videoProbeControl; + m_videoProbeControl = nullptr; + updateVideoProbe(); + delete old; + } } } @@ -349,6 +390,10 @@ void DirectShowPlayerService::doSetUrlSource(QMutexLocker *locker) m_pendingTasks |= SetAudioOutput; if (m_videoOutput) m_pendingTasks |= SetVideoOutput; + if (m_audioProbeControl) + m_pendingTasks |= SetAudioProbe; + if (m_videoProbeControl) + m_pendingTasks |= SetVideoProbe; if (m_rate != 1.0) m_pendingTasks |= SetRate; @@ -434,6 +479,18 @@ void DirectShowPlayerService::doRender(QMutexLocker *locker) m_executedTasks |= SetVideoOutput; } + if (m_pendingTasks & SetAudioProbe) { + doSetAudioProbe(locker); + m_pendingTasks ^= SetAudioProbe; + m_executedTasks |= SetAudioProbe; + } + + if (m_pendingTasks & SetVideoProbe) { + doSetVideoProbe(locker); + m_pendingTasks ^= SetVideoProbe; + m_executedTasks |= SetVideoProbe; + } + IFilterGraph2 *graph = m_graph; graph->AddRef(); @@ -601,6 +658,9 @@ void DirectShowPlayerService::doReleaseGraph(QMutexLocker *locker) control->Release(); } + doReleaseAudioProbe(locker); + doReleaseVideoProbe(locker); + if (m_source) { m_source->Release(); m_source = 0; @@ -614,6 +674,139 @@ void DirectShowPlayerService::doReleaseGraph(QMutexLocker *locker) m_loop->wake(); } +void DirectShowPlayerService::doSetVideoProbe(QMutexLocker *locker) +{ + Q_UNUSED(locker); + + if (!m_graph) { + qCWarning(qtDirectShowPlugin, "Attempting to set a video probe without a valid graph!"); + return; + } + + // Create the sample grabber, if necessary. + if (!m_videoSampleGrabber) { + m_videoSampleGrabber = new DirectShowSampleGrabber; + connect(m_videoSampleGrabber, &DirectShowSampleGrabber::bufferAvailable, this, &DirectShowPlayerService::onVideoBufferAvailable); + } + + if (FAILED(m_graph->AddFilter(m_videoSampleGrabber->filter(), L"Video Sample Grabber"))) { + qCWarning(qtDirectShowPlugin, "Failed to add the video sample grabber into the graph!"); + return; + } + + // TODO: Make util function for getting this, so it's easy to keep it in sync. + static const GUID subtypes[] = { MEDIASUBTYPE_ARGB32, + MEDIASUBTYPE_RGB32, + MEDIASUBTYPE_RGB24, + MEDIASUBTYPE_RGB565, + MEDIASUBTYPE_RGB555, + MEDIASUBTYPE_AYUV, + MEDIASUBTYPE_I420, + MEDIASUBTYPE_IYUV, + MEDIASUBTYPE_YV12, + MEDIASUBTYPE_UYVY, + MEDIASUBTYPE_YUYV, + MEDIASUBTYPE_YUY2, + MEDIASUBTYPE_NV12, + MEDIASUBTYPE_MJPG, + MEDIASUBTYPE_IMC1, + MEDIASUBTYPE_IMC2, + MEDIASUBTYPE_IMC3, + MEDIASUBTYPE_IMC4 }; + + // Negotiate the subtype + DirectShowMediaType mediaType(AM_MEDIA_TYPE { MEDIATYPE_Video }); + const int items = (sizeof subtypes / sizeof(GUID)); + bool connected = false; + for (int i = 0; i != items; ++i) { + mediaType->subtype = subtypes[i]; + m_videoSampleGrabber->setMediaType(&mediaType); + if (SUCCEEDED(DirectShowUtils::connectFilters(m_graph, m_source, m_videoSampleGrabber->filter(), true))) + connected = true; + break; + } + + if (!connected) { + qCWarning(qtDirectShowPlugin, "Unable to connect the video probe!"); + return; + } + + m_videoSampleGrabber->start(DirectShowSampleGrabber::CallbackMethod::BufferCB); +} + +void DirectShowPlayerService::doSetAudioProbe(QMutexLocker *locker) +{ + Q_UNUSED(locker); + + if (!m_graph) { + qCWarning(qtDirectShowPlugin, "Attempting to set an audio probe without a valid graph!"); + return; + } + + // Create the sample grabber, if necessary. + if (!m_audioSampleGrabber) { + m_audioSampleGrabber = new DirectShowSampleGrabber; + connect(m_audioSampleGrabber, &DirectShowSampleGrabber::bufferAvailable, this, &DirectShowPlayerService::onAudioBufferAvailable); + } + + static const AM_MEDIA_TYPE mediaType { MEDIATYPE_Audio, MEDIASUBTYPE_PCM }; + m_audioSampleGrabber->setMediaType(&mediaType); + + if (FAILED(m_graph->AddFilter(m_audioSampleGrabber->filter(), L"Audio Sample Grabber"))) { + qCWarning(qtDirectShowPlugin, "Failed to add the audio sample grabber into the graph!"); + return; + } + + if (FAILED(DirectShowUtils::connectFilters(m_graph, m_source, m_audioSampleGrabber->filter(), true))) { + qCWarning(qtDirectShowPlugin, "Failed to connect the audio sample grabber"); + return; + } + + m_audioSampleGrabber->start(DirectShowSampleGrabber::CallbackMethod::BufferCB); +} + +void DirectShowPlayerService::doReleaseVideoProbe(QMutexLocker *locker) +{ + Q_UNUSED(locker); + + if (!m_graph) + return; + + if (!m_videoSampleGrabber) + return; + + m_videoSampleGrabber->stop(); + HRESULT hr = m_graph->RemoveFilter(m_videoSampleGrabber->filter()); + if (FAILED(hr)) { + qCWarning(qtDirectShowPlugin, "Failed to remove the video sample grabber!"); + return; + } + + m_videoSampleGrabber->deleteLater(); + m_videoSampleGrabber = nullptr; +} + +void DirectShowPlayerService::doReleaseAudioProbe(QMutexLocker *locker) +{ + Q_UNUSED(locker); + + if (!m_graph) + return; + + if (!m_audioSampleGrabber) + return; + + m_audioSampleGrabber->stop(); + HRESULT hr = m_graph->RemoveFilter(m_audioSampleGrabber->filter()); + if (FAILED(hr)) { + qCWarning(qtDirectShowPlugin, "Failed to remove the audio sample grabber!"); + return; + } + + m_audioSampleGrabber->deleteLater(); + m_audioSampleGrabber = nullptr; +} + int DirectShowPlayerService::findStreamTypes(IBaseFilter *source) const { QVarLengthArray filters; @@ -1121,6 +1314,40 @@ void DirectShowPlayerService::setVideoOutput(IBaseFilter *filter) } } +void DirectShowPlayerService::updateAudioProbe() +{ + QMutexLocker locker(&m_mutex); + + // Set/Activate the audio probe. + if (m_graph) { + // If we don't have a audio probe, then stop and release the audio sample grabber + if (!m_audioProbeControl && (m_executedTasks & SetAudioProbe)) { + m_pendingTasks |= ReleaseAudioProbe; + ::SetEvent(m_taskHandle); + m_loop->wait(&m_mutex); + } else if (m_audioProbeControl) { + m_pendingTasks |= SetAudioProbe; + } + } +} + +void DirectShowPlayerService::updateVideoProbe() +{ + QMutexLocker locker(&m_mutex); + + // Set/Activate the video probe. + if (m_graph) { + // If we don't have a video probe, then stop and release the video sample grabber + if (!m_videoProbeControl && (m_executedTasks & SetVideoProbe)) { + m_pendingTasks |= ReleaseVideoProbe; + ::SetEvent(m_taskHandle); + m_loop->wait(&m_mutex); + } else if (m_videoProbeControl){ + m_pendingTasks |= SetVideoProbe; + } + } +} + void DirectShowPlayerService::doReleaseVideoOutput(QMutexLocker *locker) { Q_UNUSED(locker) @@ -1217,6 +1444,97 @@ void DirectShowPlayerService::videoOutputChanged() setVideoOutput(m_videoRendererControl->filter()); } +void DirectShowPlayerService::onAudioBufferAvailable(double time, quint8 *buffer, long len) +{ + QMutexLocker locker(&m_mutex); + if (!m_audioProbeControl || !m_audioSampleGrabber) + return; + + DirectShowMediaType mt(AM_MEDIA_TYPE { GUID_NULL }); + const bool ok = m_audioSampleGrabber->getConnectedMediaType(&mt); + if (!ok) + return; + + if (mt->majortype != MEDIATYPE_Audio) + return; + + if (mt->subtype != MEDIASUBTYPE_PCM) + return; + + const bool isWfx = ((mt->formattype == FORMAT_WaveFormatEx) && (mt->cbFormat >= sizeof(WAVEFORMATEX))); + WAVEFORMATEX *wfx = isWfx ? reinterpret_cast(mt->pbFormat) : nullptr; + + if (!wfx) + return; + + if (wfx->wFormatTag != WAVE_FORMAT_PCM && wfx->wFormatTag != WAVE_FORMAT_EXTENSIBLE) + return; + + if ((wfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE) && (wfx->cbSize >= sizeof(WAVEFORMATEXTENSIBLE))) { + WAVEFORMATEXTENSIBLE *wfxe = reinterpret_cast(wfx); + if (wfxe->SubFormat != KSDATAFORMAT_SUBTYPE_PCM) + return; + } + + QAudioFormat format; + format.setSampleRate(wfx->nSamplesPerSec); + format.setChannelCount(wfx->nChannels); + format.setSampleSize(wfx->wBitsPerSample); + format.setCodec("audio/pcm"); + format.setByteOrder(QAudioFormat::LittleEndian); + if (format.sampleSize() == 8) + format.setSampleType(QAudioFormat::UnSignedInt); + else + format.setSampleType(QAudioFormat::SignedInt); + + const quint64 startTime = quint64(time * 1000.); + QAudioBuffer audioBuffer(QByteArray(reinterpret_cast(buffer), len), + format, + startTime); + + Q_EMIT m_audioProbeControl->audioBufferProbed(audioBuffer); +} + +void DirectShowPlayerService::onVideoBufferAvailable(double time, quint8 *buffer, long len) +{ + Q_UNUSED(time); + Q_UNUSED(buffer); + Q_UNUSED(len); + + QMutexLocker locker(&m_mutex); + if (!m_videoProbeControl || !m_videoSampleGrabber) + return; + + DirectShowMediaType mt(AM_MEDIA_TYPE { GUID_NULL }); + const bool ok = m_videoSampleGrabber->getConnectedMediaType(&mt); + if (!ok) + return; + + if (mt->majortype != MEDIATYPE_Video) + return; + + QVideoFrame::PixelFormat format = DirectShowMediaType::pixelFormatFromType(&mt); + if (format == QVideoFrame::Format_Invalid) { + qCWarning(qtDirectShowPlugin, "Invalid format, stopping video probes!"); + m_videoSampleGrabber->stop(); + return; + } + + const QVideoSurfaceFormat &videoFormat = DirectShowMediaType::videoFormatFromType(&mt); + if (!videoFormat.isValid()) + return; + + const QSize &size = videoFormat.frameSize(); + + const int bytesPerLine = DirectShowMediaType::bytesPerLine(videoFormat); + QByteArray data(reinterpret_cast(buffer), len); + QVideoFrame frame(new QMemoryVideoBuffer(data, bytesPerLine), + size, + format); + + Q_EMIT m_videoProbeControl->videoFrameProbed(frame); +} + void DirectShowPlayerService::graphEvent(QMutexLocker *locker) { Q_UNUSED(locker) @@ -1405,6 +1723,16 @@ void DirectShowPlayerService::run() m_executingTask = ReleaseVideoOutput; doReleaseVideoOutput(&locker); + } else if (m_pendingTasks & ReleaseAudioProbe) { + m_pendingTasks ^= ReleaseAudioProbe; + m_executingTask = ReleaseAudioProbe; + + doReleaseAudioProbe(&locker); + } else if (m_pendingTasks & ReleaseVideoProbe) { + m_pendingTasks ^= ReleaseVideoProbe; + m_executingTask = ReleaseVideoProbe; + + doReleaseVideoProbe(&locker); } else if (m_pendingTasks & SetUrlSource) { m_pendingTasks ^= SetUrlSource; m_executingTask = SetUrlSource; @@ -1415,6 +1743,16 @@ void DirectShowPlayerService::run() m_executingTask = SetStreamSource; doSetStreamSource(&locker); + } else if (m_pendingTasks & SetAudioProbe) { + m_pendingTasks ^= SetAudioProbe; + m_executingTask = SetAudioProbe; + + doSetAudioProbe(&locker); + } else if (m_pendingTasks & SetVideoProbe) { + m_pendingTasks ^= SetVideoProbe; + m_executingTask = SetVideoProbe; + + doSetVideoProbe(&locker); } else if (m_pendingTasks & Render) { m_pendingTasks ^= Render; m_executingTask = Render; diff --git a/src/plugins/directshow/player/directshowplayerservice.h b/src/plugins/directshow/player/directshowplayerservice.h index dc0226001..676d88fb5 100644 --- a/src/plugins/directshow/player/directshowplayerservice.h +++ b/src/plugins/directshow/player/directshowplayerservice.h @@ -61,6 +61,9 @@ class DirectShowAudioEndpointControl; class DirectShowMetaDataControl; class DirectShowPlayerControl; class DirectShowVideoRendererControl; +class DirectShowAudioProbeControl; +class DirectShowVideoProbeControl; +class DirectShowSampleGrabber; class QMediaContent; class QVideoWindowControl; @@ -103,10 +106,16 @@ protected: private Q_SLOTS: void videoOutputChanged(); + void onAudioBufferAvailable(double time, quint8 *buffer, long len); + void onVideoBufferAvailable(double time, quint8 *buffer, long len); + private: void releaseGraph(); void updateStatus(); + void updateAudioProbe(); + void updateVideoProbe(); + int findStreamTypes(IBaseFilter *source) const; int findStreamType(IPin *pin) const; @@ -127,29 +136,40 @@ private: void doReleaseAudioOutput(QMutexLocker *locker); void doReleaseVideoOutput(QMutexLocker *locker); void doReleaseGraph(QMutexLocker *locker); + void doSetVideoProbe(QMutexLocker *locker); + void doSetAudioProbe(QMutexLocker *locker); + void doReleaseVideoProbe(QMutexLocker *locker); + void doReleaseAudioProbe(QMutexLocker *locker); void graphEvent(QMutexLocker *locker); enum Task { - Shutdown = 0x0001, - SetUrlSource = 0x0002, - SetStreamSource = 0x0004, + Shutdown = 0x00001, + SetUrlSource = 0x00002, + SetStreamSource = 0x00004, SetSource = SetUrlSource | SetStreamSource, - SetAudioOutput = 0x0008, - SetVideoOutput = 0x0010, + SetAudioOutput = 0x00008, + SetVideoOutput = 0x00010, SetOutputs = SetAudioOutput | SetVideoOutput, - Render = 0x0020, - FinalizeLoad = 0x0040, - SetRate = 0x0080, - Seek = 0x0100, - Play = 0x0200, - Pause = 0x0400, - Stop = 0x0800, - ReleaseGraph = 0x1000, - ReleaseAudioOutput = 0x2000, - ReleaseVideoOutput = 0x4000, - ReleaseFilters = ReleaseGraph | ReleaseAudioOutput | ReleaseVideoOutput + SetAudioProbe = 0x00020, + SetVideoProbe = 0x00040, + SetProbes = SetAudioProbe | SetVideoProbe, + Render = 0x00080, + FinalizeLoad = 0x00100, + SetRate = 0x00200, + Seek = 0x00400, + Play = 0x00800, + Pause = 0x01000, + Stop = 0x02000, + ReleaseGraph = 0x04000, + ReleaseAudioOutput = 0x08000, + ReleaseVideoOutput = 0x10000, + ReleaseAudioProbe = 0x20000, + ReleaseVideoProbe = 0x40000, + ReleaseFilters = ReleaseGraph | ReleaseAudioOutput + | ReleaseVideoOutput | ReleaseAudioProbe + | ReleaseVideoProbe }; enum Event @@ -178,6 +198,10 @@ private: DirectShowVideoRendererControl *m_videoRendererControl; QVideoWindowControl *m_videoWindowControl; DirectShowAudioEndpointControl *m_audioEndpointControl; + DirectShowAudioProbeControl *m_audioProbeControl; + DirectShowVideoProbeControl *m_videoProbeControl; + DirectShowSampleGrabber *m_audioSampleGrabber; + DirectShowSampleGrabber *m_videoSampleGrabber; QThread *m_taskThread; DirectShowEventLoop *m_loop; diff --git a/src/plugins/directshow/player/player.pri b/src/plugins/directshow/player/player.pri index 59ac5a330..9111cc545 100644 --- a/src/plugins/directshow/player/player.pri +++ b/src/plugins/directshow/player/player.pri @@ -3,6 +3,8 @@ INCLUDEPATH += $$PWD QMAKE_USE += directshow LIBS += -lgdi32 +mingw: LIBS_PRIVATE += -lksuser + qtHaveModule(widgets): QT += widgets HEADERS += \ -- cgit v1.2.3 From c50fb7493753606cd436b08d33022f9b789dd2ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Thu, 17 Nov 2016 17:51:48 +0100 Subject: DirectShow: Merge the helpers and common folder Change-Id: Ie1c39c26ae6dec288daafb24b5aa0b6cc2bdd218 Reviewed-by: Yoann Lopes --- src/plugins/directshow/common/common.pri | 19 + .../directshow/common/directshowbasefilter.cpp | 277 ++++++++ .../directshow/common/directshowbasefilter.h | 101 +++ .../directshow/common/directshoweventloop.cpp | 152 +++++ .../directshow/common/directshoweventloop.h | 80 +++ src/plugins/directshow/common/directshowglobal.h | 160 +++++ .../directshow/common/directshowmediatype.cpp | 350 ++++++++++ .../directshow/common/directshowmediatype.h | 97 +++ .../directshow/common/directshowmediatypeenum.cpp | 117 ++++ .../directshow/common/directshowmediatypeenum.h | 80 +++ src/plugins/directshow/common/directshowobject.cpp | 86 +++ src/plugins/directshow/common/directshowobject.h | 82 +++ src/plugins/directshow/common/directshowpin.cpp | 740 +++++++++++++++++++++ src/plugins/directshow/common/directshowpin.h | 192 ++++++ .../directshow/common/directshowpinenum.cpp | 130 ++++ src/plugins/directshow/common/directshowpinenum.h | 81 +++ src/plugins/directshow/common/directshowutils.cpp | 313 +++++++++ src/plugins/directshow/common/directshowutils.h | 87 +++ .../directshow/common/directshowvideobuffer.cpp | 88 +++ .../directshow/common/directshowvideobuffer.h | 70 ++ src/plugins/directshow/directshow.pro | 1 - .../directshow/helpers/directshowbasefilter.cpp | 277 -------- .../directshow/helpers/directshowbasefilter.h | 101 --- .../directshow/helpers/directshoweventloop.cpp | 152 ----- .../directshow/helpers/directshoweventloop.h | 80 --- src/plugins/directshow/helpers/directshowglobal.h | 160 ----- .../directshow/helpers/directshowmediatype.cpp | 350 ---------- .../directshow/helpers/directshowmediatype.h | 97 --- .../directshow/helpers/directshowmediatypeenum.cpp | 117 ---- .../directshow/helpers/directshowmediatypeenum.h | 80 --- .../directshow/helpers/directshowobject.cpp | 86 --- src/plugins/directshow/helpers/directshowobject.h | 82 --- src/plugins/directshow/helpers/directshowpin.cpp | 740 --------------------- src/plugins/directshow/helpers/directshowpin.h | 192 ------ .../directshow/helpers/directshowpinenum.cpp | 130 ---- src/plugins/directshow/helpers/directshowpinenum.h | 81 --- src/plugins/directshow/helpers/directshowutils.cpp | 313 --------- src/plugins/directshow/helpers/directshowutils.h | 87 --- .../directshow/helpers/directshowvideobuffer.cpp | 88 --- .../directshow/helpers/directshowvideobuffer.h | 70 -- src/plugins/directshow/helpers/helpers.pri | 24 - 41 files changed, 3302 insertions(+), 3308 deletions(-) create mode 100644 src/plugins/directshow/common/directshowbasefilter.cpp create mode 100644 src/plugins/directshow/common/directshowbasefilter.h create mode 100644 src/plugins/directshow/common/directshoweventloop.cpp create mode 100644 src/plugins/directshow/common/directshoweventloop.h create mode 100644 src/plugins/directshow/common/directshowglobal.h create mode 100644 src/plugins/directshow/common/directshowmediatype.cpp create mode 100644 src/plugins/directshow/common/directshowmediatype.h create mode 100644 src/plugins/directshow/common/directshowmediatypeenum.cpp create mode 100644 src/plugins/directshow/common/directshowmediatypeenum.h create mode 100644 src/plugins/directshow/common/directshowobject.cpp create mode 100644 src/plugins/directshow/common/directshowobject.h create mode 100644 src/plugins/directshow/common/directshowpin.cpp create mode 100644 src/plugins/directshow/common/directshowpin.h create mode 100644 src/plugins/directshow/common/directshowpinenum.cpp create mode 100644 src/plugins/directshow/common/directshowpinenum.h create mode 100644 src/plugins/directshow/common/directshowutils.cpp create mode 100644 src/plugins/directshow/common/directshowutils.h create mode 100644 src/plugins/directshow/common/directshowvideobuffer.cpp create mode 100644 src/plugins/directshow/common/directshowvideobuffer.h delete mode 100644 src/plugins/directshow/helpers/directshowbasefilter.cpp delete mode 100644 src/plugins/directshow/helpers/directshowbasefilter.h delete mode 100644 src/plugins/directshow/helpers/directshoweventloop.cpp delete mode 100644 src/plugins/directshow/helpers/directshoweventloop.h delete mode 100644 src/plugins/directshow/helpers/directshowglobal.h delete mode 100644 src/plugins/directshow/helpers/directshowmediatype.cpp delete mode 100644 src/plugins/directshow/helpers/directshowmediatype.h delete mode 100644 src/plugins/directshow/helpers/directshowmediatypeenum.cpp delete mode 100644 src/plugins/directshow/helpers/directshowmediatypeenum.h delete mode 100644 src/plugins/directshow/helpers/directshowobject.cpp delete mode 100644 src/plugins/directshow/helpers/directshowobject.h delete mode 100644 src/plugins/directshow/helpers/directshowpin.cpp delete mode 100644 src/plugins/directshow/helpers/directshowpin.h delete mode 100644 src/plugins/directshow/helpers/directshowpinenum.cpp delete mode 100644 src/plugins/directshow/helpers/directshowpinenum.h delete mode 100644 src/plugins/directshow/helpers/directshowutils.cpp delete mode 100644 src/plugins/directshow/helpers/directshowutils.h delete mode 100644 src/plugins/directshow/helpers/directshowvideobuffer.cpp delete mode 100644 src/plugins/directshow/helpers/directshowvideobuffer.h delete mode 100644 src/plugins/directshow/helpers/helpers.pri (limited to 'src') diff --git a/src/plugins/directshow/common/common.pri b/src/plugins/directshow/common/common.pri index 9b7c1e3f4..06f8582ac 100644 --- a/src/plugins/directshow/common/common.pri +++ b/src/plugins/directshow/common/common.pri @@ -1,11 +1,30 @@ INCLUDEPATH += $$PWD HEADERS += \ + $$PWD/directshowbasefilter.h \ + $$PWD/directshoweventloop.h \ + $$PWD/directshowglobal.h \ + $$PWD/directshowmediatype.h \ + $$PWD/directshowmediatypeenum.h \ + $$PWD/directshowobject.h \ + $$PWD/directshowpin.h \ + $$PWD/directshowpinenum.h \ + $$PWD/directshowvideobuffer.h \ + $$PWD/directshowutils.h \ $$PWD/directshowvideoprobecontrol.h \ $$PWD/directshowaudioprobecontrol.h \ $$PWD/directshowsamplegrabber.h SOURCES += \ + $$PWD/directshowbasefilter.cpp \ + $$PWD/directshoweventloop.cpp \ + $$PWD/directshowmediatype.cpp \ + $$PWD/directshowmediatypeenum.cpp \ + $$PWD/directshowobject.cpp \ + $$PWD/directshowpin.cpp \ + $$PWD/directshowpinenum.cpp \ + $$PWD/directshowvideobuffer.cpp \ + $$PWD/directshowutils.cpp \ $$PWD/directshowvideoprobecontrol.cpp \ $$PWD/directshowaudioprobecontrol.cpp \ $$PWD/directshowsamplegrabber.cpp diff --git a/src/plugins/directshow/common/directshowbasefilter.cpp b/src/plugins/directshow/common/directshowbasefilter.cpp new file mode 100644 index 000000000..342f0c271 --- /dev/null +++ b/src/plugins/directshow/common/directshowbasefilter.cpp @@ -0,0 +1,277 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 "directshowbasefilter.h" + +#include "directshowpinenum.h" + +QT_BEGIN_NAMESPACE + +DirectShowBaseFilter::DirectShowBaseFilter() + : m_mutex(QMutex::Recursive) + , m_state(State_Stopped) + , m_graph(NULL) + , m_clock(NULL) + , m_sink(NULL) +{ + +} + +DirectShowBaseFilter::~DirectShowBaseFilter() +{ + if (m_clock) { + m_clock->Release(); + m_clock = NULL; + } +} + +HRESULT DirectShowBaseFilter::getInterface(REFIID riid, void **ppvObject) +{ + if (riid == IID_IPersist + || riid == IID_IMediaFilter + || riid == IID_IBaseFilter) { + return GetInterface(static_cast(this), ppvObject); + } else { + return DirectShowObject::getInterface(riid, ppvObject); + } +} + +HRESULT DirectShowBaseFilter::GetClassID(CLSID *pClassID) +{ + *pClassID = CLSID_NULL; + return S_OK; +} + +HRESULT DirectShowBaseFilter::NotifyEvent(long eventCode, LONG_PTR eventParam1, LONG_PTR eventParam2) +{ + IMediaEventSink *sink = m_sink; + if (sink) { + if (eventCode == EC_COMPLETE) + eventParam2 = (LONG_PTR)(IBaseFilter*)this; + + return sink->Notify(eventCode, eventParam1, eventParam2); + } else { + return E_NOTIMPL; + } +} + +HRESULT DirectShowBaseFilter::Run(REFERENCE_TIME tStart) +{ + Q_UNUSED(tStart) + QMutexLocker locker(&m_mutex); + + m_startTime = tStart; + + if (m_state == State_Stopped){ + HRESULT hr = Pause(); + if (FAILED(hr)) + return hr; + } + + m_state = State_Running; + + return S_OK; +} + +HRESULT DirectShowBaseFilter::Pause() +{ + QMutexLocker locker(&m_mutex); + + if (m_state == State_Stopped) { + const QList pinList = pins(); + for (DirectShowPin *pin : pinList) { + if (pin->isConnected()) { + HRESULT hr = pin->setActive(true); + if (FAILED(hr)) + return hr; + } + } + } + + m_state = State_Paused; + + return S_OK; +} + +HRESULT DirectShowBaseFilter::Stop() +{ + QMutexLocker locker(&m_mutex); + + HRESULT hr = S_OK; + + if (m_state != State_Stopped) { + const QList pinList = pins(); + for (DirectShowPin *pin : pinList) { + if (pin->isConnected()) { + HRESULT hrTmp = pin->setActive(false); + if (FAILED(hrTmp) && SUCCEEDED(hr)) + hr = hrTmp; + } + } + } + + m_state = State_Stopped; + + return hr; +} + +HRESULT DirectShowBaseFilter::GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *pState) +{ + Q_UNUSED(dwMilliSecsTimeout); + + if (!pState) { + return E_POINTER; + } else { + QMutexLocker locker(&m_mutex); + + *pState = m_state; + + return S_OK; + } +} + +HRESULT DirectShowBaseFilter::SetSyncSource(IReferenceClock *pClock) +{ + QMutexLocker locker(&m_mutex); + + if (m_clock) + m_clock->Release(); + + m_clock = pClock; + + if (m_clock) + m_clock->AddRef(); + + return S_OK; +} + +HRESULT DirectShowBaseFilter::GetSyncSource(IReferenceClock **ppClock) +{ + if (!ppClock) { + return E_POINTER; + } else { + if (!m_clock) { + *ppClock = 0; + + return S_FALSE; + } else { + m_clock->AddRef(); + + *ppClock = m_clock; + + return S_OK; + } + } +} + +HRESULT DirectShowBaseFilter::EnumPins(IEnumPins **ppEnum) +{ + if (!ppEnum) { + return E_POINTER; + } else { + *ppEnum = new DirectShowPinEnum(this); + return S_OK; + } +} + +HRESULT DirectShowBaseFilter::FindPin(LPCWSTR Id, IPin **ppPin) +{ + if (!ppPin || !Id) { + return E_POINTER; + } else { + QMutexLocker locker(&m_mutex); + const QList pinList = pins(); + for (DirectShowPin *pin : pinList) { + if (QString::fromWCharArray(Id) == pin->name()) { + pin->AddRef(); + *ppPin = pin; + return S_OK; + } + } + + *ppPin = 0; + return VFW_E_NOT_FOUND; + } +} + +HRESULT DirectShowBaseFilter::JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName) +{ + QMutexLocker locker(&m_mutex); + + m_filterName = QString::fromWCharArray(pName); + m_graph = pGraph; + m_sink = NULL; + + if (m_graph) { + if (SUCCEEDED(m_graph->QueryInterface(IID_PPV_ARGS(&m_sink)))) + m_sink->Release(); // we don't keep a reference on it + } + + return S_OK; +} + +HRESULT DirectShowBaseFilter::QueryFilterInfo(FILTER_INFO *pInfo) +{ + if (!pInfo) { + return E_POINTER; + } else { + QString name = m_filterName; + + if (name.length() >= MAX_FILTER_NAME) + name.truncate(MAX_FILTER_NAME - 1); + + int length = name.toWCharArray(pInfo->achName); + pInfo->achName[length] = '\0'; + + if (m_graph) + m_graph->AddRef(); + + pInfo->pGraph = m_graph; + + return S_OK; + } +} + +HRESULT DirectShowBaseFilter::QueryVendorInfo(LPWSTR *pVendorInfo) +{ + Q_UNUSED(pVendorInfo); + return E_NOTIMPL; +} + +QT_END_NAMESPACE diff --git a/src/plugins/directshow/common/directshowbasefilter.h b/src/plugins/directshow/common/directshowbasefilter.h new file mode 100644 index 000000000..9a2f44567 --- /dev/null +++ b/src/plugins/directshow/common/directshowbasefilter.h @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 DIRECTSHOWBASEFILTER_H +#define DIRECTSHOWBASEFILTER_H + +#include "directshowpin.h" + +QT_BEGIN_NAMESPACE + +class DirectShowBaseFilter : public DirectShowObject + , public IBaseFilter +{ + DIRECTSHOW_OBJECT + +public: + DirectShowBaseFilter(); + virtual ~DirectShowBaseFilter(); + + FILTER_STATE state() const { return m_state; } + HRESULT NotifyEvent(long eventCode, LONG_PTR eventParam1, LONG_PTR eventParam2); + + virtual QList pins() = 0; + + // DirectShowObject + HRESULT getInterface(const IID &riid, void **ppvObject); + + // IPersist + STDMETHODIMP GetClassID(CLSID *pClassID); + + // IMediaFilter + STDMETHODIMP Run(REFERENCE_TIME tStart); + STDMETHODIMP Pause(); + STDMETHODIMP Stop(); + + STDMETHODIMP GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *pState); + + STDMETHODIMP SetSyncSource(IReferenceClock *pClock); + STDMETHODIMP GetSyncSource(IReferenceClock **ppClock); + + // IBaseFilter + STDMETHODIMP EnumPins(IEnumPins **ppEnum); + STDMETHODIMP FindPin(LPCWSTR Id, IPin **ppPin); + + STDMETHODIMP JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName); + + STDMETHODIMP QueryFilterInfo(FILTER_INFO *pInfo); + STDMETHODIMP QueryVendorInfo(LPWSTR *pVendorInfo); + +protected: + QMutex m_mutex; + FILTER_STATE m_state; + IFilterGraph *m_graph; + IReferenceClock *m_clock; + IMediaEventSink *m_sink; + QString m_filterName; + REFERENCE_TIME m_startTime; + +private: + Q_DISABLE_COPY(DirectShowBaseFilter) +}; + +QT_END_NAMESPACE + +#endif // DIRECTSHOWBASEFILTER_H diff --git a/src/plugins/directshow/common/directshoweventloop.cpp b/src/plugins/directshow/common/directshoweventloop.cpp new file mode 100644 index 000000000..ef85c0429 --- /dev/null +++ b/src/plugins/directshow/common/directshoweventloop.cpp @@ -0,0 +1,152 @@ +/**************************************************************************** +** +** 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 + +#include +#include + +QT_BEGIN_NAMESPACE + +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(); + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/directshow/common/directshoweventloop.h b/src/plugins/directshow/common/directshoweventloop.h new file mode 100644 index 000000000..609e53134 --- /dev/null +++ b/src/plugins/directshow/common/directshoweventloop.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** 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 +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +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; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/directshow/common/directshowglobal.h b/src/plugins/directshow/common/directshowglobal.h new file mode 100644 index 000000000..5f391710e --- /dev/null +++ b/src/plugins/directshow/common/directshowglobal.h @@ -0,0 +1,160 @@ +/**************************************************************************** +** +** 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 + +#include +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(qtDirectShowPlugin) + +QT_END_NAMESPACE + +template T *com_cast(IUnknown *unknown, const IID &iid) +{ + T *iface = 0; + return unknown && unknown->QueryInterface(iid, reinterpret_cast(&iface)) == S_OK + ? iface + : 0; +} + +template 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 T *com_new(const IID &clsid, const IID &iid) +{ + T *object = 0; + return CoCreateInstance( + clsid, + NULL, + CLSCTX_INPROC_SERVER, + iid, + reinterpret_cast(&object)) == S_OK + ? object + : 0; +} + +DEFINE_GUID(MEDIASUBTYPE_I420, + 0x30323449,0x0000,0x0010,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71); + +#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/common/directshowmediatype.cpp b/src/plugins/directshow/common/directshowmediatype.cpp new file mode 100644 index 000000000..65882806c --- /dev/null +++ b/src/plugins/directshow/common/directshowmediatype.cpp @@ -0,0 +1,350 @@ +/**************************************************************************** +** +** 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" +#include "directshowglobal.h" + +namespace +{ + struct TypeLookup + { + QVideoFrame::PixelFormat pixelFormat; + GUID mediaType; + }; + + static const TypeLookup qt_typeLookup[] = + { + { QVideoFrame::Format_ARGB32, MEDIASUBTYPE_ARGB32 }, + { QVideoFrame::Format_RGB32, MEDIASUBTYPE_RGB32 }, + { QVideoFrame::Format_RGB24, MEDIASUBTYPE_RGB24 }, + { QVideoFrame::Format_RGB565, MEDIASUBTYPE_RGB565 }, + { QVideoFrame::Format_RGB555, MEDIASUBTYPE_RGB555 }, + { QVideoFrame::Format_AYUV444, MEDIASUBTYPE_AYUV }, + { QVideoFrame::Format_YUYV, MEDIASUBTYPE_YUY2 }, + { QVideoFrame::Format_UYVY, MEDIASUBTYPE_UYVY }, + { QVideoFrame::Format_IMC1, MEDIASUBTYPE_IMC1 }, + { QVideoFrame::Format_IMC2, MEDIASUBTYPE_IMC2 }, + { QVideoFrame::Format_IMC3, MEDIASUBTYPE_IMC3 }, + { QVideoFrame::Format_IMC4, MEDIASUBTYPE_IMC4 }, + { QVideoFrame::Format_YV12, MEDIASUBTYPE_YV12 }, + { QVideoFrame::Format_NV12, MEDIASUBTYPE_NV12 }, + { QVideoFrame::Format_YUV420P, MEDIASUBTYPE_IYUV }, + { QVideoFrame::Format_YUV420P, MEDIASUBTYPE_I420 }, + { QVideoFrame::Format_Jpeg, MEDIASUBTYPE_MJPG } + }; +} + +bool DirectShowMediaType::isPartiallySpecified(const AM_MEDIA_TYPE *mediaType) +{ + return mediaType->majortype == GUID_NULL || mediaType->formattype == GUID_NULL; +} + +DirectShowMediaType::DirectShowMediaType() + : mediaType({ GUID_NULL, GUID_NULL, TRUE, FALSE, 1, GUID_NULL, nullptr, 0, nullptr}) +{ +} + +DirectShowMediaType::DirectShowMediaType(const AM_MEDIA_TYPE &type) + : DirectShowMediaType() +{ + copy(&mediaType, &type); +} + +DirectShowMediaType::DirectShowMediaType(AM_MEDIA_TYPE &&type) + : DirectShowMediaType() +{ + move(&mediaType, type); +} + +DirectShowMediaType::DirectShowMediaType(const DirectShowMediaType &other) + : DirectShowMediaType() +{ + copy(&mediaType, &other.mediaType); +} + +DirectShowMediaType::DirectShowMediaType(DirectShowMediaType &&other) + : DirectShowMediaType() +{ + move(&mediaType, other.mediaType); +} + +DirectShowMediaType &DirectShowMediaType::operator=(const DirectShowMediaType &other) +{ + copy(&mediaType, &other.mediaType); + return *this; +} + +DirectShowMediaType &DirectShowMediaType::operator=(DirectShowMediaType &&other) +{ + move(&mediaType, other.mediaType); + return *this; +} + +void DirectShowMediaType::init(AM_MEDIA_TYPE *type) +{ + Q_ASSERT(type); + SecureZeroMemory(reinterpret_cast(type), sizeof(AM_MEDIA_TYPE)); + type->lSampleSize = 1; + type->bFixedSizeSamples = TRUE; +} + +void DirectShowMediaType::copy(AM_MEDIA_TYPE *target, const AM_MEDIA_TYPE *source) +{ + if (!(target && source)) + return; + + if (target == source) + return; + + clear(*target); + + copyToUninitialized(target, source); +} + +void DirectShowMediaType::copyToUninitialized(AM_MEDIA_TYPE *target, const AM_MEDIA_TYPE *source) +{ + *target = *source; + + if (source->cbFormat > 0) { + target->pbFormat = reinterpret_cast(CoTaskMemAlloc(source->cbFormat)); + memcpy(target->pbFormat, source->pbFormat, source->cbFormat); + } + if (target->pUnk) + target->pUnk->AddRef(); +} + +void DirectShowMediaType::move(AM_MEDIA_TYPE *target, AM_MEDIA_TYPE **source) +{ + if (!target || !source || !(*source)) + return; + + if (target == *source) + return; + + clear(*target); + *target = *(*source); + SecureZeroMemory(reinterpret_cast(*source), sizeof(AM_MEDIA_TYPE)); + *source = nullptr; +} + +void DirectShowMediaType::move(AM_MEDIA_TYPE *target, AM_MEDIA_TYPE &source) +{ + AM_MEDIA_TYPE *srcPtr = &source; + move(target, &srcPtr); +} + +/** + * @brief DirectShowMediaType::deleteType - Used for AM_MEDIA_TYPE structures that have + * been allocated by CoTaskMemAlloc or CreateMediaType. + * @param type + */ +void DirectShowMediaType::deleteType(AM_MEDIA_TYPE *type) +{ + if (!type) + return; + + clear(*type); + CoTaskMemFree(type); +} + +bool DirectShowMediaType::isCompatible(const AM_MEDIA_TYPE *a, const AM_MEDIA_TYPE *b) +{ + if (b->majortype != GUID_NULL && a->majortype != b->majortype) + return false; + + if (b->subtype != GUID_NULL && a->subtype != b->subtype) + return false; + + if (b->formattype != GUID_NULL) { + if (a->formattype != b->formattype) + return false; + if (a->cbFormat != b->cbFormat) + return false; + if (a->cbFormat != 0 && memcmp(a->pbFormat, b->pbFormat, a->cbFormat) != 0) + return false; + } + + return true; +} + +/** + * @brief DirectShowMediaType::clear - Clears all member data, and releases allocated buffers. + * Use this to release automatic AM_MEDIA_TYPE structures. + * @param type + */ +void DirectShowMediaType::clear(AM_MEDIA_TYPE &type) +{ + if (type.cbFormat > 0) + CoTaskMemFree(type.pbFormat); + + if (type.pUnk) + type.pUnk->Release(); + + SecureZeroMemory(&type, sizeof(type)); +} + + +GUID DirectShowMediaType::convertPixelFormat(QVideoFrame::PixelFormat format) +{ + 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 MEDIASUBTYPE_None; +} + +QVideoSurfaceFormat DirectShowMediaType::videoFormatFromType(const AM_MEDIA_TYPE *type) +{ + if (!type) + return QVideoSurfaceFormat(); + + 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(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(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(); +} + +QVideoFrame::PixelFormat DirectShowMediaType::pixelFormatFromType(const AM_MEDIA_TYPE *type) +{ + if (!type) + return QVideoFrame::Format_Invalid; + + const int count = sizeof(qt_typeLookup) / sizeof(TypeLookup); + + for (int i = 0; i < count; ++i) { + if (IsEqualGUID(qt_typeLookup[i].mediaType, type->subtype)) { + return qt_typeLookup[i].pixelFormat; + } + } + + return QVideoFrame::Format_Invalid; +} + +#define PAD_TO_DWORD(x) (((x) + 3) & ~3) +int DirectShowMediaType::bytesPerLine(const QVideoSurfaceFormat &format) +{ + switch (format.pixelFormat()) { + // 32 bpp packed formats. + case QVideoFrame::Format_ARGB32: + 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_YV12: + case QVideoFrame::Format_YUV420P: + case QVideoFrame::Format_IMC1: + case QVideoFrame::Format_IMC2: + case QVideoFrame::Format_IMC3: + case QVideoFrame::Format_IMC4: + case QVideoFrame::Format_NV12: + return 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_ARGB32: + case QVideoFrame::Format_RGB32: + case QVideoFrame::Format_RGB24: + 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/common/directshowmediatype.h b/src/plugins/directshow/common/directshowmediatype.h new file mode 100644 index 000000000..7f495f3b2 --- /dev/null +++ b/src/plugins/directshow/common/directshowmediatype.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** 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 + +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +class DirectShowMediaType +{ +public: + DirectShowMediaType(); + DirectShowMediaType(const DirectShowMediaType &other); + DirectShowMediaType(DirectShowMediaType &&other); + explicit DirectShowMediaType(const AM_MEDIA_TYPE &type); + explicit DirectShowMediaType(AM_MEDIA_TYPE &&type); + ~DirectShowMediaType() { clear(mediaType); } + + DirectShowMediaType &operator =(const DirectShowMediaType &other); + DirectShowMediaType &operator =(DirectShowMediaType &&other); + + void clear() { clear(mediaType); } + + inline AM_MEDIA_TYPE *operator &() Q_DECL_NOTHROW { return &mediaType; } + inline AM_MEDIA_TYPE *operator ->() Q_DECL_NOTHROW { return &mediaType; } + + inline const AM_MEDIA_TYPE *operator &() const Q_DECL_NOTHROW { return &mediaType; } + inline const AM_MEDIA_TYPE *operator ->() const Q_DECL_NOTHROW { return &mediaType; } + + static void init(AM_MEDIA_TYPE *type); + static void copy(AM_MEDIA_TYPE *target, const AM_MEDIA_TYPE *source); + static void copyToUninitialized(AM_MEDIA_TYPE *target, const AM_MEDIA_TYPE *source); + static void move(AM_MEDIA_TYPE *target, AM_MEDIA_TYPE **source); + static void move(AM_MEDIA_TYPE *target, AM_MEDIA_TYPE &source); + static void clear(AM_MEDIA_TYPE &type); + static void deleteType(AM_MEDIA_TYPE *type); + static bool isPartiallySpecified(const AM_MEDIA_TYPE *mediaType); + static bool isCompatible(const AM_MEDIA_TYPE *a, const AM_MEDIA_TYPE *b); + static GUID convertPixelFormat(QVideoFrame::PixelFormat format); + + static QVideoSurfaceFormat videoFormatFromType(const AM_MEDIA_TYPE *type); + static QVideoFrame::PixelFormat pixelFormatFromType(const AM_MEDIA_TYPE *type); + static int bytesPerLine(const QVideoSurfaceFormat &format); + static QVideoSurfaceFormat::Direction scanLineDirection(QVideoFrame::PixelFormat pixelFormat, const BITMAPINFOHEADER &bmiHeader); + +private: + AM_MEDIA_TYPE mediaType; +}; + +Q_DECLARE_TYPEINFO(DirectShowMediaType, Q_MOVABLE_TYPE); + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/directshow/common/directshowmediatypeenum.cpp b/src/plugins/directshow/common/directshowmediatypeenum.cpp new file mode 100644 index 000000000..8fbdf7dea --- /dev/null +++ b/src/plugins/directshow/common/directshowmediatypeenum.cpp @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 "directshowmediatypeenum.h" + +#include "directshowpin.h" + +DirectShowMediaTypeEnum::DirectShowMediaTypeEnum(DirectShowPin *pin) + : m_pin(pin) + , m_mediaTypes(pin->supportedMediaTypes()) + , m_index(0) +{ + m_pin->AddRef(); +} + +DirectShowMediaTypeEnum::DirectShowMediaTypeEnum(const QList &types) + : m_pin(NULL) + , m_mediaTypes(types) + , m_index(0) +{ +} + +DirectShowMediaTypeEnum::~DirectShowMediaTypeEnum() +{ + if (m_pin) + m_pin->Release(); +} + +HRESULT DirectShowMediaTypeEnum::getInterface(REFIID riid, void **ppvObject) +{ + if (riid == IID_IEnumMediaTypes) { + return GetInterface(static_cast(this), ppvObject); + } else { + return DirectShowObject::getInterface(riid, ppvObject); + } +} + +HRESULT DirectShowMediaTypeEnum::Next(ULONG cMediaTypes, AM_MEDIA_TYPE **ppMediaTypes, ULONG *pcFetched) +{ + if (ppMediaTypes && (pcFetched || cMediaTypes == 1)) { + ULONG count = qBound(0, cMediaTypes, m_mediaTypes.count() - m_index); + + for (ULONG i = 0; i < count; ++i, ++m_index) { + ppMediaTypes[i] = reinterpret_cast(CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE))); + DirectShowMediaType::copyToUninitialized(ppMediaTypes[i], &m_mediaTypes.at(m_index)); + } + + if (pcFetched) + *pcFetched = count; + + return count == cMediaTypes ? S_OK : S_FALSE; + } else { + return E_POINTER; + } +} + +HRESULT DirectShowMediaTypeEnum::Skip(ULONG cMediaTypes) +{ + m_index = qMin(int(m_index + cMediaTypes), m_mediaTypes.count()); + return m_index < m_mediaTypes.count() ? S_OK : S_FALSE; +} + +HRESULT DirectShowMediaTypeEnum::Reset() +{ + m_index = 0; + return S_OK; +} + +HRESULT DirectShowMediaTypeEnum::Clone(IEnumMediaTypes **ppEnum) +{ + if (ppEnum) { + if (m_pin) + *ppEnum = new DirectShowMediaTypeEnum(m_pin); + else + *ppEnum = new DirectShowMediaTypeEnum(m_mediaTypes); + return S_OK; + } else { + return E_POINTER; + } +} + diff --git a/src/plugins/directshow/common/directshowmediatypeenum.h b/src/plugins/directshow/common/directshowmediatypeenum.h new file mode 100644 index 000000000..9b058fc5b --- /dev/null +++ b/src/plugins/directshow/common/directshowmediatypeenum.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 DIRECTSHOWMEDIATYPEENUM_H +#define DIRECTSHOWMEDIATYPEENUM_H + +#include "directshowobject.h" +#include + +QT_BEGIN_NAMESPACE + +class DirectShowPin; +class DirectShowMediaType; + +class DirectShowMediaTypeEnum : public DirectShowObject + , public IEnumMediaTypes +{ + DIRECTSHOW_OBJECT + +public: + DirectShowMediaTypeEnum(DirectShowPin *pin); + DirectShowMediaTypeEnum(const QList &types); + ~DirectShowMediaTypeEnum(); + + // DirectShowObject + HRESULT getInterface(REFIID riid, void **ppvObject); + + // IEnumMediaTypes + STDMETHODIMP Next(ULONG cMediaTypes, AM_MEDIA_TYPE **ppMediaTypes, ULONG *pcFetched); + STDMETHODIMP Skip(ULONG cMediaTypes); + STDMETHODIMP Reset(); + STDMETHODIMP Clone(IEnumMediaTypes **ppEnum); + +private: + Q_DISABLE_COPY(DirectShowMediaTypeEnum) + + DirectShowPin *m_pin; + QList m_mediaTypes; + int m_index; +}; + +QT_END_NAMESPACE + +#endif // DIRECTSHOWMEDIATYPEENUM_H diff --git a/src/plugins/directshow/common/directshowobject.cpp b/src/plugins/directshow/common/directshowobject.cpp new file mode 100644 index 000000000..db1817a8d --- /dev/null +++ b/src/plugins/directshow/common/directshowobject.cpp @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** 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 "directshowobject.h" + +QT_BEGIN_NAMESPACE + +DirectShowObject::DirectShowObject() + : m_ref(1) +{ +} + +DirectShowObject::~DirectShowObject() +{ + Q_ASSERT(m_ref == 0); +} + +HRESULT DirectShowObject::getInterface(const IID &riid, void **ppvObject) +{ + Q_UNUSED(riid) + *ppvObject = NULL; + return E_NOINTERFACE; +} + +ULONG DirectShowObject::ref() +{ + return InterlockedIncrement(&m_ref); +} + +ULONG DirectShowObject::unref() +{ + ULONG ref = InterlockedDecrement(&m_ref); + if (ref == 0) + delete this; + + return ref; +} + +HRESULT GetInterface(IUnknown *pUnk, void **ppv) +{ + if (!ppv) + return E_POINTER; + + *ppv = pUnk; + pUnk->AddRef(); + + return S_OK; +} + +QT_END_NAMESPACE diff --git a/src/plugins/directshow/common/directshowobject.h b/src/plugins/directshow/common/directshowobject.h new file mode 100644 index 000000000..cfac16f61 --- /dev/null +++ b/src/plugins/directshow/common/directshowobject.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 DIRECTSHOWOBJECT_H +#define DIRECTSHOWOBJECT_H + +#include "directshowglobal.h" + +QT_BEGIN_NAMESPACE + +class DirectShowObject +{ +public: + DirectShowObject(); + virtual ~DirectShowObject(); + + virtual HRESULT getInterface(REFIID riid, void **ppvObject); + ULONG ref(); + ULONG unref(); + +private: + Q_DISABLE_COPY(DirectShowObject) + + volatile LONG m_ref; +}; + +HRESULT GetInterface(IUnknown *pUnk, void **ppv); + +#define DIRECTSHOW_OBJECT \ +public: \ + STDMETHODIMP QueryInterface(REFIID riid, void **ppv) { \ + if (riid == IID_IUnknown) \ + return GetInterface(reinterpret_cast(this), ppv); \ + else \ + return getInterface(riid, ppv); \ + }; \ + STDMETHODIMP_(ULONG) AddRef() { \ + return ref(); \ + }; \ + STDMETHODIMP_(ULONG) Release() { \ + return unref(); \ + }; + +QT_END_NAMESPACE + +#endif // DIRECTSHOWOBJECT_H diff --git a/src/plugins/directshow/common/directshowpin.cpp b/src/plugins/directshow/common/directshowpin.cpp new file mode 100644 index 000000000..b49c3f8a4 --- /dev/null +++ b/src/plugins/directshow/common/directshowpin.cpp @@ -0,0 +1,740 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 "directshowpin.h" + +#include "directshowmediatype.h" +#include "directshowbasefilter.h" +#include "directshowmediatypeenum.h" + +#include + +QT_BEGIN_NAMESPACE + +DirectShowPin::DirectShowPin(DirectShowBaseFilter *filter, const QString &name, PIN_DIRECTION direction) + : m_mutex(QMutex::Recursive) + , m_filter(filter) + , m_name(name) + , m_direction(direction) + , m_peerPin(NULL) +{ +} + +DirectShowPin::~DirectShowPin() +{ + +} + +HRESULT DirectShowPin::getInterface(const IID &riid, void **ppvObject) +{ + if (riid == IID_IPin) + return GetInterface(static_cast(this), ppvObject); + else + return DirectShowObject::getInterface(riid, ppvObject); +} + + + +HRESULT DirectShowPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt) +{ + if (!pReceivePin) + return E_POINTER; + + HRESULT hr = E_FAIL; + QMutexLocker locker(&m_mutex); + + if (m_peerPin) + return VFW_E_ALREADY_CONNECTED; + if (m_filter->state() != State_Stopped) + return VFW_E_NOT_STOPPED; + + PIN_DIRECTION pd; + pReceivePin->QueryDirection(&pd); + if (pd == m_direction) + return VFW_E_INVALID_DIRECTION; + + if (pmt != NULL && DirectShowMediaType::isPartiallySpecified(pmt)) { + // If the type is fully specified, use it + hr = tryConnect(pReceivePin, pmt); + } else { + IEnumMediaTypes *enumMediaTypes = NULL; + + // First, try the receiving pin's preferred types + if (SUCCEEDED(pReceivePin->EnumMediaTypes(&enumMediaTypes))) { + hr = tryMediaTypes(pReceivePin, pmt, enumMediaTypes); + enumMediaTypes->Release(); + } + // Then, try this pin's preferred types + if (FAILED(hr) && SUCCEEDED(EnumMediaTypes(&enumMediaTypes))) { + hr = tryMediaTypes(pReceivePin, pmt, enumMediaTypes); + enumMediaTypes->Release(); + } + } + + if (FAILED(hr)) { + return ((hr != E_FAIL) && (hr != E_INVALIDARG) && (hr != VFW_E_TYPE_NOT_ACCEPTED)) + ? hr : VFW_E_NO_ACCEPTABLE_TYPES; + } + + return S_OK; +} + +HRESULT DirectShowPin::tryMediaTypes(IPin *pin, const AM_MEDIA_TYPE *partialType, IEnumMediaTypes *enumMediaTypes) +{ + HRESULT hr = enumMediaTypes->Reset(); + if (FAILED(hr)) + return hr; + + AM_MEDIA_TYPE *mediaType = NULL; + ULONG mediaCount = 0; + HRESULT hrFailure = VFW_E_NO_ACCEPTABLE_TYPES; + + for (; enumMediaTypes->Next(1, &mediaType, &mediaCount) == S_OK;) { + + if (mediaType && (partialType == NULL || DirectShowMediaType::isCompatible(mediaType, partialType))) { + hr = tryConnect(pin, mediaType); + + if (FAILED(hr) && (hr != E_FAIL) + && (hr != E_INVALIDARG) + && (hr != VFW_E_TYPE_NOT_ACCEPTED)) { + hrFailure = hr; + } + } + + if (mediaType) + DirectShowMediaType::deleteType(mediaType); + + if (SUCCEEDED(hr)) + return S_OK; + } + + return hrFailure; +} + +HRESULT DirectShowPin::tryConnect(IPin *pin, const AM_MEDIA_TYPE *type) +{ + if (!isMediaTypeSupported(type)) + return VFW_E_TYPE_NOT_ACCEPTED; + + m_peerPin = pin; + m_peerPin->AddRef(); + + HRESULT hr; + if (!setMediaType(type)) { + hr = VFW_E_TYPE_NOT_ACCEPTED; + } else { + hr = pin->ReceiveConnection(this, type); + if (SUCCEEDED(hr)) { + hr = completeConnection(pin); + if (FAILED(hr)) + pin->Disconnect(); + } + } + + if (FAILED(hr)) { + connectionEnded(); + m_peerPin->Release(); + m_peerPin = NULL; + setMediaType(NULL); + return hr; + } + + return S_OK; +} + +HRESULT DirectShowPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt) +{ + if (!pConnector || !pmt) + return E_POINTER; + + QMutexLocker locker(&m_mutex); + + if (m_peerPin) + return VFW_E_ALREADY_CONNECTED; + if (m_filter->state() != State_Stopped) + return VFW_E_NOT_STOPPED; + + PIN_DIRECTION pd; + pConnector->QueryDirection(&pd); + if (pd == m_direction) + return VFW_E_INVALID_DIRECTION; + + if (!isMediaTypeSupported(pmt)) + return VFW_E_TYPE_NOT_ACCEPTED; + + m_peerPin = pConnector; + m_peerPin->AddRef(); + + HRESULT hr; + if (!setMediaType(pmt)) + hr = VFW_E_TYPE_NOT_ACCEPTED; + else + hr = completeConnection(pConnector); + + if (FAILED(hr)) { + connectionEnded(); + m_peerPin->Release(); + m_peerPin = NULL; + setMediaType(NULL); + return hr; + } + + return S_OK; +} + +HRESULT DirectShowPin::Disconnect() +{ + QMutexLocker locker(&m_mutex); + + if (m_filter->state() != State_Stopped) + return VFW_E_NOT_STOPPED; + + if (m_peerPin) { + HRESULT hr = connectionEnded(); + if (FAILED(hr)) + return hr; + + m_peerPin->Release(); + m_peerPin = NULL; + + setMediaType(NULL); + + return S_OK; + } + + return S_FALSE; +} + +HRESULT DirectShowPin::ConnectedTo(IPin **ppPin) +{ + if (!ppPin) { + return E_POINTER; + } else { + QMutexLocker locker(&m_mutex); + + if (!m_peerPin) { + *ppPin = 0; + return VFW_E_NOT_CONNECTED; + } else { + m_peerPin->AddRef(); + *ppPin = m_peerPin; + return S_OK; + } + } +} + +HRESULT DirectShowPin::ConnectionMediaType(AM_MEDIA_TYPE *pmt) +{ + if (!pmt) { + return E_POINTER; + } else { + QMutexLocker locker(&m_mutex); + + if (!m_peerPin) { + DirectShowMediaType::init(pmt); + return VFW_E_NOT_CONNECTED; + } else { + DirectShowMediaType::copy(pmt, &m_mediaType); + return S_OK; + } + } +} + +HRESULT DirectShowPin::QueryPinInfo(PIN_INFO *pInfo) +{ + if (!pInfo) { + return E_POINTER; + } else { + pInfo->pFilter = m_filter; + if (m_filter) { + m_filter->AddRef(); + } + pInfo->dir = m_direction; + + QString name = m_name; + if (name.length() >= MAX_PIN_NAME) + name.truncate(MAX_PIN_NAME - 1); + int length = name.toWCharArray(pInfo->achName); + pInfo->achName[length] = '\0'; + + return S_OK; + } +} + +HRESULT DirectShowPin::QueryId(LPWSTR *Id) +{ + if (!Id) { + return E_POINTER; + } else { + const int bytes = (m_name.length() + 1) * 2; + *Id = static_cast(::CoTaskMemAlloc(bytes)); + ::memcpy(*Id, m_name.utf16(), bytes); + return S_OK; + } +} + +HRESULT DirectShowPin::QueryAccept(const AM_MEDIA_TYPE *pmt) +{ + if (!pmt) + return E_POINTER; + + if (!isMediaTypeSupported(pmt)) + return S_FALSE; + + return S_OK; +} + +HRESULT DirectShowPin::EnumMediaTypes(IEnumMediaTypes **ppEnum) +{ + if (!ppEnum) { + return E_POINTER; + } else { + *ppEnum = new DirectShowMediaTypeEnum(this); + return S_OK; + } +} + +HRESULT DirectShowPin::QueryInternalConnections(IPin **apPin, ULONG *nPin) +{ + Q_UNUSED(apPin); + Q_UNUSED(nPin); + return E_NOTIMPL; +} + +HRESULT DirectShowPin::EndOfStream() +{ + return S_OK; +} + +HRESULT DirectShowPin::BeginFlush() +{ + return E_UNEXPECTED; +} + +HRESULT DirectShowPin::EndFlush() +{ + return E_UNEXPECTED; +} + +HRESULT DirectShowPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate) +{ + Q_UNUSED(tStart); + Q_UNUSED(tStop); + Q_UNUSED(dRate); + return S_OK; +} + +HRESULT DirectShowPin::QueryDirection(PIN_DIRECTION *pPinDir) +{ + if (!pPinDir) { + return E_POINTER; + } else { + *pPinDir = m_direction; + return S_OK; + } +} + +QList DirectShowPin::supportedMediaTypes() +{ + return QList(); +} + +bool DirectShowPin::setMediaType(const AM_MEDIA_TYPE *type) +{ + if (!type) + m_mediaType.clear(); + else + DirectShowMediaType::copy(&m_mediaType, type); + + return true; +} + +HRESULT DirectShowPin::completeConnection(IPin *pin) +{ + Q_UNUSED(pin) + return S_OK; +} + +HRESULT DirectShowPin::connectionEnded() +{ + return S_OK; +} + +HRESULT DirectShowPin::setActive(bool active) +{ + Q_UNUSED(active) + return S_OK; +} + + +/* DirectShowOutputPin */ + +DirectShowOutputPin::DirectShowOutputPin(DirectShowBaseFilter *filter, const QString &name) + : DirectShowPin(filter, name, PINDIR_OUTPUT) + , m_allocator(NULL) + , m_inputPin(NULL) +{ + +} + +DirectShowOutputPin::~DirectShowOutputPin() +{ +} + +HRESULT DirectShowOutputPin::completeConnection(IPin *pin) +{ + if (!pin) + return E_POINTER; + + Q_ASSERT(m_inputPin == NULL); + Q_ASSERT(m_allocator == NULL); + + HRESULT hr = pin->QueryInterface(IID_PPV_ARGS(&m_inputPin)); + if (FAILED(hr)) + return hr; + + ALLOCATOR_PROPERTIES prop; + ZeroMemory(&prop, sizeof(prop)); + m_inputPin->GetAllocatorRequirements(&prop); + if (prop.cBuffers <= 0) + prop.cBuffers = 1; + if (prop.cbBuffer <= 0) + prop.cbBuffer = 1; + if (prop.cbAlign <= 0) + prop.cbAlign = 1; + + // Use the connected input pin's allocator if it has one + hr = m_inputPin->GetAllocator(&m_allocator); + if (SUCCEEDED(hr)) { + ALLOCATOR_PROPERTIES actualProperties; + hr = m_allocator->SetProperties(&prop, &actualProperties); + + if (SUCCEEDED(hr)) { + hr = m_inputPin->NotifyAllocator(m_allocator, FALSE); + if (SUCCEEDED(hr)) + return S_OK; + } + + m_allocator->Release(); + m_allocator = NULL; + } + + // Otherwise, allocate its own allocator + m_allocator = com_new(CLSID_MemoryAllocator); + if (!m_allocator) { + hr = E_OUTOFMEMORY; + } else { + ALLOCATOR_PROPERTIES actualProperties; + hr = m_allocator->SetProperties(&prop, &actualProperties); + + if (SUCCEEDED(hr)) { + hr = m_inputPin->NotifyAllocator(m_allocator, FALSE); + if (SUCCEEDED(hr)) + return S_OK; + } + + m_allocator->Release(); + m_allocator = NULL; + } + + return hr; +} + +HRESULT DirectShowOutputPin::connectionEnded() +{ + if (m_allocator) { + HRESULT hr = m_allocator->Decommit(); + if (FAILED(hr)) + return hr; + + m_allocator->Release(); + m_allocator = NULL; + } + + if (m_inputPin) { + m_inputPin->Release(); + m_inputPin = NULL; + } + + return S_OK; +} + +HRESULT DirectShowOutputPin::setActive(bool active) +{ + if (!m_allocator) + return VFW_E_NO_ALLOCATOR; + + return active ? m_allocator->Commit() + : m_allocator->Decommit(); +} + +HRESULT DirectShowOutputPin::EndOfStream() +{ + return E_UNEXPECTED; +} + + +/* DirectShowInputPin */ + +DirectShowInputPin::DirectShowInputPin(DirectShowBaseFilter *filter, const QString &name) + : DirectShowPin(filter, name, PINDIR_INPUT) + , m_allocator(NULL) + , m_flushing(false) + , m_inErrorState(false) +{ + ZeroMemory(&m_sampleProperties, sizeof(m_sampleProperties)); +} + +DirectShowInputPin::~DirectShowInputPin() +{ + +} + +HRESULT DirectShowInputPin::getInterface(const IID &riid, void **ppvObject) +{ + if (riid == IID_IMemInputPin) + return GetInterface(static_cast(this), ppvObject); + else + return DirectShowPin::getInterface(riid, ppvObject); +} + +HRESULT DirectShowInputPin::connectionEnded() +{ + if (m_allocator) { + HRESULT hr = m_allocator->Decommit(); + if (FAILED(hr)) + return hr; + + m_allocator->Release(); + m_allocator = NULL; + } + + return S_OK; +} + +HRESULT DirectShowInputPin::setActive(bool active) +{ + if (!active) { + m_inErrorState = false; + + if (!m_allocator) + return VFW_E_NO_ALLOCATOR; + + m_flushing = false; + return m_allocator->Decommit(); + } + + return S_OK; +} + +HRESULT DirectShowInputPin::EndOfStream() +{ + if (m_filter->state() == State_Stopped) + return VFW_E_WRONG_STATE; + if (m_flushing) + return S_FALSE; + if (m_inErrorState) + return VFW_E_RUNTIME_ERROR; + + return S_OK; +} + +HRESULT DirectShowInputPin::BeginFlush() +{ + QMutexLocker locker(&m_mutex); + m_flushing = true; + return S_OK; +} + +HRESULT DirectShowInputPin::EndFlush() +{ + QMutexLocker locker(&m_mutex); + m_flushing = false; + m_inErrorState = false; + return S_OK; +} + +HRESULT DirectShowInputPin::GetAllocator(IMemAllocator **ppAllocator) +{ + if (!ppAllocator) + return E_POINTER; + + QMutexLocker locker(&m_mutex); + + if (!m_allocator) { + m_allocator = com_new(CLSID_MemoryAllocator);; + if (!m_allocator) + return E_OUTOFMEMORY; + } + + *ppAllocator = m_allocator; + m_allocator->AddRef(); + + return S_OK; +} + +HRESULT DirectShowInputPin::NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly) +{ + Q_UNUSED(bReadOnly) + + if (!pAllocator) + return E_POINTER; + + QMutexLocker locker(&m_mutex); + + if (m_allocator) + m_allocator->Release(); + + m_allocator = pAllocator; + m_allocator->AddRef(); + + return S_OK; +} + +HRESULT DirectShowInputPin::GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps) +{ + Q_UNUSED(pProps) + return E_NOTIMPL; +} + +HRESULT DirectShowInputPin::Receive(IMediaSample *pSample) +{ + if (!pSample) + return E_POINTER; + if (m_filter->state() == State_Stopped) + return VFW_E_WRONG_STATE; + if (m_flushing) + return S_FALSE; + if (m_inErrorState) + return VFW_E_RUNTIME_ERROR; + + HRESULT hr = S_OK; + + IMediaSample2 *sample2; + if (SUCCEEDED(pSample->QueryInterface(IID_PPV_ARGS(&sample2)))) { + hr = sample2->GetProperties(sizeof(m_sampleProperties), (PBYTE)&m_sampleProperties); + sample2->Release(); + if (FAILED(hr)) + return hr; + } else { + m_sampleProperties.cbData = sizeof(m_sampleProperties); + m_sampleProperties.dwTypeSpecificFlags = 0; + m_sampleProperties.dwStreamId = AM_STREAM_MEDIA; + m_sampleProperties.dwSampleFlags = 0; + if (pSample->IsDiscontinuity() == S_OK) + m_sampleProperties.dwSampleFlags |= AM_SAMPLE_DATADISCONTINUITY; + if (pSample->IsPreroll() == S_OK) + m_sampleProperties.dwSampleFlags |= AM_SAMPLE_PREROLL; + if (pSample->IsSyncPoint() == S_OK) + m_sampleProperties.dwSampleFlags |= AM_SAMPLE_SPLICEPOINT; + if (SUCCEEDED(pSample->GetTime(&m_sampleProperties.tStart, + &m_sampleProperties.tStop))) { + m_sampleProperties.dwSampleFlags |= AM_SAMPLE_TIMEVALID | AM_SAMPLE_STOPVALID; + } + if (pSample->GetMediaType(&m_sampleProperties.pMediaType) == S_OK) + m_sampleProperties.dwSampleFlags |= AM_SAMPLE_TYPECHANGED; + pSample->GetPointer(&m_sampleProperties.pbBuffer); + m_sampleProperties.lActual = pSample->GetActualDataLength(); + m_sampleProperties.cbBuffer = pSample->GetSize(); + } + + + if (!(m_sampleProperties.dwSampleFlags & AM_SAMPLE_TYPECHANGED)) + return S_OK; + + if (isMediaTypeSupported(m_sampleProperties.pMediaType)) + return S_OK; + + m_inErrorState = true; + EndOfStream(); + m_filter->NotifyEvent(EC_ERRORABORT, VFW_E_TYPE_NOT_ACCEPTED, 0); + return VFW_E_INVALIDMEDIATYPE; +} + +HRESULT DirectShowInputPin::ReceiveMultiple(IMediaSample **pSamples, long nSamples, long *nSamplesProcessed) +{ + if (!pSamples || !nSamplesProcessed) + return E_POINTER; + + HRESULT hr = S_OK; + *nSamplesProcessed = 0; + while (nSamples-- > 0) { + hr = Receive(pSamples[*nSamplesProcessed]); + if (hr != S_OK) + break; + (*nSamplesProcessed)++; + } + return hr; +} + +HRESULT DirectShowInputPin::ReceiveCanBlock() +{ + int outputPins = 0; + + const QList pinList = m_filter->pins(); + for (DirectShowPin *pin : pinList) { + PIN_DIRECTION pd; + HRESULT hr = pin->QueryDirection(&pd); + if (FAILED(hr)) + return hr; + + if (pd == PINDIR_OUTPUT) { + IPin *connected; + hr = pin->ConnectedTo(&connected); + if (SUCCEEDED(hr)) { + ++outputPins; + IMemInputPin *inputPin; + hr = connected->QueryInterface(IID_PPV_ARGS(&inputPin)); + connected->Release(); + if (SUCCEEDED(hr)) { + hr = inputPin->ReceiveCanBlock(); + inputPin->Release(); + if (hr != S_FALSE) + return S_OK; + } else { + return S_OK; + } + } + } + } + + return outputPins == 0 ? S_OK : S_FALSE; +} + +QT_END_NAMESPACE diff --git a/src/plugins/directshow/common/directshowpin.h b/src/plugins/directshow/common/directshowpin.h new file mode 100644 index 000000000..97e808384 --- /dev/null +++ b/src/plugins/directshow/common/directshowpin.h @@ -0,0 +1,192 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 DIRECTSHOWPIN_H +#define DIRECTSHOWPIN_H + +#include "directshowobject.h" + +#include "directshowmediatype.h" +#include +#include + +QT_BEGIN_NAMESPACE + +class DirectShowBaseFilter; + +class DirectShowPin : public DirectShowObject + , public IPin +{ + DIRECTSHOW_OBJECT + +public: + virtual ~DirectShowPin(); + + QString name() const { return m_name; } + bool isConnected() const { return m_peerPin != NULL; } + + virtual bool isMediaTypeSupported(const AM_MEDIA_TYPE *type) = 0; + virtual QList supportedMediaTypes(); + virtual bool setMediaType(const AM_MEDIA_TYPE *type); + + virtual HRESULT completeConnection(IPin *pin); + virtual HRESULT connectionEnded(); + + virtual HRESULT setActive(bool active); + + // DirectShowObject + HRESULT getInterface(REFIID riid, void **ppvObject); + + // IPin + STDMETHODIMP Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt); + STDMETHODIMP ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt); + STDMETHODIMP Disconnect(); + STDMETHODIMP ConnectedTo(IPin **ppPin); + + STDMETHODIMP ConnectionMediaType(AM_MEDIA_TYPE *pmt); + + STDMETHODIMP QueryPinInfo(PIN_INFO *pInfo); + STDMETHODIMP QueryId(LPWSTR *Id); + + STDMETHODIMP QueryAccept(const AM_MEDIA_TYPE *pmt); + + STDMETHODIMP EnumMediaTypes(IEnumMediaTypes **ppEnum); + + STDMETHODIMP QueryInternalConnections(IPin **apPin, ULONG *nPin); + + STDMETHODIMP EndOfStream(); + + STDMETHODIMP BeginFlush(); + STDMETHODIMP EndFlush(); + + STDMETHODIMP NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate); + + STDMETHODIMP QueryDirection(PIN_DIRECTION *pPinDir); + +protected: + DirectShowPin(DirectShowBaseFilter *filter, const QString &name, PIN_DIRECTION direction); + + QMutex m_mutex; + + DirectShowBaseFilter *m_filter; + QString m_name; + PIN_DIRECTION m_direction; + + IPin *m_peerPin; + DirectShowMediaType m_mediaType; + +private: + Q_DISABLE_COPY(DirectShowPin) + HRESULT tryMediaTypes(IPin *pin, const AM_MEDIA_TYPE *type, IEnumMediaTypes *enumMediaTypes); + HRESULT tryConnect(IPin *pin, const AM_MEDIA_TYPE *type); +}; + + +class DirectShowOutputPin : public DirectShowPin +{ + DIRECTSHOW_OBJECT + +public: + virtual ~DirectShowOutputPin(); + + // DirectShowPin + virtual HRESULT completeConnection(IPin *pin); + virtual HRESULT connectionEnded(); + virtual HRESULT setActive(bool active); + + // IPin + STDMETHODIMP EndOfStream(); + +protected: + DirectShowOutputPin(DirectShowBaseFilter *filter, const QString &name); + + IMemAllocator *m_allocator; + IMemInputPin *m_inputPin; + +private: + Q_DISABLE_COPY(DirectShowOutputPin) +}; + + +class DirectShowInputPin : public DirectShowPin + , public IMemInputPin +{ + DIRECTSHOW_OBJECT + +public: + virtual ~DirectShowInputPin(); + + const AM_SAMPLE2_PROPERTIES *currentSampleProperties() const { return &m_sampleProperties; } + + // DirectShowObject + HRESULT getInterface(REFIID riid, void **ppvObject); + + // DirectShowPin + HRESULT connectionEnded(); + HRESULT setActive(bool active); + + // IPin + STDMETHODIMP EndOfStream(); + STDMETHODIMP BeginFlush(); + STDMETHODIMP EndFlush(); + + // IMemInputPin + STDMETHODIMP GetAllocator(IMemAllocator **ppAllocator); + STDMETHODIMP NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly); + STDMETHODIMP GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps); + + STDMETHODIMP Receive(IMediaSample *pSample); + STDMETHODIMP ReceiveMultiple(IMediaSample **pSamples, long nSamples, long *nSamplesProcessed); + STDMETHODIMP ReceiveCanBlock(); + +protected: + DirectShowInputPin(DirectShowBaseFilter *filter, const QString &name); + + IMemAllocator *m_allocator; + bool m_flushing; + bool m_inErrorState; + AM_SAMPLE2_PROPERTIES m_sampleProperties; + +private: + Q_DISABLE_COPY(DirectShowInputPin) +}; + +QT_END_NAMESPACE + +#endif // DIRECTSHOWPIN_H diff --git a/src/plugins/directshow/common/directshowpinenum.cpp b/src/plugins/directshow/common/directshowpinenum.cpp new file mode 100644 index 000000000..910bba77d --- /dev/null +++ b/src/plugins/directshow/common/directshowpinenum.cpp @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** 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" +#include "directshowbasefilter.h" + +QT_BEGIN_NAMESPACE + +DirectShowPinEnum::DirectShowPinEnum(DirectShowBaseFilter *filter) + : m_filter(filter) + , m_index(0) +{ + m_filter->AddRef(); + const QList pinList = filter->pins(); + for (DirectShowPin *pin : pinList) { + pin->AddRef(); + m_pins.append(pin); + } +} + +DirectShowPinEnum::DirectShowPinEnum(const QList &pins) + : m_filter(NULL) + , m_pins(pins) + , m_index(0) +{ + for (IPin *pin : qAsConst(m_pins)) + pin->AddRef(); +} + +DirectShowPinEnum::~DirectShowPinEnum() +{ + for (IPin *pin : qAsConst(m_pins)) + pin->Release(); + if (m_filter) + m_filter->Release(); +} + +HRESULT DirectShowPinEnum::getInterface(REFIID riid, void **ppvObject) +{ + if (riid == IID_IEnumPins) { + return GetInterface(static_cast(this), ppvObject); + } else { + return DirectShowObject::getInterface(riid, ppvObject); + } +} + +HRESULT DirectShowPinEnum::Next(ULONG cPins, IPin **ppPins, ULONG *pcFetched) +{ + if (ppPins && (pcFetched || cPins == 1)) { + ULONG count = qBound(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) { + if (m_filter) + *ppEnum = new DirectShowPinEnum(m_filter); + else + *ppEnum = new DirectShowPinEnum(m_pins); + + return S_OK; + } else { + return E_POINTER; + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/directshow/common/directshowpinenum.h b/src/plugins/directshow/common/directshowpinenum.h new file mode 100644 index 000000000..77214e376 --- /dev/null +++ b/src/plugins/directshow/common/directshowpinenum.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** 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 + +#include +#include "directshowpin.h" + +QT_BEGIN_NAMESPACE + +class DirectShowBaseFilter; + +class DirectShowPinEnum : public DirectShowObject + , public IEnumPins +{ + DIRECTSHOW_OBJECT + +public: + DirectShowPinEnum(DirectShowBaseFilter *filter); + DirectShowPinEnum(const QList &pins); + ~DirectShowPinEnum(); + + // DirectShowObject + HRESULT getInterface(REFIID riid, void **ppvObject); + + // IEnumPins + STDMETHODIMP Next(ULONG cPins, IPin **ppPins, ULONG *pcFetched); + STDMETHODIMP Skip(ULONG cPins); + STDMETHODIMP Reset(); + STDMETHODIMP Clone(IEnumPins **ppEnum); + +private: + Q_DISABLE_COPY(DirectShowPinEnum) + + DirectShowBaseFilter *m_filter; + QList m_pins; + int m_index; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/directshow/common/directshowutils.cpp b/src/plugins/directshow/common/directshowutils.cpp new file mode 100644 index 000000000..96fabd6da --- /dev/null +++ b/src/plugins/directshow/common/directshowutils.cpp @@ -0,0 +1,313 @@ +/**************************************************************************** +** +** 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 "directshowutils.h" + +QT_BEGIN_NAMESPACE + +/** + * @brief DirectShowUtils::isPinConnected + * @param pin + * @param hrOut + * @return + */ +bool DirectShowUtils::isPinConnected(IPin *pin, HRESULT *hrOut) +{ + IPin *connectedPin = nullptr; + const ScopedSafeRelease releasePin { &connectedPin }; + HRESULT hr = S_OK; + if (!hrOut) + hrOut = &hr; + + *hrOut = pin->ConnectedTo(&connectedPin); + if (*hrOut == VFW_E_NOT_CONNECTED) // Not an error in this case + *hrOut = S_OK; + + if (FAILED(*hrOut)) { + qCDebug(qtDirectShowPlugin, "Querying pin connection failed!"); + return false; + } + + return true; +} + +/** + * @brief DirectShowUtils::hasPinDirection + * @param pin + * @param direction + * @param hrOut + * @return + */ +bool DirectShowUtils::hasPinDirection(IPin *pin, PIN_DIRECTION direction, HRESULT *hrOut) +{ + PIN_DIRECTION pinDir; + HRESULT hr = S_OK; + if (!hrOut) + hrOut = &hr; + + *hrOut = pin->QueryDirection(&pinDir); + + if (FAILED(*hrOut)) { + qCDebug(qtDirectShowPlugin, "Querying pin direction failed!"); + return false; + } + + return (pinDir == direction); +} + +/** + * @brief DirectShowUtils::getPin + * @param filter + * @param pinDirection + * @param pin + * @param hrOut + * @return + */ +bool DirectShowUtils::getPin(IBaseFilter *filter, PIN_DIRECTION pinDirection, IPin **pin, HRESULT *hrOut) +{ + IEnumPins *enumPins = nullptr; + const ScopedSafeRelease releaseEnumPins { &enumPins }; + HRESULT hr S_OK; + if (!hrOut) + hrOut = &hr; + + *hrOut = filter->EnumPins(&enumPins); + if (FAILED(*hrOut)) { + qCDebug(qtDirectShowPlugin, "Unable to retrieve pins from the filter!"); + return false; + } + + enumPins->Reset(); + IPin *nextPin = nullptr; + while (enumPins->Next(1, &nextPin, NULL) == S_OK) { + const ScopedSafeRelease releasePin { &nextPin }; + PIN_DIRECTION currentPinDir; + *hrOut = nextPin->QueryDirection(¤tPinDir); + if (currentPinDir == pinDirection) { + *pin = nextPin; + (*pin)->AddRef(); + return true; + } + } + + return false; +} + +/** + * @brief DirectShowUtils::matchPin + * @param pin + * @param pinDirection + * @param shouldBeConnected + * @param hrOut + * @return + */ +bool DirectShowUtils::matchPin(IPin *pin, PIN_DIRECTION pinDirection, BOOL shouldBeConnected, HRESULT *hrOut) +{ + HRESULT hr = S_OK; + if (!hrOut) + hrOut = &hr; + + const BOOL isConnected = isPinConnected(pin, hrOut); + if (FAILED(*hrOut)) // Error reason will already be logged, so just return. + return false; + + if (isConnected == shouldBeConnected) + return hasPinDirection(pin, pinDirection, hrOut); + + return SUCCEEDED(*hrOut); +} + +/** + * @brief DirectShowUtils::findUnconnectedPin + * @param filter + * @param pinDirection + * @param pin + * @param hrOut + * @return + */ +bool DirectShowUtils::findUnconnectedPin(IBaseFilter *filter, PIN_DIRECTION pinDirection, IPin **pin, HRESULT *hrOut) +{ + HRESULT hr = S_OK; + if (!hrOut) + hrOut = &hr; + + IEnumPins *enumPins = nullptr; + const ScopedSafeRelease releaseEnumPins { &enumPins }; + *hrOut = filter->EnumPins(&enumPins); + if (FAILED(*hrOut)) { + qCDebug(qtDirectShowPlugin, "Unable to retrieve pins from the DS filter"); + return false; + } + + IPin *nextPin = nullptr; + while (S_OK == enumPins->Next(1, &nextPin, nullptr)) { + const ScopedSafeRelease releaseNextPin { &nextPin }; + if (matchPin(nextPin, pinDirection, FALSE, hrOut)) { + *pin = nextPin; + (*pin)->AddRef(); + return true; + } + + if (FAILED(*hrOut)) + return false; + } + + qCDebug(qtDirectShowPlugin, "No unconnected pins found"); + *hrOut = VFW_E_NOT_FOUND; + + return false; +} + +/** + * @brief DirectShowUtils::connectFilters - Attempts to connect \a outputPin to \a filter + * @param graph + * @param outputPin + * @param filter + * @param hrOut + * @return + */ +bool DirectShowUtils::connectFilters(IGraphBuilder *graph, IPin *outputPin, IBaseFilter *filter, HRESULT *hrOut) +{ + + // Find an input pin on the downstream filter. + HRESULT hr = S_OK; + if (!hrOut) + hrOut = &hr; + + IPin *inputPin = nullptr; + const ScopedSafeRelease releaseInputPin { &inputPin }; + if (!findUnconnectedPin(filter, PINDIR_INPUT, &inputPin, hrOut)) + return false; + + + // Try to connect them. + *hrOut = graph->Connect(outputPin, inputPin); + if (FAILED(*hrOut)) { + qCDebug(qtDirectShowPlugin, "Unable to connect output pin to filter!"); + return false; + } + + return true; +} + +/** + * @brief DirectShowUtils::connectFilters - Attempts to connect \a filter to \a inputPin. + * @param graph + * @param filter + * @param inputPin + * @param hrOut + * @return + */ +bool DirectShowUtils::connectFilters(IGraphBuilder *graph, IBaseFilter *filter, IPin *inputPin, HRESULT *hrOut) +{ + HRESULT hr = S_OK; + if (!hrOut) + hrOut = &hr; + + IPin *outputPin = nullptr; + const ScopedSafeRelease releaseOutputPin { &outputPin }; + // Find an output pin on the upstream filter. + if (findUnconnectedPin(filter, PINDIR_OUTPUT, &outputPin, hrOut)) + return false; + + *hrOut = graph->Connect(outputPin, inputPin); + if (FAILED(*hrOut)) { + qCDebug(qtDirectShowPlugin, "Unable to connect filter to input pin!"); + return false; + } + + return true; +} + +/** + * @brief DirectShowUtils::connectFilters - Attempts to connect the \a upstreamFilter to \a downstreamFilter. + * @param graph + * @param upstreamFilter + * @param downstreamFilter + * @param autoConnect - If set to true all filters in the graph will be considered. + * @param hrOut + * @return true if the the filters were connected, false otherwise. + */ +bool DirectShowUtils::connectFilters(IGraphBuilder *graph, + IBaseFilter *upstreamFilter, + IBaseFilter *downstreamFilter, + bool autoConnect, + HRESULT *hrOut) +{ + HRESULT hr = S_OK; + if (!hrOut) + hrOut = &hr; + + const auto findAndConnect = [graph, downstreamFilter, hrOut](IBaseFilter *filter) -> bool { + IPin *outputPin = nullptr; + const ScopedSafeRelease releaseOutputPin { &outputPin }; + if (findUnconnectedPin(filter, PINDIR_OUTPUT, &outputPin, hrOut)) + return connectFilters(graph, outputPin, downstreamFilter, hrOut); + + return false; + }; + + // Try to connect to the upstream filter first. + if (findAndConnect(upstreamFilter)) + return S_OK; + + const auto getFilters = [graph, hrOut]() -> IEnumFilters * { + IEnumFilters *f = nullptr; + *hrOut = graph->EnumFilters(&f); + return f; + }; + IEnumFilters *filters = autoConnect ? getFilters() + : nullptr; + const ScopedSafeRelease releaseEnumFilters { &filters }; + if (!filters) { + qCDebug(qtDirectShowPlugin, "No filters found!"); + return false; + } + + IBaseFilter *nextFilter = nullptr; + while (S_OK == filters->Next(1, &nextFilter, 0)) { + const ScopedSafeRelease releaseNextFilter { &nextFilter }; + if (nextFilter && findAndConnect(nextFilter)) + break; + } + + return SUCCEEDED(*hrOut); +} + +QT_END_NAMESPACE diff --git a/src/plugins/directshow/common/directshowutils.h b/src/plugins/directshow/common/directshowutils.h new file mode 100644 index 000000000..09c81c257 --- /dev/null +++ b/src/plugins/directshow/common/directshowutils.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** 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 DIRECTSHOWUTILS_H +#define DIRECTSHOWUTILS_H + +#include "directshowglobal.h" + +QT_BEGIN_NAMESPACE + +namespace DirectShowUtils +{ +template +void safeRelease(T **iface) { + if (!iface) + return; + + if (!*iface) + return; + + (*iface)->Release(); + *iface = nullptr; +} + +template +struct ScopedSafeRelease +{ + T **iunknown; + ~ScopedSafeRelease() + { + DirectShowUtils::safeRelease(iunknown); + } +}; + +bool getPin(IBaseFilter *filter, PIN_DIRECTION pinDirection, IPin **pin, HRESULT *hrOut); +bool isPinConnected(IPin *pin, HRESULT *hrOut = nullptr); +bool hasPinDirection(IPin *pin, PIN_DIRECTION direction, HRESULT *hrOut = nullptr); +bool matchPin(IPin *pin, PIN_DIRECTION pinDirection, BOOL shouldBeConnected, HRESULT *hrOut = nullptr); +bool findUnconnectedPin(IBaseFilter *filter, PIN_DIRECTION pinDirection, IPin **pin, HRESULT *hrOut = nullptr); +bool connectFilters(IGraphBuilder *graph, IPin *outputPin, IBaseFilter *filter, HRESULT *hrOut = nullptr); +bool connectFilters(IGraphBuilder *graph, IBaseFilter *filter, IPin *inputPin, HRESULT *hrOut = nullptr); +bool connectFilters(IGraphBuilder *graph, + IBaseFilter *upstreamFilter, + IBaseFilter *downstreamFilter, + bool autoConnect = false, + HRESULT *hrOut = nullptr); +} + +QT_END_NAMESPACE + +#endif // DIRECTSHOWUTILS_H diff --git a/src/plugins/directshow/common/directshowvideobuffer.cpp b/src/plugins/directshow/common/directshowvideobuffer.cpp new file mode 100644 index 000000000..7f94da97e --- /dev/null +++ b/src/plugins/directshow/common/directshowvideobuffer.cpp @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** 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 "directshowvideobuffer.h" + +QT_BEGIN_NAMESPACE + +DirectShowVideoBuffer::DirectShowVideoBuffer(IMediaSample *sample, int bytesPerLine) + : QAbstractVideoBuffer(NoHandle) + , m_sample(sample) + , m_bytesPerLine(bytesPerLine) + , m_mapMode(NotMapped) +{ + m_sample->AddRef(); +} + +DirectShowVideoBuffer::~DirectShowVideoBuffer() +{ + m_sample->Release(); +} + +uchar *DirectShowVideoBuffer::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(bytes); + } + } + return 0; +} + +void DirectShowVideoBuffer::unmap() +{ + m_mapMode = NotMapped; +} + +QAbstractVideoBuffer::MapMode DirectShowVideoBuffer::mapMode() const +{ + return m_mapMode; +} + +QT_END_NAMESPACE diff --git a/src/plugins/directshow/common/directshowvideobuffer.h b/src/plugins/directshow/common/directshowvideobuffer.h new file mode 100644 index 000000000..85e02b53d --- /dev/null +++ b/src/plugins/directshow/common/directshowvideobuffer.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** 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 DIRECTSHOWVIDEOBUFFER_H +#define DIRECTSHOWVIDEOBUFFER_H + +#include + +#include + +QT_BEGIN_NAMESPACE + +class DirectShowVideoBuffer : public QAbstractVideoBuffer +{ +public: + DirectShowVideoBuffer(IMediaSample *sample, int bytesPerLine); + ~DirectShowVideoBuffer(); + + 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; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/directshow/directshow.pro b/src/plugins/directshow/directshow.pro index 35301474f..2857f87d9 100644 --- a/src/plugins/directshow/directshow.pro +++ b/src/plugins/directshow/directshow.pro @@ -11,7 +11,6 @@ SOURCES += dsserviceplugin.cpp mingw: DEFINES += NO_DSHOW_STRSAFE include(common/common.pri) -include(helpers/helpers.pri) qtConfig(directshow-player): include(player/player.pri) include(camera/camera.pri) diff --git a/src/plugins/directshow/helpers/directshowbasefilter.cpp b/src/plugins/directshow/helpers/directshowbasefilter.cpp deleted file mode 100644 index 342f0c271..000000000 --- a/src/plugins/directshow/helpers/directshowbasefilter.cpp +++ /dev/null @@ -1,277 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 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 "directshowbasefilter.h" - -#include "directshowpinenum.h" - -QT_BEGIN_NAMESPACE - -DirectShowBaseFilter::DirectShowBaseFilter() - : m_mutex(QMutex::Recursive) - , m_state(State_Stopped) - , m_graph(NULL) - , m_clock(NULL) - , m_sink(NULL) -{ - -} - -DirectShowBaseFilter::~DirectShowBaseFilter() -{ - if (m_clock) { - m_clock->Release(); - m_clock = NULL; - } -} - -HRESULT DirectShowBaseFilter::getInterface(REFIID riid, void **ppvObject) -{ - if (riid == IID_IPersist - || riid == IID_IMediaFilter - || riid == IID_IBaseFilter) { - return GetInterface(static_cast(this), ppvObject); - } else { - return DirectShowObject::getInterface(riid, ppvObject); - } -} - -HRESULT DirectShowBaseFilter::GetClassID(CLSID *pClassID) -{ - *pClassID = CLSID_NULL; - return S_OK; -} - -HRESULT DirectShowBaseFilter::NotifyEvent(long eventCode, LONG_PTR eventParam1, LONG_PTR eventParam2) -{ - IMediaEventSink *sink = m_sink; - if (sink) { - if (eventCode == EC_COMPLETE) - eventParam2 = (LONG_PTR)(IBaseFilter*)this; - - return sink->Notify(eventCode, eventParam1, eventParam2); - } else { - return E_NOTIMPL; - } -} - -HRESULT DirectShowBaseFilter::Run(REFERENCE_TIME tStart) -{ - Q_UNUSED(tStart) - QMutexLocker locker(&m_mutex); - - m_startTime = tStart; - - if (m_state == State_Stopped){ - HRESULT hr = Pause(); - if (FAILED(hr)) - return hr; - } - - m_state = State_Running; - - return S_OK; -} - -HRESULT DirectShowBaseFilter::Pause() -{ - QMutexLocker locker(&m_mutex); - - if (m_state == State_Stopped) { - const QList pinList = pins(); - for (DirectShowPin *pin : pinList) { - if (pin->isConnected()) { - HRESULT hr = pin->setActive(true); - if (FAILED(hr)) - return hr; - } - } - } - - m_state = State_Paused; - - return S_OK; -} - -HRESULT DirectShowBaseFilter::Stop() -{ - QMutexLocker locker(&m_mutex); - - HRESULT hr = S_OK; - - if (m_state != State_Stopped) { - const QList pinList = pins(); - for (DirectShowPin *pin : pinList) { - if (pin->isConnected()) { - HRESULT hrTmp = pin->setActive(false); - if (FAILED(hrTmp) && SUCCEEDED(hr)) - hr = hrTmp; - } - } - } - - m_state = State_Stopped; - - return hr; -} - -HRESULT DirectShowBaseFilter::GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *pState) -{ - Q_UNUSED(dwMilliSecsTimeout); - - if (!pState) { - return E_POINTER; - } else { - QMutexLocker locker(&m_mutex); - - *pState = m_state; - - return S_OK; - } -} - -HRESULT DirectShowBaseFilter::SetSyncSource(IReferenceClock *pClock) -{ - QMutexLocker locker(&m_mutex); - - if (m_clock) - m_clock->Release(); - - m_clock = pClock; - - if (m_clock) - m_clock->AddRef(); - - return S_OK; -} - -HRESULT DirectShowBaseFilter::GetSyncSource(IReferenceClock **ppClock) -{ - if (!ppClock) { - return E_POINTER; - } else { - if (!m_clock) { - *ppClock = 0; - - return S_FALSE; - } else { - m_clock->AddRef(); - - *ppClock = m_clock; - - return S_OK; - } - } -} - -HRESULT DirectShowBaseFilter::EnumPins(IEnumPins **ppEnum) -{ - if (!ppEnum) { - return E_POINTER; - } else { - *ppEnum = new DirectShowPinEnum(this); - return S_OK; - } -} - -HRESULT DirectShowBaseFilter::FindPin(LPCWSTR Id, IPin **ppPin) -{ - if (!ppPin || !Id) { - return E_POINTER; - } else { - QMutexLocker locker(&m_mutex); - const QList pinList = pins(); - for (DirectShowPin *pin : pinList) { - if (QString::fromWCharArray(Id) == pin->name()) { - pin->AddRef(); - *ppPin = pin; - return S_OK; - } - } - - *ppPin = 0; - return VFW_E_NOT_FOUND; - } -} - -HRESULT DirectShowBaseFilter::JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName) -{ - QMutexLocker locker(&m_mutex); - - m_filterName = QString::fromWCharArray(pName); - m_graph = pGraph; - m_sink = NULL; - - if (m_graph) { - if (SUCCEEDED(m_graph->QueryInterface(IID_PPV_ARGS(&m_sink)))) - m_sink->Release(); // we don't keep a reference on it - } - - return S_OK; -} - -HRESULT DirectShowBaseFilter::QueryFilterInfo(FILTER_INFO *pInfo) -{ - if (!pInfo) { - return E_POINTER; - } else { - QString name = m_filterName; - - if (name.length() >= MAX_FILTER_NAME) - name.truncate(MAX_FILTER_NAME - 1); - - int length = name.toWCharArray(pInfo->achName); - pInfo->achName[length] = '\0'; - - if (m_graph) - m_graph->AddRef(); - - pInfo->pGraph = m_graph; - - return S_OK; - } -} - -HRESULT DirectShowBaseFilter::QueryVendorInfo(LPWSTR *pVendorInfo) -{ - Q_UNUSED(pVendorInfo); - return E_NOTIMPL; -} - -QT_END_NAMESPACE diff --git a/src/plugins/directshow/helpers/directshowbasefilter.h b/src/plugins/directshow/helpers/directshowbasefilter.h deleted file mode 100644 index 9a2f44567..000000000 --- a/src/plugins/directshow/helpers/directshowbasefilter.h +++ /dev/null @@ -1,101 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 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 DIRECTSHOWBASEFILTER_H -#define DIRECTSHOWBASEFILTER_H - -#include "directshowpin.h" - -QT_BEGIN_NAMESPACE - -class DirectShowBaseFilter : public DirectShowObject - , public IBaseFilter -{ - DIRECTSHOW_OBJECT - -public: - DirectShowBaseFilter(); - virtual ~DirectShowBaseFilter(); - - FILTER_STATE state() const { return m_state; } - HRESULT NotifyEvent(long eventCode, LONG_PTR eventParam1, LONG_PTR eventParam2); - - virtual QList pins() = 0; - - // DirectShowObject - HRESULT getInterface(const IID &riid, void **ppvObject); - - // IPersist - STDMETHODIMP GetClassID(CLSID *pClassID); - - // IMediaFilter - STDMETHODIMP Run(REFERENCE_TIME tStart); - STDMETHODIMP Pause(); - STDMETHODIMP Stop(); - - STDMETHODIMP GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *pState); - - STDMETHODIMP SetSyncSource(IReferenceClock *pClock); - STDMETHODIMP GetSyncSource(IReferenceClock **ppClock); - - // IBaseFilter - STDMETHODIMP EnumPins(IEnumPins **ppEnum); - STDMETHODIMP FindPin(LPCWSTR Id, IPin **ppPin); - - STDMETHODIMP JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName); - - STDMETHODIMP QueryFilterInfo(FILTER_INFO *pInfo); - STDMETHODIMP QueryVendorInfo(LPWSTR *pVendorInfo); - -protected: - QMutex m_mutex; - FILTER_STATE m_state; - IFilterGraph *m_graph; - IReferenceClock *m_clock; - IMediaEventSink *m_sink; - QString m_filterName; - REFERENCE_TIME m_startTime; - -private: - Q_DISABLE_COPY(DirectShowBaseFilter) -}; - -QT_END_NAMESPACE - -#endif // DIRECTSHOWBASEFILTER_H diff --git a/src/plugins/directshow/helpers/directshoweventloop.cpp b/src/plugins/directshow/helpers/directshoweventloop.cpp deleted file mode 100644 index ef85c0429..000000000 --- a/src/plugins/directshow/helpers/directshoweventloop.cpp +++ /dev/null @@ -1,152 +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 - -#include -#include - -QT_BEGIN_NAMESPACE - -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(); - } -} - -QT_END_NAMESPACE diff --git a/src/plugins/directshow/helpers/directshoweventloop.h b/src/plugins/directshow/helpers/directshoweventloop.h deleted file mode 100644 index 609e53134..000000000 --- a/src/plugins/directshow/helpers/directshoweventloop.h +++ /dev/null @@ -1,80 +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 -#include -#include - -#include - -QT_BEGIN_NAMESPACE - -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; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/plugins/directshow/helpers/directshowglobal.h b/src/plugins/directshow/helpers/directshowglobal.h deleted file mode 100644 index 5f391710e..000000000 --- a/src/plugins/directshow/helpers/directshowglobal.h +++ /dev/null @@ -1,160 +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 - -#include -#include - -QT_BEGIN_NAMESPACE - -Q_DECLARE_LOGGING_CATEGORY(qtDirectShowPlugin) - -QT_END_NAMESPACE - -template T *com_cast(IUnknown *unknown, const IID &iid) -{ - T *iface = 0; - return unknown && unknown->QueryInterface(iid, reinterpret_cast(&iface)) == S_OK - ? iface - : 0; -} - -template 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 T *com_new(const IID &clsid, const IID &iid) -{ - T *object = 0; - return CoCreateInstance( - clsid, - NULL, - CLSCTX_INPROC_SERVER, - iid, - reinterpret_cast(&object)) == S_OK - ? object - : 0; -} - -DEFINE_GUID(MEDIASUBTYPE_I420, - 0x30323449,0x0000,0x0010,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71); - -#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/helpers/directshowmediatype.cpp b/src/plugins/directshow/helpers/directshowmediatype.cpp deleted file mode 100644 index 65882806c..000000000 --- a/src/plugins/directshow/helpers/directshowmediatype.cpp +++ /dev/null @@ -1,350 +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" -#include "directshowglobal.h" - -namespace -{ - struct TypeLookup - { - QVideoFrame::PixelFormat pixelFormat; - GUID mediaType; - }; - - static const TypeLookup qt_typeLookup[] = - { - { QVideoFrame::Format_ARGB32, MEDIASUBTYPE_ARGB32 }, - { QVideoFrame::Format_RGB32, MEDIASUBTYPE_RGB32 }, - { QVideoFrame::Format_RGB24, MEDIASUBTYPE_RGB24 }, - { QVideoFrame::Format_RGB565, MEDIASUBTYPE_RGB565 }, - { QVideoFrame::Format_RGB555, MEDIASUBTYPE_RGB555 }, - { QVideoFrame::Format_AYUV444, MEDIASUBTYPE_AYUV }, - { QVideoFrame::Format_YUYV, MEDIASUBTYPE_YUY2 }, - { QVideoFrame::Format_UYVY, MEDIASUBTYPE_UYVY }, - { QVideoFrame::Format_IMC1, MEDIASUBTYPE_IMC1 }, - { QVideoFrame::Format_IMC2, MEDIASUBTYPE_IMC2 }, - { QVideoFrame::Format_IMC3, MEDIASUBTYPE_IMC3 }, - { QVideoFrame::Format_IMC4, MEDIASUBTYPE_IMC4 }, - { QVideoFrame::Format_YV12, MEDIASUBTYPE_YV12 }, - { QVideoFrame::Format_NV12, MEDIASUBTYPE_NV12 }, - { QVideoFrame::Format_YUV420P, MEDIASUBTYPE_IYUV }, - { QVideoFrame::Format_YUV420P, MEDIASUBTYPE_I420 }, - { QVideoFrame::Format_Jpeg, MEDIASUBTYPE_MJPG } - }; -} - -bool DirectShowMediaType::isPartiallySpecified(const AM_MEDIA_TYPE *mediaType) -{ - return mediaType->majortype == GUID_NULL || mediaType->formattype == GUID_NULL; -} - -DirectShowMediaType::DirectShowMediaType() - : mediaType({ GUID_NULL, GUID_NULL, TRUE, FALSE, 1, GUID_NULL, nullptr, 0, nullptr}) -{ -} - -DirectShowMediaType::DirectShowMediaType(const AM_MEDIA_TYPE &type) - : DirectShowMediaType() -{ - copy(&mediaType, &type); -} - -DirectShowMediaType::DirectShowMediaType(AM_MEDIA_TYPE &&type) - : DirectShowMediaType() -{ - move(&mediaType, type); -} - -DirectShowMediaType::DirectShowMediaType(const DirectShowMediaType &other) - : DirectShowMediaType() -{ - copy(&mediaType, &other.mediaType); -} - -DirectShowMediaType::DirectShowMediaType(DirectShowMediaType &&other) - : DirectShowMediaType() -{ - move(&mediaType, other.mediaType); -} - -DirectShowMediaType &DirectShowMediaType::operator=(const DirectShowMediaType &other) -{ - copy(&mediaType, &other.mediaType); - return *this; -} - -DirectShowMediaType &DirectShowMediaType::operator=(DirectShowMediaType &&other) -{ - move(&mediaType, other.mediaType); - return *this; -} - -void DirectShowMediaType::init(AM_MEDIA_TYPE *type) -{ - Q_ASSERT(type); - SecureZeroMemory(reinterpret_cast(type), sizeof(AM_MEDIA_TYPE)); - type->lSampleSize = 1; - type->bFixedSizeSamples = TRUE; -} - -void DirectShowMediaType::copy(AM_MEDIA_TYPE *target, const AM_MEDIA_TYPE *source) -{ - if (!(target && source)) - return; - - if (target == source) - return; - - clear(*target); - - copyToUninitialized(target, source); -} - -void DirectShowMediaType::copyToUninitialized(AM_MEDIA_TYPE *target, const AM_MEDIA_TYPE *source) -{ - *target = *source; - - if (source->cbFormat > 0) { - target->pbFormat = reinterpret_cast(CoTaskMemAlloc(source->cbFormat)); - memcpy(target->pbFormat, source->pbFormat, source->cbFormat); - } - if (target->pUnk) - target->pUnk->AddRef(); -} - -void DirectShowMediaType::move(AM_MEDIA_TYPE *target, AM_MEDIA_TYPE **source) -{ - if (!target || !source || !(*source)) - return; - - if (target == *source) - return; - - clear(*target); - *target = *(*source); - SecureZeroMemory(reinterpret_cast(*source), sizeof(AM_MEDIA_TYPE)); - *source = nullptr; -} - -void DirectShowMediaType::move(AM_MEDIA_TYPE *target, AM_MEDIA_TYPE &source) -{ - AM_MEDIA_TYPE *srcPtr = &source; - move(target, &srcPtr); -} - -/** - * @brief DirectShowMediaType::deleteType - Used for AM_MEDIA_TYPE structures that have - * been allocated by CoTaskMemAlloc or CreateMediaType. - * @param type - */ -void DirectShowMediaType::deleteType(AM_MEDIA_TYPE *type) -{ - if (!type) - return; - - clear(*type); - CoTaskMemFree(type); -} - -bool DirectShowMediaType::isCompatible(const AM_MEDIA_TYPE *a, const AM_MEDIA_TYPE *b) -{ - if (b->majortype != GUID_NULL && a->majortype != b->majortype) - return false; - - if (b->subtype != GUID_NULL && a->subtype != b->subtype) - return false; - - if (b->formattype != GUID_NULL) { - if (a->formattype != b->formattype) - return false; - if (a->cbFormat != b->cbFormat) - return false; - if (a->cbFormat != 0 && memcmp(a->pbFormat, b->pbFormat, a->cbFormat) != 0) - return false; - } - - return true; -} - -/** - * @brief DirectShowMediaType::clear - Clears all member data, and releases allocated buffers. - * Use this to release automatic AM_MEDIA_TYPE structures. - * @param type - */ -void DirectShowMediaType::clear(AM_MEDIA_TYPE &type) -{ - if (type.cbFormat > 0) - CoTaskMemFree(type.pbFormat); - - if (type.pUnk) - type.pUnk->Release(); - - SecureZeroMemory(&type, sizeof(type)); -} - - -GUID DirectShowMediaType::convertPixelFormat(QVideoFrame::PixelFormat format) -{ - 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 MEDIASUBTYPE_None; -} - -QVideoSurfaceFormat DirectShowMediaType::videoFormatFromType(const AM_MEDIA_TYPE *type) -{ - if (!type) - return QVideoSurfaceFormat(); - - 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(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(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(); -} - -QVideoFrame::PixelFormat DirectShowMediaType::pixelFormatFromType(const AM_MEDIA_TYPE *type) -{ - if (!type) - return QVideoFrame::Format_Invalid; - - const int count = sizeof(qt_typeLookup) / sizeof(TypeLookup); - - for (int i = 0; i < count; ++i) { - if (IsEqualGUID(qt_typeLookup[i].mediaType, type->subtype)) { - return qt_typeLookup[i].pixelFormat; - } - } - - return QVideoFrame::Format_Invalid; -} - -#define PAD_TO_DWORD(x) (((x) + 3) & ~3) -int DirectShowMediaType::bytesPerLine(const QVideoSurfaceFormat &format) -{ - switch (format.pixelFormat()) { - // 32 bpp packed formats. - case QVideoFrame::Format_ARGB32: - 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_YV12: - case QVideoFrame::Format_YUV420P: - case QVideoFrame::Format_IMC1: - case QVideoFrame::Format_IMC2: - case QVideoFrame::Format_IMC3: - case QVideoFrame::Format_IMC4: - case QVideoFrame::Format_NV12: - return 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_ARGB32: - case QVideoFrame::Format_RGB32: - case QVideoFrame::Format_RGB24: - 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/helpers/directshowmediatype.h b/src/plugins/directshow/helpers/directshowmediatype.h deleted file mode 100644 index 7f495f3b2..000000000 --- a/src/plugins/directshow/helpers/directshowmediatype.h +++ /dev/null @@ -1,97 +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 - -#include - -#include -#include - -QT_BEGIN_NAMESPACE - -class DirectShowMediaType -{ -public: - DirectShowMediaType(); - DirectShowMediaType(const DirectShowMediaType &other); - DirectShowMediaType(DirectShowMediaType &&other); - explicit DirectShowMediaType(const AM_MEDIA_TYPE &type); - explicit DirectShowMediaType(AM_MEDIA_TYPE &&type); - ~DirectShowMediaType() { clear(mediaType); } - - DirectShowMediaType &operator =(const DirectShowMediaType &other); - DirectShowMediaType &operator =(DirectShowMediaType &&other); - - void clear() { clear(mediaType); } - - inline AM_MEDIA_TYPE *operator &() Q_DECL_NOTHROW { return &mediaType; } - inline AM_MEDIA_TYPE *operator ->() Q_DECL_NOTHROW { return &mediaType; } - - inline const AM_MEDIA_TYPE *operator &() const Q_DECL_NOTHROW { return &mediaType; } - inline const AM_MEDIA_TYPE *operator ->() const Q_DECL_NOTHROW { return &mediaType; } - - static void init(AM_MEDIA_TYPE *type); - static void copy(AM_MEDIA_TYPE *target, const AM_MEDIA_TYPE *source); - static void copyToUninitialized(AM_MEDIA_TYPE *target, const AM_MEDIA_TYPE *source); - static void move(AM_MEDIA_TYPE *target, AM_MEDIA_TYPE **source); - static void move(AM_MEDIA_TYPE *target, AM_MEDIA_TYPE &source); - static void clear(AM_MEDIA_TYPE &type); - static void deleteType(AM_MEDIA_TYPE *type); - static bool isPartiallySpecified(const AM_MEDIA_TYPE *mediaType); - static bool isCompatible(const AM_MEDIA_TYPE *a, const AM_MEDIA_TYPE *b); - static GUID convertPixelFormat(QVideoFrame::PixelFormat format); - - static QVideoSurfaceFormat videoFormatFromType(const AM_MEDIA_TYPE *type); - static QVideoFrame::PixelFormat pixelFormatFromType(const AM_MEDIA_TYPE *type); - static int bytesPerLine(const QVideoSurfaceFormat &format); - static QVideoSurfaceFormat::Direction scanLineDirection(QVideoFrame::PixelFormat pixelFormat, const BITMAPINFOHEADER &bmiHeader); - -private: - AM_MEDIA_TYPE mediaType; -}; - -Q_DECLARE_TYPEINFO(DirectShowMediaType, Q_MOVABLE_TYPE); - -QT_END_NAMESPACE - -#endif diff --git a/src/plugins/directshow/helpers/directshowmediatypeenum.cpp b/src/plugins/directshow/helpers/directshowmediatypeenum.cpp deleted file mode 100644 index 8fbdf7dea..000000000 --- a/src/plugins/directshow/helpers/directshowmediatypeenum.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 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 "directshowmediatypeenum.h" - -#include "directshowpin.h" - -DirectShowMediaTypeEnum::DirectShowMediaTypeEnum(DirectShowPin *pin) - : m_pin(pin) - , m_mediaTypes(pin->supportedMediaTypes()) - , m_index(0) -{ - m_pin->AddRef(); -} - -DirectShowMediaTypeEnum::DirectShowMediaTypeEnum(const QList &types) - : m_pin(NULL) - , m_mediaTypes(types) - , m_index(0) -{ -} - -DirectShowMediaTypeEnum::~DirectShowMediaTypeEnum() -{ - if (m_pin) - m_pin->Release(); -} - -HRESULT DirectShowMediaTypeEnum::getInterface(REFIID riid, void **ppvObject) -{ - if (riid == IID_IEnumMediaTypes) { - return GetInterface(static_cast(this), ppvObject); - } else { - return DirectShowObject::getInterface(riid, ppvObject); - } -} - -HRESULT DirectShowMediaTypeEnum::Next(ULONG cMediaTypes, AM_MEDIA_TYPE **ppMediaTypes, ULONG *pcFetched) -{ - if (ppMediaTypes && (pcFetched || cMediaTypes == 1)) { - ULONG count = qBound(0, cMediaTypes, m_mediaTypes.count() - m_index); - - for (ULONG i = 0; i < count; ++i, ++m_index) { - ppMediaTypes[i] = reinterpret_cast(CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE))); - DirectShowMediaType::copyToUninitialized(ppMediaTypes[i], &m_mediaTypes.at(m_index)); - } - - if (pcFetched) - *pcFetched = count; - - return count == cMediaTypes ? S_OK : S_FALSE; - } else { - return E_POINTER; - } -} - -HRESULT DirectShowMediaTypeEnum::Skip(ULONG cMediaTypes) -{ - m_index = qMin(int(m_index + cMediaTypes), m_mediaTypes.count()); - return m_index < m_mediaTypes.count() ? S_OK : S_FALSE; -} - -HRESULT DirectShowMediaTypeEnum::Reset() -{ - m_index = 0; - return S_OK; -} - -HRESULT DirectShowMediaTypeEnum::Clone(IEnumMediaTypes **ppEnum) -{ - if (ppEnum) { - if (m_pin) - *ppEnum = new DirectShowMediaTypeEnum(m_pin); - else - *ppEnum = new DirectShowMediaTypeEnum(m_mediaTypes); - return S_OK; - } else { - return E_POINTER; - } -} - diff --git a/src/plugins/directshow/helpers/directshowmediatypeenum.h b/src/plugins/directshow/helpers/directshowmediatypeenum.h deleted file mode 100644 index 9b058fc5b..000000000 --- a/src/plugins/directshow/helpers/directshowmediatypeenum.h +++ /dev/null @@ -1,80 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 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 DIRECTSHOWMEDIATYPEENUM_H -#define DIRECTSHOWMEDIATYPEENUM_H - -#include "directshowobject.h" -#include - -QT_BEGIN_NAMESPACE - -class DirectShowPin; -class DirectShowMediaType; - -class DirectShowMediaTypeEnum : public DirectShowObject - , public IEnumMediaTypes -{ - DIRECTSHOW_OBJECT - -public: - DirectShowMediaTypeEnum(DirectShowPin *pin); - DirectShowMediaTypeEnum(const QList &types); - ~DirectShowMediaTypeEnum(); - - // DirectShowObject - HRESULT getInterface(REFIID riid, void **ppvObject); - - // IEnumMediaTypes - STDMETHODIMP Next(ULONG cMediaTypes, AM_MEDIA_TYPE **ppMediaTypes, ULONG *pcFetched); - STDMETHODIMP Skip(ULONG cMediaTypes); - STDMETHODIMP Reset(); - STDMETHODIMP Clone(IEnumMediaTypes **ppEnum); - -private: - Q_DISABLE_COPY(DirectShowMediaTypeEnum) - - DirectShowPin *m_pin; - QList m_mediaTypes; - int m_index; -}; - -QT_END_NAMESPACE - -#endif // DIRECTSHOWMEDIATYPEENUM_H diff --git a/src/plugins/directshow/helpers/directshowobject.cpp b/src/plugins/directshow/helpers/directshowobject.cpp deleted file mode 100644 index db1817a8d..000000000 --- a/src/plugins/directshow/helpers/directshowobject.cpp +++ /dev/null @@ -1,86 +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 "directshowobject.h" - -QT_BEGIN_NAMESPACE - -DirectShowObject::DirectShowObject() - : m_ref(1) -{ -} - -DirectShowObject::~DirectShowObject() -{ - Q_ASSERT(m_ref == 0); -} - -HRESULT DirectShowObject::getInterface(const IID &riid, void **ppvObject) -{ - Q_UNUSED(riid) - *ppvObject = NULL; - return E_NOINTERFACE; -} - -ULONG DirectShowObject::ref() -{ - return InterlockedIncrement(&m_ref); -} - -ULONG DirectShowObject::unref() -{ - ULONG ref = InterlockedDecrement(&m_ref); - if (ref == 0) - delete this; - - return ref; -} - -HRESULT GetInterface(IUnknown *pUnk, void **ppv) -{ - if (!ppv) - return E_POINTER; - - *ppv = pUnk; - pUnk->AddRef(); - - return S_OK; -} - -QT_END_NAMESPACE diff --git a/src/plugins/directshow/helpers/directshowobject.h b/src/plugins/directshow/helpers/directshowobject.h deleted file mode 100644 index cfac16f61..000000000 --- a/src/plugins/directshow/helpers/directshowobject.h +++ /dev/null @@ -1,82 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 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 DIRECTSHOWOBJECT_H -#define DIRECTSHOWOBJECT_H - -#include "directshowglobal.h" - -QT_BEGIN_NAMESPACE - -class DirectShowObject -{ -public: - DirectShowObject(); - virtual ~DirectShowObject(); - - virtual HRESULT getInterface(REFIID riid, void **ppvObject); - ULONG ref(); - ULONG unref(); - -private: - Q_DISABLE_COPY(DirectShowObject) - - volatile LONG m_ref; -}; - -HRESULT GetInterface(IUnknown *pUnk, void **ppv); - -#define DIRECTSHOW_OBJECT \ -public: \ - STDMETHODIMP QueryInterface(REFIID riid, void **ppv) { \ - if (riid == IID_IUnknown) \ - return GetInterface(reinterpret_cast(this), ppv); \ - else \ - return getInterface(riid, ppv); \ - }; \ - STDMETHODIMP_(ULONG) AddRef() { \ - return ref(); \ - }; \ - STDMETHODIMP_(ULONG) Release() { \ - return unref(); \ - }; - -QT_END_NAMESPACE - -#endif // DIRECTSHOWOBJECT_H diff --git a/src/plugins/directshow/helpers/directshowpin.cpp b/src/plugins/directshow/helpers/directshowpin.cpp deleted file mode 100644 index b49c3f8a4..000000000 --- a/src/plugins/directshow/helpers/directshowpin.cpp +++ /dev/null @@ -1,740 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 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 "directshowpin.h" - -#include "directshowmediatype.h" -#include "directshowbasefilter.h" -#include "directshowmediatypeenum.h" - -#include - -QT_BEGIN_NAMESPACE - -DirectShowPin::DirectShowPin(DirectShowBaseFilter *filter, const QString &name, PIN_DIRECTION direction) - : m_mutex(QMutex::Recursive) - , m_filter(filter) - , m_name(name) - , m_direction(direction) - , m_peerPin(NULL) -{ -} - -DirectShowPin::~DirectShowPin() -{ - -} - -HRESULT DirectShowPin::getInterface(const IID &riid, void **ppvObject) -{ - if (riid == IID_IPin) - return GetInterface(static_cast(this), ppvObject); - else - return DirectShowObject::getInterface(riid, ppvObject); -} - - - -HRESULT DirectShowPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt) -{ - if (!pReceivePin) - return E_POINTER; - - HRESULT hr = E_FAIL; - QMutexLocker locker(&m_mutex); - - if (m_peerPin) - return VFW_E_ALREADY_CONNECTED; - if (m_filter->state() != State_Stopped) - return VFW_E_NOT_STOPPED; - - PIN_DIRECTION pd; - pReceivePin->QueryDirection(&pd); - if (pd == m_direction) - return VFW_E_INVALID_DIRECTION; - - if (pmt != NULL && DirectShowMediaType::isPartiallySpecified(pmt)) { - // If the type is fully specified, use it - hr = tryConnect(pReceivePin, pmt); - } else { - IEnumMediaTypes *enumMediaTypes = NULL; - - // First, try the receiving pin's preferred types - if (SUCCEEDED(pReceivePin->EnumMediaTypes(&enumMediaTypes))) { - hr = tryMediaTypes(pReceivePin, pmt, enumMediaTypes); - enumMediaTypes->Release(); - } - // Then, try this pin's preferred types - if (FAILED(hr) && SUCCEEDED(EnumMediaTypes(&enumMediaTypes))) { - hr = tryMediaTypes(pReceivePin, pmt, enumMediaTypes); - enumMediaTypes->Release(); - } - } - - if (FAILED(hr)) { - return ((hr != E_FAIL) && (hr != E_INVALIDARG) && (hr != VFW_E_TYPE_NOT_ACCEPTED)) - ? hr : VFW_E_NO_ACCEPTABLE_TYPES; - } - - return S_OK; -} - -HRESULT DirectShowPin::tryMediaTypes(IPin *pin, const AM_MEDIA_TYPE *partialType, IEnumMediaTypes *enumMediaTypes) -{ - HRESULT hr = enumMediaTypes->Reset(); - if (FAILED(hr)) - return hr; - - AM_MEDIA_TYPE *mediaType = NULL; - ULONG mediaCount = 0; - HRESULT hrFailure = VFW_E_NO_ACCEPTABLE_TYPES; - - for (; enumMediaTypes->Next(1, &mediaType, &mediaCount) == S_OK;) { - - if (mediaType && (partialType == NULL || DirectShowMediaType::isCompatible(mediaType, partialType))) { - hr = tryConnect(pin, mediaType); - - if (FAILED(hr) && (hr != E_FAIL) - && (hr != E_INVALIDARG) - && (hr != VFW_E_TYPE_NOT_ACCEPTED)) { - hrFailure = hr; - } - } - - if (mediaType) - DirectShowMediaType::deleteType(mediaType); - - if (SUCCEEDED(hr)) - return S_OK; - } - - return hrFailure; -} - -HRESULT DirectShowPin::tryConnect(IPin *pin, const AM_MEDIA_TYPE *type) -{ - if (!isMediaTypeSupported(type)) - return VFW_E_TYPE_NOT_ACCEPTED; - - m_peerPin = pin; - m_peerPin->AddRef(); - - HRESULT hr; - if (!setMediaType(type)) { - hr = VFW_E_TYPE_NOT_ACCEPTED; - } else { - hr = pin->ReceiveConnection(this, type); - if (SUCCEEDED(hr)) { - hr = completeConnection(pin); - if (FAILED(hr)) - pin->Disconnect(); - } - } - - if (FAILED(hr)) { - connectionEnded(); - m_peerPin->Release(); - m_peerPin = NULL; - setMediaType(NULL); - return hr; - } - - return S_OK; -} - -HRESULT DirectShowPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt) -{ - if (!pConnector || !pmt) - return E_POINTER; - - QMutexLocker locker(&m_mutex); - - if (m_peerPin) - return VFW_E_ALREADY_CONNECTED; - if (m_filter->state() != State_Stopped) - return VFW_E_NOT_STOPPED; - - PIN_DIRECTION pd; - pConnector->QueryDirection(&pd); - if (pd == m_direction) - return VFW_E_INVALID_DIRECTION; - - if (!isMediaTypeSupported(pmt)) - return VFW_E_TYPE_NOT_ACCEPTED; - - m_peerPin = pConnector; - m_peerPin->AddRef(); - - HRESULT hr; - if (!setMediaType(pmt)) - hr = VFW_E_TYPE_NOT_ACCEPTED; - else - hr = completeConnection(pConnector); - - if (FAILED(hr)) { - connectionEnded(); - m_peerPin->Release(); - m_peerPin = NULL; - setMediaType(NULL); - return hr; - } - - return S_OK; -} - -HRESULT DirectShowPin::Disconnect() -{ - QMutexLocker locker(&m_mutex); - - if (m_filter->state() != State_Stopped) - return VFW_E_NOT_STOPPED; - - if (m_peerPin) { - HRESULT hr = connectionEnded(); - if (FAILED(hr)) - return hr; - - m_peerPin->Release(); - m_peerPin = NULL; - - setMediaType(NULL); - - return S_OK; - } - - return S_FALSE; -} - -HRESULT DirectShowPin::ConnectedTo(IPin **ppPin) -{ - if (!ppPin) { - return E_POINTER; - } else { - QMutexLocker locker(&m_mutex); - - if (!m_peerPin) { - *ppPin = 0; - return VFW_E_NOT_CONNECTED; - } else { - m_peerPin->AddRef(); - *ppPin = m_peerPin; - return S_OK; - } - } -} - -HRESULT DirectShowPin::ConnectionMediaType(AM_MEDIA_TYPE *pmt) -{ - if (!pmt) { - return E_POINTER; - } else { - QMutexLocker locker(&m_mutex); - - if (!m_peerPin) { - DirectShowMediaType::init(pmt); - return VFW_E_NOT_CONNECTED; - } else { - DirectShowMediaType::copy(pmt, &m_mediaType); - return S_OK; - } - } -} - -HRESULT DirectShowPin::QueryPinInfo(PIN_INFO *pInfo) -{ - if (!pInfo) { - return E_POINTER; - } else { - pInfo->pFilter = m_filter; - if (m_filter) { - m_filter->AddRef(); - } - pInfo->dir = m_direction; - - QString name = m_name; - if (name.length() >= MAX_PIN_NAME) - name.truncate(MAX_PIN_NAME - 1); - int length = name.toWCharArray(pInfo->achName); - pInfo->achName[length] = '\0'; - - return S_OK; - } -} - -HRESULT DirectShowPin::QueryId(LPWSTR *Id) -{ - if (!Id) { - return E_POINTER; - } else { - const int bytes = (m_name.length() + 1) * 2; - *Id = static_cast(::CoTaskMemAlloc(bytes)); - ::memcpy(*Id, m_name.utf16(), bytes); - return S_OK; - } -} - -HRESULT DirectShowPin::QueryAccept(const AM_MEDIA_TYPE *pmt) -{ - if (!pmt) - return E_POINTER; - - if (!isMediaTypeSupported(pmt)) - return S_FALSE; - - return S_OK; -} - -HRESULT DirectShowPin::EnumMediaTypes(IEnumMediaTypes **ppEnum) -{ - if (!ppEnum) { - return E_POINTER; - } else { - *ppEnum = new DirectShowMediaTypeEnum(this); - return S_OK; - } -} - -HRESULT DirectShowPin::QueryInternalConnections(IPin **apPin, ULONG *nPin) -{ - Q_UNUSED(apPin); - Q_UNUSED(nPin); - return E_NOTIMPL; -} - -HRESULT DirectShowPin::EndOfStream() -{ - return S_OK; -} - -HRESULT DirectShowPin::BeginFlush() -{ - return E_UNEXPECTED; -} - -HRESULT DirectShowPin::EndFlush() -{ - return E_UNEXPECTED; -} - -HRESULT DirectShowPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate) -{ - Q_UNUSED(tStart); - Q_UNUSED(tStop); - Q_UNUSED(dRate); - return S_OK; -} - -HRESULT DirectShowPin::QueryDirection(PIN_DIRECTION *pPinDir) -{ - if (!pPinDir) { - return E_POINTER; - } else { - *pPinDir = m_direction; - return S_OK; - } -} - -QList DirectShowPin::supportedMediaTypes() -{ - return QList(); -} - -bool DirectShowPin::setMediaType(const AM_MEDIA_TYPE *type) -{ - if (!type) - m_mediaType.clear(); - else - DirectShowMediaType::copy(&m_mediaType, type); - - return true; -} - -HRESULT DirectShowPin::completeConnection(IPin *pin) -{ - Q_UNUSED(pin) - return S_OK; -} - -HRESULT DirectShowPin::connectionEnded() -{ - return S_OK; -} - -HRESULT DirectShowPin::setActive(bool active) -{ - Q_UNUSED(active) - return S_OK; -} - - -/* DirectShowOutputPin */ - -DirectShowOutputPin::DirectShowOutputPin(DirectShowBaseFilter *filter, const QString &name) - : DirectShowPin(filter, name, PINDIR_OUTPUT) - , m_allocator(NULL) - , m_inputPin(NULL) -{ - -} - -DirectShowOutputPin::~DirectShowOutputPin() -{ -} - -HRESULT DirectShowOutputPin::completeConnection(IPin *pin) -{ - if (!pin) - return E_POINTER; - - Q_ASSERT(m_inputPin == NULL); - Q_ASSERT(m_allocator == NULL); - - HRESULT hr = pin->QueryInterface(IID_PPV_ARGS(&m_inputPin)); - if (FAILED(hr)) - return hr; - - ALLOCATOR_PROPERTIES prop; - ZeroMemory(&prop, sizeof(prop)); - m_inputPin->GetAllocatorRequirements(&prop); - if (prop.cBuffers <= 0) - prop.cBuffers = 1; - if (prop.cbBuffer <= 0) - prop.cbBuffer = 1; - if (prop.cbAlign <= 0) - prop.cbAlign = 1; - - // Use the connected input pin's allocator if it has one - hr = m_inputPin->GetAllocator(&m_allocator); - if (SUCCEEDED(hr)) { - ALLOCATOR_PROPERTIES actualProperties; - hr = m_allocator->SetProperties(&prop, &actualProperties); - - if (SUCCEEDED(hr)) { - hr = m_inputPin->NotifyAllocator(m_allocator, FALSE); - if (SUCCEEDED(hr)) - return S_OK; - } - - m_allocator->Release(); - m_allocator = NULL; - } - - // Otherwise, allocate its own allocator - m_allocator = com_new(CLSID_MemoryAllocator); - if (!m_allocator) { - hr = E_OUTOFMEMORY; - } else { - ALLOCATOR_PROPERTIES actualProperties; - hr = m_allocator->SetProperties(&prop, &actualProperties); - - if (SUCCEEDED(hr)) { - hr = m_inputPin->NotifyAllocator(m_allocator, FALSE); - if (SUCCEEDED(hr)) - return S_OK; - } - - m_allocator->Release(); - m_allocator = NULL; - } - - return hr; -} - -HRESULT DirectShowOutputPin::connectionEnded() -{ - if (m_allocator) { - HRESULT hr = m_allocator->Decommit(); - if (FAILED(hr)) - return hr; - - m_allocator->Release(); - m_allocator = NULL; - } - - if (m_inputPin) { - m_inputPin->Release(); - m_inputPin = NULL; - } - - return S_OK; -} - -HRESULT DirectShowOutputPin::setActive(bool active) -{ - if (!m_allocator) - return VFW_E_NO_ALLOCATOR; - - return active ? m_allocator->Commit() - : m_allocator->Decommit(); -} - -HRESULT DirectShowOutputPin::EndOfStream() -{ - return E_UNEXPECTED; -} - - -/* DirectShowInputPin */ - -DirectShowInputPin::DirectShowInputPin(DirectShowBaseFilter *filter, const QString &name) - : DirectShowPin(filter, name, PINDIR_INPUT) - , m_allocator(NULL) - , m_flushing(false) - , m_inErrorState(false) -{ - ZeroMemory(&m_sampleProperties, sizeof(m_sampleProperties)); -} - -DirectShowInputPin::~DirectShowInputPin() -{ - -} - -HRESULT DirectShowInputPin::getInterface(const IID &riid, void **ppvObject) -{ - if (riid == IID_IMemInputPin) - return GetInterface(static_cast(this), ppvObject); - else - return DirectShowPin::getInterface(riid, ppvObject); -} - -HRESULT DirectShowInputPin::connectionEnded() -{ - if (m_allocator) { - HRESULT hr = m_allocator->Decommit(); - if (FAILED(hr)) - return hr; - - m_allocator->Release(); - m_allocator = NULL; - } - - return S_OK; -} - -HRESULT DirectShowInputPin::setActive(bool active) -{ - if (!active) { - m_inErrorState = false; - - if (!m_allocator) - return VFW_E_NO_ALLOCATOR; - - m_flushing = false; - return m_allocator->Decommit(); - } - - return S_OK; -} - -HRESULT DirectShowInputPin::EndOfStream() -{ - if (m_filter->state() == State_Stopped) - return VFW_E_WRONG_STATE; - if (m_flushing) - return S_FALSE; - if (m_inErrorState) - return VFW_E_RUNTIME_ERROR; - - return S_OK; -} - -HRESULT DirectShowInputPin::BeginFlush() -{ - QMutexLocker locker(&m_mutex); - m_flushing = true; - return S_OK; -} - -HRESULT DirectShowInputPin::EndFlush() -{ - QMutexLocker locker(&m_mutex); - m_flushing = false; - m_inErrorState = false; - return S_OK; -} - -HRESULT DirectShowInputPin::GetAllocator(IMemAllocator **ppAllocator) -{ - if (!ppAllocator) - return E_POINTER; - - QMutexLocker locker(&m_mutex); - - if (!m_allocator) { - m_allocator = com_new(CLSID_MemoryAllocator);; - if (!m_allocator) - return E_OUTOFMEMORY; - } - - *ppAllocator = m_allocator; - m_allocator->AddRef(); - - return S_OK; -} - -HRESULT DirectShowInputPin::NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly) -{ - Q_UNUSED(bReadOnly) - - if (!pAllocator) - return E_POINTER; - - QMutexLocker locker(&m_mutex); - - if (m_allocator) - m_allocator->Release(); - - m_allocator = pAllocator; - m_allocator->AddRef(); - - return S_OK; -} - -HRESULT DirectShowInputPin::GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps) -{ - Q_UNUSED(pProps) - return E_NOTIMPL; -} - -HRESULT DirectShowInputPin::Receive(IMediaSample *pSample) -{ - if (!pSample) - return E_POINTER; - if (m_filter->state() == State_Stopped) - return VFW_E_WRONG_STATE; - if (m_flushing) - return S_FALSE; - if (m_inErrorState) - return VFW_E_RUNTIME_ERROR; - - HRESULT hr = S_OK; - - IMediaSample2 *sample2; - if (SUCCEEDED(pSample->QueryInterface(IID_PPV_ARGS(&sample2)))) { - hr = sample2->GetProperties(sizeof(m_sampleProperties), (PBYTE)&m_sampleProperties); - sample2->Release(); - if (FAILED(hr)) - return hr; - } else { - m_sampleProperties.cbData = sizeof(m_sampleProperties); - m_sampleProperties.dwTypeSpecificFlags = 0; - m_sampleProperties.dwStreamId = AM_STREAM_MEDIA; - m_sampleProperties.dwSampleFlags = 0; - if (pSample->IsDiscontinuity() == S_OK) - m_sampleProperties.dwSampleFlags |= AM_SAMPLE_DATADISCONTINUITY; - if (pSample->IsPreroll() == S_OK) - m_sampleProperties.dwSampleFlags |= AM_SAMPLE_PREROLL; - if (pSample->IsSyncPoint() == S_OK) - m_sampleProperties.dwSampleFlags |= AM_SAMPLE_SPLICEPOINT; - if (SUCCEEDED(pSample->GetTime(&m_sampleProperties.tStart, - &m_sampleProperties.tStop))) { - m_sampleProperties.dwSampleFlags |= AM_SAMPLE_TIMEVALID | AM_SAMPLE_STOPVALID; - } - if (pSample->GetMediaType(&m_sampleProperties.pMediaType) == S_OK) - m_sampleProperties.dwSampleFlags |= AM_SAMPLE_TYPECHANGED; - pSample->GetPointer(&m_sampleProperties.pbBuffer); - m_sampleProperties.lActual = pSample->GetActualDataLength(); - m_sampleProperties.cbBuffer = pSample->GetSize(); - } - - - if (!(m_sampleProperties.dwSampleFlags & AM_SAMPLE_TYPECHANGED)) - return S_OK; - - if (isMediaTypeSupported(m_sampleProperties.pMediaType)) - return S_OK; - - m_inErrorState = true; - EndOfStream(); - m_filter->NotifyEvent(EC_ERRORABORT, VFW_E_TYPE_NOT_ACCEPTED, 0); - return VFW_E_INVALIDMEDIATYPE; -} - -HRESULT DirectShowInputPin::ReceiveMultiple(IMediaSample **pSamples, long nSamples, long *nSamplesProcessed) -{ - if (!pSamples || !nSamplesProcessed) - return E_POINTER; - - HRESULT hr = S_OK; - *nSamplesProcessed = 0; - while (nSamples-- > 0) { - hr = Receive(pSamples[*nSamplesProcessed]); - if (hr != S_OK) - break; - (*nSamplesProcessed)++; - } - return hr; -} - -HRESULT DirectShowInputPin::ReceiveCanBlock() -{ - int outputPins = 0; - - const QList pinList = m_filter->pins(); - for (DirectShowPin *pin : pinList) { - PIN_DIRECTION pd; - HRESULT hr = pin->QueryDirection(&pd); - if (FAILED(hr)) - return hr; - - if (pd == PINDIR_OUTPUT) { - IPin *connected; - hr = pin->ConnectedTo(&connected); - if (SUCCEEDED(hr)) { - ++outputPins; - IMemInputPin *inputPin; - hr = connected->QueryInterface(IID_PPV_ARGS(&inputPin)); - connected->Release(); - if (SUCCEEDED(hr)) { - hr = inputPin->ReceiveCanBlock(); - inputPin->Release(); - if (hr != S_FALSE) - return S_OK; - } else { - return S_OK; - } - } - } - } - - return outputPins == 0 ? S_OK : S_FALSE; -} - -QT_END_NAMESPACE diff --git a/src/plugins/directshow/helpers/directshowpin.h b/src/plugins/directshow/helpers/directshowpin.h deleted file mode 100644 index 97e808384..000000000 --- a/src/plugins/directshow/helpers/directshowpin.h +++ /dev/null @@ -1,192 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 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 DIRECTSHOWPIN_H -#define DIRECTSHOWPIN_H - -#include "directshowobject.h" - -#include "directshowmediatype.h" -#include -#include - -QT_BEGIN_NAMESPACE - -class DirectShowBaseFilter; - -class DirectShowPin : public DirectShowObject - , public IPin -{ - DIRECTSHOW_OBJECT - -public: - virtual ~DirectShowPin(); - - QString name() const { return m_name; } - bool isConnected() const { return m_peerPin != NULL; } - - virtual bool isMediaTypeSupported(const AM_MEDIA_TYPE *type) = 0; - virtual QList supportedMediaTypes(); - virtual bool setMediaType(const AM_MEDIA_TYPE *type); - - virtual HRESULT completeConnection(IPin *pin); - virtual HRESULT connectionEnded(); - - virtual HRESULT setActive(bool active); - - // DirectShowObject - HRESULT getInterface(REFIID riid, void **ppvObject); - - // IPin - STDMETHODIMP Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt); - STDMETHODIMP ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt); - STDMETHODIMP Disconnect(); - STDMETHODIMP ConnectedTo(IPin **ppPin); - - STDMETHODIMP ConnectionMediaType(AM_MEDIA_TYPE *pmt); - - STDMETHODIMP QueryPinInfo(PIN_INFO *pInfo); - STDMETHODIMP QueryId(LPWSTR *Id); - - STDMETHODIMP QueryAccept(const AM_MEDIA_TYPE *pmt); - - STDMETHODIMP EnumMediaTypes(IEnumMediaTypes **ppEnum); - - STDMETHODIMP QueryInternalConnections(IPin **apPin, ULONG *nPin); - - STDMETHODIMP EndOfStream(); - - STDMETHODIMP BeginFlush(); - STDMETHODIMP EndFlush(); - - STDMETHODIMP NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate); - - STDMETHODIMP QueryDirection(PIN_DIRECTION *pPinDir); - -protected: - DirectShowPin(DirectShowBaseFilter *filter, const QString &name, PIN_DIRECTION direction); - - QMutex m_mutex; - - DirectShowBaseFilter *m_filter; - QString m_name; - PIN_DIRECTION m_direction; - - IPin *m_peerPin; - DirectShowMediaType m_mediaType; - -private: - Q_DISABLE_COPY(DirectShowPin) - HRESULT tryMediaTypes(IPin *pin, const AM_MEDIA_TYPE *type, IEnumMediaTypes *enumMediaTypes); - HRESULT tryConnect(IPin *pin, const AM_MEDIA_TYPE *type); -}; - - -class DirectShowOutputPin : public DirectShowPin -{ - DIRECTSHOW_OBJECT - -public: - virtual ~DirectShowOutputPin(); - - // DirectShowPin - virtual HRESULT completeConnection(IPin *pin); - virtual HRESULT connectionEnded(); - virtual HRESULT setActive(bool active); - - // IPin - STDMETHODIMP EndOfStream(); - -protected: - DirectShowOutputPin(DirectShowBaseFilter *filter, const QString &name); - - IMemAllocator *m_allocator; - IMemInputPin *m_inputPin; - -private: - Q_DISABLE_COPY(DirectShowOutputPin) -}; - - -class DirectShowInputPin : public DirectShowPin - , public IMemInputPin -{ - DIRECTSHOW_OBJECT - -public: - virtual ~DirectShowInputPin(); - - const AM_SAMPLE2_PROPERTIES *currentSampleProperties() const { return &m_sampleProperties; } - - // DirectShowObject - HRESULT getInterface(REFIID riid, void **ppvObject); - - // DirectShowPin - HRESULT connectionEnded(); - HRESULT setActive(bool active); - - // IPin - STDMETHODIMP EndOfStream(); - STDMETHODIMP BeginFlush(); - STDMETHODIMP EndFlush(); - - // IMemInputPin - STDMETHODIMP GetAllocator(IMemAllocator **ppAllocator); - STDMETHODIMP NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly); - STDMETHODIMP GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps); - - STDMETHODIMP Receive(IMediaSample *pSample); - STDMETHODIMP ReceiveMultiple(IMediaSample **pSamples, long nSamples, long *nSamplesProcessed); - STDMETHODIMP ReceiveCanBlock(); - -protected: - DirectShowInputPin(DirectShowBaseFilter *filter, const QString &name); - - IMemAllocator *m_allocator; - bool m_flushing; - bool m_inErrorState; - AM_SAMPLE2_PROPERTIES m_sampleProperties; - -private: - Q_DISABLE_COPY(DirectShowInputPin) -}; - -QT_END_NAMESPACE - -#endif // DIRECTSHOWPIN_H diff --git a/src/plugins/directshow/helpers/directshowpinenum.cpp b/src/plugins/directshow/helpers/directshowpinenum.cpp deleted file mode 100644 index 910bba77d..000000000 --- a/src/plugins/directshow/helpers/directshowpinenum.cpp +++ /dev/null @@ -1,130 +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" -#include "directshowbasefilter.h" - -QT_BEGIN_NAMESPACE - -DirectShowPinEnum::DirectShowPinEnum(DirectShowBaseFilter *filter) - : m_filter(filter) - , m_index(0) -{ - m_filter->AddRef(); - const QList pinList = filter->pins(); - for (DirectShowPin *pin : pinList) { - pin->AddRef(); - m_pins.append(pin); - } -} - -DirectShowPinEnum::DirectShowPinEnum(const QList &pins) - : m_filter(NULL) - , m_pins(pins) - , m_index(0) -{ - for (IPin *pin : qAsConst(m_pins)) - pin->AddRef(); -} - -DirectShowPinEnum::~DirectShowPinEnum() -{ - for (IPin *pin : qAsConst(m_pins)) - pin->Release(); - if (m_filter) - m_filter->Release(); -} - -HRESULT DirectShowPinEnum::getInterface(REFIID riid, void **ppvObject) -{ - if (riid == IID_IEnumPins) { - return GetInterface(static_cast(this), ppvObject); - } else { - return DirectShowObject::getInterface(riid, ppvObject); - } -} - -HRESULT DirectShowPinEnum::Next(ULONG cPins, IPin **ppPins, ULONG *pcFetched) -{ - if (ppPins && (pcFetched || cPins == 1)) { - ULONG count = qBound(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) { - if (m_filter) - *ppEnum = new DirectShowPinEnum(m_filter); - else - *ppEnum = new DirectShowPinEnum(m_pins); - - return S_OK; - } else { - return E_POINTER; - } -} - -QT_END_NAMESPACE diff --git a/src/plugins/directshow/helpers/directshowpinenum.h b/src/plugins/directshow/helpers/directshowpinenum.h deleted file mode 100644 index 77214e376..000000000 --- a/src/plugins/directshow/helpers/directshowpinenum.h +++ /dev/null @@ -1,81 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt 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 - -#include -#include "directshowpin.h" - -QT_BEGIN_NAMESPACE - -class DirectShowBaseFilter; - -class DirectShowPinEnum : public DirectShowObject - , public IEnumPins -{ - DIRECTSHOW_OBJECT - -public: - DirectShowPinEnum(DirectShowBaseFilter *filter); - DirectShowPinEnum(const QList &pins); - ~DirectShowPinEnum(); - - // DirectShowObject - HRESULT getInterface(REFIID riid, void **ppvObject); - - // IEnumPins - STDMETHODIMP Next(ULONG cPins, IPin **ppPins, ULONG *pcFetched); - STDMETHODIMP Skip(ULONG cPins); - STDMETHODIMP Reset(); - STDMETHODIMP Clone(IEnumPins **ppEnum); - -private: - Q_DISABLE_COPY(DirectShowPinEnum) - - DirectShowBaseFilter *m_filter; - QList m_pins; - int m_index; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/plugins/directshow/helpers/directshowutils.cpp b/src/plugins/directshow/helpers/directshowutils.cpp deleted file mode 100644 index 96fabd6da..000000000 --- a/src/plugins/directshow/helpers/directshowutils.cpp +++ /dev/null @@ -1,313 +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 "directshowutils.h" - -QT_BEGIN_NAMESPACE - -/** - * @brief DirectShowUtils::isPinConnected - * @param pin - * @param hrOut - * @return - */ -bool DirectShowUtils::isPinConnected(IPin *pin, HRESULT *hrOut) -{ - IPin *connectedPin = nullptr; - const ScopedSafeRelease releasePin { &connectedPin }; - HRESULT hr = S_OK; - if (!hrOut) - hrOut = &hr; - - *hrOut = pin->ConnectedTo(&connectedPin); - if (*hrOut == VFW_E_NOT_CONNECTED) // Not an error in this case - *hrOut = S_OK; - - if (FAILED(*hrOut)) { - qCDebug(qtDirectShowPlugin, "Querying pin connection failed!"); - return false; - } - - return true; -} - -/** - * @brief DirectShowUtils::hasPinDirection - * @param pin - * @param direction - * @param hrOut - * @return - */ -bool DirectShowUtils::hasPinDirection(IPin *pin, PIN_DIRECTION direction, HRESULT *hrOut) -{ - PIN_DIRECTION pinDir; - HRESULT hr = S_OK; - if (!hrOut) - hrOut = &hr; - - *hrOut = pin->QueryDirection(&pinDir); - - if (FAILED(*hrOut)) { - qCDebug(qtDirectShowPlugin, "Querying pin direction failed!"); - return false; - } - - return (pinDir == direction); -} - -/** - * @brief DirectShowUtils::getPin - * @param filter - * @param pinDirection - * @param pin - * @param hrOut - * @return - */ -bool DirectShowUtils::getPin(IBaseFilter *filter, PIN_DIRECTION pinDirection, IPin **pin, HRESULT *hrOut) -{ - IEnumPins *enumPins = nullptr; - const ScopedSafeRelease releaseEnumPins { &enumPins }; - HRESULT hr S_OK; - if (!hrOut) - hrOut = &hr; - - *hrOut = filter->EnumPins(&enumPins); - if (FAILED(*hrOut)) { - qCDebug(qtDirectShowPlugin, "Unable to retrieve pins from the filter!"); - return false; - } - - enumPins->Reset(); - IPin *nextPin = nullptr; - while (enumPins->Next(1, &nextPin, NULL) == S_OK) { - const ScopedSafeRelease releasePin { &nextPin }; - PIN_DIRECTION currentPinDir; - *hrOut = nextPin->QueryDirection(¤tPinDir); - if (currentPinDir == pinDirection) { - *pin = nextPin; - (*pin)->AddRef(); - return true; - } - } - - return false; -} - -/** - * @brief DirectShowUtils::matchPin - * @param pin - * @param pinDirection - * @param shouldBeConnected - * @param hrOut - * @return - */ -bool DirectShowUtils::matchPin(IPin *pin, PIN_DIRECTION pinDirection, BOOL shouldBeConnected, HRESULT *hrOut) -{ - HRESULT hr = S_OK; - if (!hrOut) - hrOut = &hr; - - const BOOL isConnected = isPinConnected(pin, hrOut); - if (FAILED(*hrOut)) // Error reason will already be logged, so just return. - return false; - - if (isConnected == shouldBeConnected) - return hasPinDirection(pin, pinDirection, hrOut); - - return SUCCEEDED(*hrOut); -} - -/** - * @brief DirectShowUtils::findUnconnectedPin - * @param filter - * @param pinDirection - * @param pin - * @param hrOut - * @return - */ -bool DirectShowUtils::findUnconnectedPin(IBaseFilter *filter, PIN_DIRECTION pinDirection, IPin **pin, HRESULT *hrOut) -{ - HRESULT hr = S_OK; - if (!hrOut) - hrOut = &hr; - - IEnumPins *enumPins = nullptr; - const ScopedSafeRelease releaseEnumPins { &enumPins }; - *hrOut = filter->EnumPins(&enumPins); - if (FAILED(*hrOut)) { - qCDebug(qtDirectShowPlugin, "Unable to retrieve pins from the DS filter"); - return false; - } - - IPin *nextPin = nullptr; - while (S_OK == enumPins->Next(1, &nextPin, nullptr)) { - const ScopedSafeRelease releaseNextPin { &nextPin }; - if (matchPin(nextPin, pinDirection, FALSE, hrOut)) { - *pin = nextPin; - (*pin)->AddRef(); - return true; - } - - if (FAILED(*hrOut)) - return false; - } - - qCDebug(qtDirectShowPlugin, "No unconnected pins found"); - *hrOut = VFW_E_NOT_FOUND; - - return false; -} - -/** - * @brief DirectShowUtils::connectFilters - Attempts to connect \a outputPin to \a filter - * @param graph - * @param outputPin - * @param filter - * @param hrOut - * @return - */ -bool DirectShowUtils::connectFilters(IGraphBuilder *graph, IPin *outputPin, IBaseFilter *filter, HRESULT *hrOut) -{ - - // Find an input pin on the downstream filter. - HRESULT hr = S_OK; - if (!hrOut) - hrOut = &hr; - - IPin *inputPin = nullptr; - const ScopedSafeRelease releaseInputPin { &inputPin }; - if (!findUnconnectedPin(filter, PINDIR_INPUT, &inputPin, hrOut)) - return false; - - - // Try to connect them. - *hrOut = graph->Connect(outputPin, inputPin); - if (FAILED(*hrOut)) { - qCDebug(qtDirectShowPlugin, "Unable to connect output pin to filter!"); - return false; - } - - return true; -} - -/** - * @brief DirectShowUtils::connectFilters - Attempts to connect \a filter to \a inputPin. - * @param graph - * @param filter - * @param inputPin - * @param hrOut - * @return - */ -bool DirectShowUtils::connectFilters(IGraphBuilder *graph, IBaseFilter *filter, IPin *inputPin, HRESULT *hrOut) -{ - HRESULT hr = S_OK; - if (!hrOut) - hrOut = &hr; - - IPin *outputPin = nullptr; - const ScopedSafeRelease releaseOutputPin { &outputPin }; - // Find an output pin on the upstream filter. - if (findUnconnectedPin(filter, PINDIR_OUTPUT, &outputPin, hrOut)) - return false; - - *hrOut = graph->Connect(outputPin, inputPin); - if (FAILED(*hrOut)) { - qCDebug(qtDirectShowPlugin, "Unable to connect filter to input pin!"); - return false; - } - - return true; -} - -/** - * @brief DirectShowUtils::connectFilters - Attempts to connect the \a upstreamFilter to \a downstreamFilter. - * @param graph - * @param upstreamFilter - * @param downstreamFilter - * @param autoConnect - If set to true all filters in the graph will be considered. - * @param hrOut - * @return true if the the filters were connected, false otherwise. - */ -bool DirectShowUtils::connectFilters(IGraphBuilder *graph, - IBaseFilter *upstreamFilter, - IBaseFilter *downstreamFilter, - bool autoConnect, - HRESULT *hrOut) -{ - HRESULT hr = S_OK; - if (!hrOut) - hrOut = &hr; - - const auto findAndConnect = [graph, downstreamFilter, hrOut](IBaseFilter *filter) -> bool { - IPin *outputPin = nullptr; - const ScopedSafeRelease releaseOutputPin { &outputPin }; - if (findUnconnectedPin(filter, PINDIR_OUTPUT, &outputPin, hrOut)) - return connectFilters(graph, outputPin, downstreamFilter, hrOut); - - return false; - }; - - // Try to connect to the upstream filter first. - if (findAndConnect(upstreamFilter)) - return S_OK; - - const auto getFilters = [graph, hrOut]() -> IEnumFilters * { - IEnumFilters *f = nullptr; - *hrOut = graph->EnumFilters(&f); - return f; - }; - IEnumFilters *filters = autoConnect ? getFilters() - : nullptr; - const ScopedSafeRelease releaseEnumFilters { &filters }; - if (!filters) { - qCDebug(qtDirectShowPlugin, "No filters found!"); - return false; - } - - IBaseFilter *nextFilter = nullptr; - while (S_OK == filters->Next(1, &nextFilter, 0)) { - const ScopedSafeRelease releaseNextFilter { &nextFilter }; - if (nextFilter && findAndConnect(nextFilter)) - break; - } - - return SUCCEEDED(*hrOut); -} - -QT_END_NAMESPACE diff --git a/src/plugins/directshow/helpers/directshowutils.h b/src/plugins/directshow/helpers/directshowutils.h deleted file mode 100644 index 09c81c257..000000000 --- a/src/plugins/directshow/helpers/directshowutils.h +++ /dev/null @@ -1,87 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt 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 DIRECTSHOWUTILS_H -#define DIRECTSHOWUTILS_H - -#include "directshowglobal.h" - -QT_BEGIN_NAMESPACE - -namespace DirectShowUtils -{ -template -void safeRelease(T **iface) { - if (!iface) - return; - - if (!*iface) - return; - - (*iface)->Release(); - *iface = nullptr; -} - -template -struct ScopedSafeRelease -{ - T **iunknown; - ~ScopedSafeRelease() - { - DirectShowUtils::safeRelease(iunknown); - } -}; - -bool getPin(IBaseFilter *filter, PIN_DIRECTION pinDirection, IPin **pin, HRESULT *hrOut); -bool isPinConnected(IPin *pin, HRESULT *hrOut = nullptr); -bool hasPinDirection(IPin *pin, PIN_DIRECTION direction, HRESULT *hrOut = nullptr); -bool matchPin(IPin *pin, PIN_DIRECTION pinDirection, BOOL shouldBeConnected, HRESULT *hrOut = nullptr); -bool findUnconnectedPin(IBaseFilter *filter, PIN_DIRECTION pinDirection, IPin **pin, HRESULT *hrOut = nullptr); -bool connectFilters(IGraphBuilder *graph, IPin *outputPin, IBaseFilter *filter, HRESULT *hrOut = nullptr); -bool connectFilters(IGraphBuilder *graph, IBaseFilter *filter, IPin *inputPin, HRESULT *hrOut = nullptr); -bool connectFilters(IGraphBuilder *graph, - IBaseFilter *upstreamFilter, - IBaseFilter *downstreamFilter, - bool autoConnect = false, - HRESULT *hrOut = nullptr); -} - -QT_END_NAMESPACE - -#endif // DIRECTSHOWUTILS_H diff --git a/src/plugins/directshow/helpers/directshowvideobuffer.cpp b/src/plugins/directshow/helpers/directshowvideobuffer.cpp deleted file mode 100644 index 7f94da97e..000000000 --- a/src/plugins/directshow/helpers/directshowvideobuffer.cpp +++ /dev/null @@ -1,88 +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 "directshowvideobuffer.h" - -QT_BEGIN_NAMESPACE - -DirectShowVideoBuffer::DirectShowVideoBuffer(IMediaSample *sample, int bytesPerLine) - : QAbstractVideoBuffer(NoHandle) - , m_sample(sample) - , m_bytesPerLine(bytesPerLine) - , m_mapMode(NotMapped) -{ - m_sample->AddRef(); -} - -DirectShowVideoBuffer::~DirectShowVideoBuffer() -{ - m_sample->Release(); -} - -uchar *DirectShowVideoBuffer::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(bytes); - } - } - return 0; -} - -void DirectShowVideoBuffer::unmap() -{ - m_mapMode = NotMapped; -} - -QAbstractVideoBuffer::MapMode DirectShowVideoBuffer::mapMode() const -{ - return m_mapMode; -} - -QT_END_NAMESPACE diff --git a/src/plugins/directshow/helpers/directshowvideobuffer.h b/src/plugins/directshow/helpers/directshowvideobuffer.h deleted file mode 100644 index 85e02b53d..000000000 --- a/src/plugins/directshow/helpers/directshowvideobuffer.h +++ /dev/null @@ -1,70 +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 DIRECTSHOWVIDEOBUFFER_H -#define DIRECTSHOWVIDEOBUFFER_H - -#include - -#include - -QT_BEGIN_NAMESPACE - -class DirectShowVideoBuffer : public QAbstractVideoBuffer -{ -public: - DirectShowVideoBuffer(IMediaSample *sample, int bytesPerLine); - ~DirectShowVideoBuffer(); - - 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; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/plugins/directshow/helpers/helpers.pri b/src/plugins/directshow/helpers/helpers.pri deleted file mode 100644 index ca883eeb8..000000000 --- a/src/plugins/directshow/helpers/helpers.pri +++ /dev/null @@ -1,24 +0,0 @@ -INCLUDEPATH += $$PWD - -HEADERS += \ - $$PWD/directshowbasefilter.h \ - $$PWD/directshoweventloop.h \ - $$PWD/directshowglobal.h \ - $$PWD/directshowmediatype.h \ - $$PWD/directshowmediatypeenum.h \ - $$PWD/directshowobject.h \ - $$PWD/directshowpin.h \ - $$PWD/directshowpinenum.h \ - $$PWD/directshowvideobuffer.h \ - $$PWD/directshowutils.h - -SOURCES += \ - $$PWD/directshowbasefilter.cpp \ - $$PWD/directshoweventloop.cpp \ - $$PWD/directshowmediatype.cpp \ - $$PWD/directshowmediatypeenum.cpp \ - $$PWD/directshowobject.cpp \ - $$PWD/directshowpin.cpp \ - $$PWD/directshowpinenum.cpp \ - $$PWD/directshowvideobuffer.cpp \ - $$PWD/directshowutils.cpp -- cgit v1.2.3 From 960fbf083be4391314e8fe36994a133763dbbe7d Mon Sep 17 00:00:00 2001 From: Christian Stromme Date: Tue, 22 Nov 2016 18:57:30 +0100 Subject: DirectShow: Expose the camera control interface The interface is needed to implement Qt's camera control classes. Change-Id: I468527dd1f5e9e7a0f8868f0b7addc3c069adf54 Reviewed-by: Yoann Lopes --- src/plugins/directshow/camera/dscamerasession.cpp | 20 ++++++++++++++++++++ src/plugins/directshow/camera/dscamerasession.h | 2 ++ 2 files changed, 22 insertions(+) (limited to 'src') diff --git a/src/plugins/directshow/camera/dscamerasession.cpp b/src/plugins/directshow/camera/dscamerasession.cpp index 40e54a94d..3f1187baa 100644 --- a/src/plugins/directshow/camera/dscamerasession.cpp +++ b/src/plugins/directshow/camera/dscamerasession.cpp @@ -334,6 +334,26 @@ void DSCameraSession::setImageProcessingParameter( } } +bool DSCameraSession::getCameraControlInterface(IAMCameraControl **cameraControl) const +{ + if (!m_sourceFilter) { + qCDebug(qtDirectShowPlugin, "getCameraControlInterface failed: No capture filter!"); + return false; + } + + if (!cameraControl) { + qCDebug(qtDirectShowPlugin, "getCameraControlInterface failed: Invalid out argument!"); + return false; + } + + if (FAILED(m_sourceFilter->QueryInterface(IID_IAMCameraControl, reinterpret_cast(cameraControl)))) { + qCDebug(qtDirectShowPlugin, "getCameraControlInterface failed: Querying camera control failed!"); + return false; + } + + return true; +} + bool DSCameraSession::load() { unload(); diff --git a/src/plugins/directshow/camera/dscamerasession.h b/src/plugins/directshow/camera/dscamerasession.h index 37730736f..6b6cb49b2 100644 --- a/src/plugins/directshow/camera/dscamerasession.h +++ b/src/plugins/directshow/camera/dscamerasession.h @@ -118,6 +118,8 @@ public: QCameraImageProcessingControl::ProcessingParameter, const QVariant &); + bool getCameraControlInterface(IAMCameraControl **cameraControl) const; + Q_SIGNALS: void statusChanged(QCamera::Status); void imageExposed(int id); -- cgit v1.2.3 From 6c18b2085e9d738b48a5bec3bdc9c96db2e7e4d7 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 9 Feb 2017 15:50:20 +0100 Subject: de-duplicate gstreamer_encodingprofiles configure tests take advantage of the system now supporting 'use' by exported name. Change-Id: I7879d4c2e31b279bbbe17916e805ee60c108351d Reviewed-by: Jake Petroules --- src/multimedia/configure.json | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/multimedia/configure.json b/src/multimedia/configure.json index 4f0532ad4..e250f2b9a 100644 --- a/src/multimedia/configure.json +++ b/src/multimedia/configure.json @@ -137,16 +137,10 @@ "type": "compile", "test": "evr" }, - "gstreamer_encodingprofiles_1_0": { - "label": "GStreamer encoding-profile.h", - "type": "compile", - "use": "gstreamer_1_0", - "test": "gstreamer_encodingprofiles" - }, - "gstreamer_encodingprofiles_0_10": { + "gstreamer_encodingprofiles": { "label": "GStreamer encoding-profile.h", "type": "compile", - "use": "gstreamer_0_10", + "use": "gstreamer", "test": "gstreamer_encodingprofiles" }, "gpu_vivante": { @@ -230,7 +224,7 @@ }, "gstreamer_encodingprofiles": { "label": "GStreamer encoding-profile.h", - "condition": "(features.gstreamer_1_0 && tests.gstreamer_encodingprofiles_1_0) || (features.gstreamer_0_10 && tests.gstreamer_encodingprofiles_0_10)", + "condition": "features.gstreamer && tests.gstreamer_encodingprofiles", "output": [ "privateFeature" ] }, "gstreamer_photography": { -- cgit v1.2.3 From 18010674c34fcda241e7c9e436c4dd06edc1e361 Mon Sep 17 00:00:00 2001 From: Stephan Binner Date: Wed, 19 Apr 2017 16:10:33 +0200 Subject: Fix build for -no-feature-temporaryfile If a backend does not support streaming then playing from qrc is impossible for -no-feature-temporaryfile case. Change-Id: Ibb0518c4afe0598c6f3a1c03b75cc00e76b8eead Reviewed-by: Oswald Buddenhagen Reviewed-by: Christian Stromme --- src/multimedia/playback/qmediaplayer.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/multimedia/playback/qmediaplayer.cpp b/src/multimedia/playback/qmediaplayer.cpp index c9b9b4fc1..16fdec8ea 100644 --- a/src/multimedia/playback/qmediaplayer.cpp +++ b/src/multimedia/playback/qmediaplayer.cpp @@ -362,6 +362,7 @@ void QMediaPlayerPrivate::setMedia(const QMediaContent &media, QIODevice *stream } else if (hasStreamPlaybackFeature) { control->setMedia(media, file.data()); } else { +#if QT_CONFIG(temporaryfile) QTemporaryFile *tempFile = new QTemporaryFile; // Preserve original file extension, some backends might not load the file if it doesn't @@ -383,6 +384,9 @@ void QMediaPlayerPrivate::setMedia(const QMediaContent &media, QIODevice *stream file.reset(tempFile); control->setMedia(QMediaContent(QUrl::fromLocalFile(file->fileName())), 0); +#else + qWarning("Qt was built with -no-feature-temporaryfile: playback from resource file is not supported!"); +#endif } } else { qrcMedia = QMediaContent(); -- cgit v1.2.3 From 6e3d6bf8322efd609d3a3ed33c5101072176ed5a Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Fri, 5 May 2017 09:32:39 +0200 Subject: Emit the StoppedState change after the file has finished writing Where possible, we should be emitting the stateChanged() signal to StoppedState when we know the file is no longer being written to. The finializing status can be used to indicate it is finishing and when it is actually finished then StoppedState should be used. Task-number: QTBUG-50588 Change-Id: Ie3ac1c5cd00a6a36978e72b5485622e3302054ce Reviewed-by: Christian Stromme --- src/multimedia/recording/qmediarecorder.cpp | 4 ++++ src/plugins/avfoundation/camera/avfmediarecordercontrol.mm | 10 ++++++++-- src/plugins/avfoundation/camera/avfmediarecordercontrol_ios.mm | 8 ++++---- 3 files changed, 16 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/multimedia/recording/qmediarecorder.cpp b/src/multimedia/recording/qmediarecorder.cpp index d3962b78f..3bab3dada 100644 --- a/src/multimedia/recording/qmediarecorder.cpp +++ b/src/multimedia/recording/qmediarecorder.cpp @@ -909,6 +909,10 @@ void QMediaRecorder::stop() \enum QMediaRecorder::State \value StoppedState The recorder is not active. + If this is the state after recording then the actual created recording has + finished being written to the final location and is ready on all platforms + except on Android. On Android, due to platform limitations, there is no way + to be certain that the recording has finished writing to the final location. \value RecordingState The recording is requested. \value PausedState The recorder is paused. */ diff --git a/src/plugins/avfoundation/camera/avfmediarecordercontrol.mm b/src/plugins/avfoundation/camera/avfmediarecordercontrol.mm index 79bf2e932..02261027d 100644 --- a/src/plugins/avfoundation/camera/avfmediarecordercontrol.mm +++ b/src/plugins/avfoundation/camera/avfmediarecordercontrol.mm @@ -306,14 +306,16 @@ void AVFMediaRecorderControl::setState(QMediaRecorder::State state) } break; case QMediaRecorder::StoppedState: { - m_state = QMediaRecorder::StoppedState; + m_lastStatus = QMediaRecorder::FinalizingStatus; + Q_EMIT statusChanged(m_lastStatus); [m_movieOutput stopRecording]; unapplySettings(); } } updateStatus(); - Q_EMIT stateChanged(m_state); + if (state != m_state) + Q_EMIT stateChanged(m_state); } void AVFMediaRecorderControl::setMuted(bool muted) @@ -341,6 +343,10 @@ void AVFMediaRecorderControl::handleRecordingStarted() void AVFMediaRecorderControl::handleRecordingFinished() { m_recordingFinished = true; + if (m_state != QMediaRecorder::StoppedState) { + m_state = QMediaRecorder::StoppedState; + Q_EMIT stateChanged(m_state); + } updateStatus(); } diff --git a/src/plugins/avfoundation/camera/avfmediarecordercontrol_ios.mm b/src/plugins/avfoundation/camera/avfmediarecordercontrol_ios.mm index 5f604e9a0..d657dc17d 100644 --- a/src/plugins/avfoundation/camera/avfmediarecordercontrol_ios.mm +++ b/src/plugins/avfoundation/camera/avfmediarecordercontrol_ios.mm @@ -340,7 +340,7 @@ void AVFMediaRecorderControlIOS::assetWriterFinished() Q_ASSERT(cameraControl); const QMediaRecorder::Status lastStatus = m_lastStatus; - + const QMediaRecorder::State lastState = m_state; if (cameraControl->captureMode() & QCamera::CaptureVideo) m_lastStatus = QMediaRecorder::LoadedStatus; else @@ -350,9 +350,11 @@ void AVFMediaRecorderControlIOS::assetWriterFinished() m_service->videoOutput()->resetCaptureDelegate(); [m_service->session()->captureSession() startRunning]; - + m_state = QMediaRecorder::StoppedState; if (m_lastStatus != lastStatus) Q_EMIT statusChanged(m_lastStatus); + if (m_state != lastState) + Q_EMIT stateChanged(m_state); } void AVFMediaRecorderControlIOS::captureModeChanged(QCamera::CaptureModes newMode) @@ -403,10 +405,8 @@ void AVFMediaRecorderControlIOS::cameraStatusChanged(QCamera::Status newStatus) void AVFMediaRecorderControlIOS::stopWriter() { if (m_lastStatus == QMediaRecorder::RecordingStatus) { - m_state = QMediaRecorder::StoppedState; m_lastStatus = QMediaRecorder::FinalizingStatus; - Q_EMIT stateChanged(m_state); Q_EMIT statusChanged(m_lastStatus); [m_writer stop]; -- cgit v1.2.3