summaryrefslogtreecommitdiffstats
path: root/src/plugins/directshow
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/directshow')
-rw-r--r--src/plugins/directshow/camera/directshowcameraglobal.h3
-rw-r--r--src/plugins/directshow/camera/dscamerasession.cpp290
-rw-r--r--src/plugins/directshow/camera/dscamerasession.h13
-rw-r--r--src/plugins/directshow/common/common.pri11
-rw-r--r--src/plugins/directshow/common/directshowaudioprobecontrol.cpp57
-rw-r--r--src/plugins/directshow/common/directshowaudioprobecontrol.h64
-rw-r--r--src/plugins/directshow/common/directshowsamplegrabber.cpp196
-rw-r--r--src/plugins/directshow/common/directshowsamplegrabber.h89
-rw-r--r--src/plugins/directshow/common/directshowvideoprobecontrol.cpp57
-rw-r--r--src/plugins/directshow/common/directshowvideoprobecontrol.h64
-rw-r--r--src/plugins/directshow/directshow.pro1
-rw-r--r--src/plugins/directshow/dsserviceplugin.cpp5
-rw-r--r--src/plugins/directshow/helpers/directshowglobal.h10
-rw-r--r--src/plugins/directshow/helpers/directshowmediatype.cpp198
-rw-r--r--src/plugins/directshow/helpers/directshowmediatype.h45
-rw-r--r--src/plugins/directshow/helpers/directshowmediatypeenum.cpp2
-rw-r--r--src/plugins/directshow/helpers/directshowpin.cpp35
-rw-r--r--src/plugins/directshow/helpers/directshowpin.h8
-rw-r--r--src/plugins/directshow/helpers/directshowutils.cpp309
-rw-r--r--src/plugins/directshow/helpers/directshowutils.h87
-rw-r--r--src/plugins/directshow/helpers/helpers.pri6
-rw-r--r--src/plugins/directshow/player/directshowiosource.cpp12
-rw-r--r--src/plugins/directshow/player/directshowplayercontrol.cpp4
-rw-r--r--src/plugins/directshow/player/directshowplayerservice.cpp6
-rw-r--r--src/plugins/directshow/player/directshowplayerservice.h10
-rw-r--r--src/plugins/directshow/player/videosurfacefilter.cpp16
-rw-r--r--src/plugins/directshow/player/videosurfacefilter.h4
27 files changed, 1211 insertions, 391 deletions
diff --git a/src/plugins/directshow/camera/directshowcameraglobal.h b/src/plugins/directshow/camera/directshowcameraglobal.h
index 75112a090..8df387b4a 100644
--- a/src/plugins/directshow/camera/directshowcameraglobal.h
+++ b/src/plugins/directshow/camera/directshowcameraglobal.h
@@ -44,9 +44,6 @@
#include <dshow.h>
-DEFINE_GUID(MEDIASUBTYPE_I420,
- 0x30323449,0x0000,0x0010,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71);
-
extern const GUID MEDIASUBTYPE_RGB24;
extern const GUID MEDIASUBTYPE_RGB32;
extern const GUID MEDIASUBTYPE_YUY2;
diff --git a/src/plugins/directshow/camera/dscamerasession.cpp b/src/plugins/directshow/camera/dscamerasession.cpp
index 5587b479c..40e54a94d 100644
--- a/src/plugins/directshow/camera/dscamerasession.cpp
+++ b/src/plugins/directshow/camera/dscamerasession.cpp
@@ -47,148 +47,13 @@
#include "dscamerasession.h"
#include "dsvideorenderer.h"
+#include "directshowsamplegrabber.h"
#include "directshowcameraglobal.h"
+#include "directshowmediatype.h"
+#include "directshowutils.h"
QT_BEGIN_NAMESPACE
-
-namespace {
-// DirectShow helper implementation
-void _CopyMediaType(AM_MEDIA_TYPE *pmtTarget, const AM_MEDIA_TYPE *pmtSource)
-{
- *pmtTarget = *pmtSource;
- if (pmtTarget->cbFormat != 0) {
- pmtTarget->pbFormat = reinterpret_cast<BYTE *>(CoTaskMemAlloc(pmtTarget->cbFormat));
- if (pmtTarget->pbFormat)
- memcpy(pmtTarget->pbFormat, pmtSource->pbFormat, pmtTarget->cbFormat);
- }
- if (pmtTarget->pUnk != NULL) {
- // pUnk should not be used.
- pmtTarget->pUnk->AddRef();
- }
-}
-
-void _FreeMediaType(AM_MEDIA_TYPE& mt)
-{
- if (mt.cbFormat != 0) {
- CoTaskMemFree((PVOID)mt.pbFormat);
- mt.cbFormat = 0;
- mt.pbFormat = NULL;
- }
- if (mt.pUnk != NULL) {
- // pUnk should not be used.
- mt.pUnk->Release();
- mt.pUnk = NULL;
- }
-}
-} // end namespace
-
-static HRESULT getPin(IBaseFilter *filter, PIN_DIRECTION pinDir, IPin **pin);
-
-
-class SampleGrabberCallbackPrivate : public ISampleGrabberCB
-{
-public:
- explicit SampleGrabberCallbackPrivate(DSCameraSession *session)
- : m_ref(1)
- , m_session(session)
- { }
-
- virtual ~SampleGrabberCallbackPrivate() { }
-
- STDMETHODIMP_(ULONG) AddRef()
- {
- return InterlockedIncrement(&m_ref);
- }
-
- STDMETHODIMP_(ULONG) Release()
- {
- ULONG ref = InterlockedDecrement(&m_ref);
- if (ref == 0)
- delete this;
- return ref;
- }
-
- STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject)
- {
- if (NULL == ppvObject)
- return E_POINTER;
- if (riid == IID_IUnknown /*__uuidof(IUnknown) */ ) {
- *ppvObject = static_cast<IUnknown*>(this);
- return S_OK;
- }
- if (riid == IID_ISampleGrabberCB /*__uuidof(ISampleGrabberCB)*/ ) {
- *ppvObject = static_cast<ISampleGrabberCB*>(this);
- return S_OK;
- }
- return E_NOTIMPL;
- }
-
- STDMETHODIMP SampleCB(double Time, IMediaSample *pSample)
- {
- Q_UNUSED(Time)
- Q_UNUSED(pSample)
- return E_NOTIMPL;
- }
-
- STDMETHODIMP BufferCB(double time, BYTE *pBuffer, long bufferLen)
- {
- // We display frames as they arrive, the presentation time is
- // irrelevant
- Q_UNUSED(time);
-
- if (m_session) {
- m_session->onFrameAvailable(reinterpret_cast<const char *>(pBuffer),
- bufferLen);
- }
-
- return S_OK;
- }
-
-private:
- ULONG m_ref;
- DSCameraSession *m_session;
-};
-
-QVideoFrame::PixelFormat pixelFormatFromMediaSubtype(GUID uid)
-{
- if (uid == MEDIASUBTYPE_ARGB32)
- return QVideoFrame::Format_ARGB32;
- else if (uid == MEDIASUBTYPE_RGB32)
- return QVideoFrame::Format_RGB32;
- else if (uid == MEDIASUBTYPE_RGB24)
- return QVideoFrame::Format_RGB24;
- else if (uid == MEDIASUBTYPE_RGB565)
- return QVideoFrame::Format_RGB565;
- else if (uid == MEDIASUBTYPE_RGB555)
- return QVideoFrame::Format_RGB555;
- else if (uid == MEDIASUBTYPE_AYUV)
- return QVideoFrame::Format_AYUV444;
- else if (uid == MEDIASUBTYPE_I420 || uid == MEDIASUBTYPE_IYUV)
- return QVideoFrame::Format_YUV420P;
- else if (uid == MEDIASUBTYPE_YV12)
- return QVideoFrame::Format_YV12;
- else if (uid == MEDIASUBTYPE_UYVY)
- return QVideoFrame::Format_UYVY;
- else if (uid == MEDIASUBTYPE_YUYV || uid == MEDIASUBTYPE_YUY2)
- return QVideoFrame::Format_YUYV;
- else if (uid == MEDIASUBTYPE_NV12)
- return QVideoFrame::Format_NV12;
- else if (uid == MEDIASUBTYPE_MJPG)
- return QVideoFrame::Format_Jpeg;
- else if (uid == MEDIASUBTYPE_IMC1)
- return QVideoFrame::Format_IMC1;
- else if (uid == MEDIASUBTYPE_IMC2)
- return QVideoFrame::Format_IMC2;
- else if (uid == MEDIASUBTYPE_IMC3)
- return QVideoFrame::Format_IMC3;
- else if (uid == MEDIASUBTYPE_IMC4)
- return QVideoFrame::Format_IMC4;
- else
- return QVideoFrame::Format_Invalid;
-}
-
-
DSCameraSession::DSCameraSession(QObject *parent)
: QObject(parent)
, m_graphBuilder(Q_NULLPTR)
@@ -196,7 +61,6 @@ DSCameraSession::DSCameraSession(QObject *parent)
, m_sourceDeviceName(QLatin1String("default"))
, m_sourceFilter(Q_NULLPTR)
, m_needsHorizontalMirroring(false)
- , m_previewFilter(Q_NULLPTR)
, m_previewSampleGrabber(Q_NULLPTR)
, m_nullRendererFilter(Q_NULLPTR)
, m_previewStarted(false)
@@ -207,8 +71,6 @@ DSCameraSession::DSCameraSession(QObject *parent)
, m_currentImageId(-1)
, m_status(QCamera::UnloadedStatus)
{
- ZeroMemory(&m_sourceFormat, sizeof(m_sourceFormat));
-
connect(this, SIGNAL(statusChanged(QCamera::Status)),
this, SLOT(updateReadyForCapture()));
}
@@ -497,14 +359,13 @@ bool DSCameraSession::unload()
setStatus(QCamera::UnloadingStatus);
+ m_previewSampleGrabber->deleteLater();
+ m_previewSampleGrabber = nullptr;
+
m_needsHorizontalMirroring = false;
m_supportedViewfinderSettings.clear();
- for (AM_MEDIA_TYPE f : qAsConst(m_supportedFormats))
- _FreeMediaType(f);
m_supportedFormats.clear();
SAFE_RELEASE(m_sourceFilter);
- SAFE_RELEASE(m_previewSampleGrabber);
- SAFE_RELEASE(m_previewFilter);
SAFE_RELEASE(m_nullRendererFilter);
SAFE_RELEASE(m_filterGraph);
SAFE_RELEASE(m_graphBuilder);
@@ -571,6 +432,9 @@ bool DSCameraSession::stopPreview()
setStatus(QCamera::StoppingStatus);
+ if (m_previewSampleGrabber)
+ m_previewSampleGrabber->stop();
+
IMediaControl* pControl = 0;
HRESULT hr = m_filterGraph->QueryInterface(IID_IMediaControl, (void**)&pControl);
if (FAILED(hr)) {
@@ -587,8 +451,7 @@ bool DSCameraSession::stopPreview()
disconnectGraph();
- _FreeMediaType(m_sourceFormat);
- ZeroMemory(&m_sourceFormat, sizeof(m_sourceFormat));
+ m_sourceFormat.clear();
m_previewStarted = false;
setStatus(QCamera::LoadedStatus);
@@ -646,12 +509,12 @@ int DSCameraSession::captureImage(const QString &fileName)
return m_imageIdCounter;
}
-void DSCameraSession::onFrameAvailable(const char *frameData, long len)
+void DSCameraSession::onFrameAvailable(double time, quint8 *buffer, long len)
{
// !!! Not called on the main thread
-
+ Q_UNUSED(time);
// Deep copy, the data might be modified or freed after the callback returns
- QByteArray data(frameData, len);
+ QByteArray data(reinterpret_cast<const char *>(buffer), len);
m_presentMutex.lock();
@@ -688,7 +551,7 @@ void DSCameraSession::presentFrame()
m_presentMutex.unlock();
QImage captureImage;
- int captureId;
+ const int captureId = m_currentImageId;
m_captureMutex.lock();
@@ -705,8 +568,6 @@ void DSCameraSession::presentFrame()
m_capturedFrame.unmap();
- captureId = m_currentImageId;
-
QtConcurrent::run(this, &DSCameraSession::saveCapturedImage,
m_currentImageId, captureImage, m_imageCaptureFileName);
@@ -737,8 +598,6 @@ void DSCameraSession::saveCapturedImage(int id, const QImage &image, const QStri
bool DSCameraSession::createFilterGraph()
{
// Previously containered in <qedit.h>.
- static const IID iID_ISampleGrabber = { 0x6B652FFF, 0x11FE, 0x4fce, { 0x92, 0xAD, 0x02, 0x66, 0xB5, 0xD7, 0xC7, 0x8F } };
- static const CLSID cLSID_SampleGrabber = { 0xC1F400A0, 0x3F08, 0x11d3, { 0x9F, 0x0B, 0x00, 0x60, 0x08, 0x03, 0x9E, 0x37 } };
static const CLSID cLSID_NullRenderer = { 0xC1F400A4, 0x3F08, 0x11d3, { 0x9F, 0x0B, 0x00, 0x60, 0x08, 0x03, 0x9E, 0x37 } };
HRESULT hr;
@@ -840,26 +699,12 @@ bool DSCameraSession::createFilterGraph()
}
// Sample grabber filter
- hr = CoCreateInstance(cLSID_SampleGrabber, NULL,CLSCTX_INPROC,
- IID_IBaseFilter, (void**)&m_previewFilter);
- if (FAILED(hr)) {
- qWarning() << "failed to create sample grabber";
- goto failed;
+ if (!m_previewSampleGrabber) {
+ m_previewSampleGrabber = new DirectShowSampleGrabber;
+ connect(m_previewSampleGrabber, &DirectShowSampleGrabber::bufferAvailable,
+ this, &DSCameraSession::onFrameAvailable);
}
- hr = m_previewFilter->QueryInterface(iID_ISampleGrabber, (void**)&m_previewSampleGrabber);
- if (FAILED(hr)) {
- qWarning() << "failed to get sample grabber";
- goto failed;
- }
-
- {
- SampleGrabberCallbackPrivate *callback = new SampleGrabberCallbackPrivate(this);
- m_previewSampleGrabber->SetCallback(callback, 1);
- m_previewSampleGrabber->SetOneShot(FALSE);
- m_previewSampleGrabber->SetBufferSamples(FALSE);
- callback->Release();
- }
// Null renderer. Input connected to the sample grabber's output. Simply
// discard the samples it receives.
@@ -877,8 +722,6 @@ bool DSCameraSession::createFilterGraph()
failed:
m_needsHorizontalMirroring = false;
SAFE_RELEASE(m_sourceFilter);
- SAFE_RELEASE(m_previewSampleGrabber);
- SAFE_RELEASE(m_previewFilter);
SAFE_RELEASE(m_nullRendererFilter);
SAFE_RELEASE(m_filterGraph);
SAFE_RELEASE(m_graphBuilder);
@@ -910,11 +753,11 @@ bool DSCameraSession::configurePreviewFormat()
m_actualViewfinderSettings = resolvedViewfinderSettings;
- _CopyMediaType(&m_sourceFormat, &m_supportedFormats[settingsIndex]);
+ m_sourceFormat = m_supportedFormats[settingsIndex];
// Set frame rate.
// We don't care about the minimumFrameRate, DirectShow only allows to set an
// average frame rate, so set that to the maximumFrameRate.
- VIDEOINFOHEADER *videoInfo = reinterpret_cast<VIDEOINFOHEADER*>(m_sourceFormat.pbFormat);
+ VIDEOINFOHEADER *videoInfo = reinterpret_cast<VIDEOINFOHEADER*>(m_sourceFormat->pbFormat);
videoInfo->AvgTimePerFrame = 10000000 / resolvedViewfinderSettings.maximumFrameRate();
// We only support RGB32, if the capture source doesn't support
@@ -955,16 +798,11 @@ bool DSCameraSession::configurePreviewFormat()
}
// Set sample grabber format (always RGB32)
- AM_MEDIA_TYPE grabberFormat;
- ZeroMemory(&grabberFormat, sizeof(grabberFormat));
- grabberFormat.majortype = MEDIATYPE_Video;
- grabberFormat.subtype = MEDIASUBTYPE_RGB32;
- grabberFormat.formattype = FORMAT_VideoInfo;
- hr = m_previewSampleGrabber->SetMediaType(&grabberFormat);
- if (FAILED(hr)) {
- qWarning() << "Failed to set video format on grabber";
+ static const AM_MEDIA_TYPE grabberFormat { MEDIATYPE_Video, MEDIASUBTYPE_RGB32, 0, 0, 0, FORMAT_VideoInfo, nullptr, 0, nullptr};
+ if (!m_previewSampleGrabber->setMediaType(&grabberFormat))
return false;
- }
+
+ m_previewSampleGrabber->start(DirectShowSampleGrabber::CallbackMethod::BufferCB);
return true;
}
@@ -1052,8 +890,7 @@ bool DSCameraSession::connectGraph()
return false;
}
- hr = m_filterGraph->AddFilter(m_previewFilter, L"Sample Grabber");
- if (FAILED(hr)) {
+ if (FAILED(m_filterGraph->AddFilter(m_previewSampleGrabber->filter(), L"Sample Grabber"))) {
qWarning() << "failed to add sample grabber to graph";
return false;
}
@@ -1066,7 +903,7 @@ bool DSCameraSession::connectGraph()
hr = m_graphBuilder->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,
m_sourceFilter,
- m_previewFilter,
+ m_previewSampleGrabber->filter(),
m_nullRendererFilter);
if (FAILED(hr)) {
qWarning() << "Graph failed to connect filters" << hr;
@@ -1078,40 +915,10 @@ bool DSCameraSession::connectGraph()
void DSCameraSession::disconnectGraph()
{
- IPin *pPin = 0;
- HRESULT hr = getPin(m_sourceFilter, PINDIR_OUTPUT, &pPin);
- if (SUCCEEDED(hr)) {
- m_filterGraph->Disconnect(pPin);
- pPin->Release();
- pPin = NULL;
- }
-
- hr = getPin(m_previewFilter, PINDIR_INPUT, &pPin);
- if (SUCCEEDED(hr)) {
- m_filterGraph->Disconnect(pPin);
- pPin->Release();
- pPin = NULL;
- }
-
- hr = getPin(m_previewFilter, PINDIR_OUTPUT, &pPin);
- if (SUCCEEDED(hr)) {
- m_filterGraph->Disconnect(pPin);
- pPin->Release();
- pPin = NULL;
- }
-
- hr = getPin(m_nullRendererFilter, PINDIR_INPUT, &pPin);
- if (SUCCEEDED(hr)) {
- m_filterGraph->Disconnect(pPin);
- pPin->Release();
- pPin = NULL;
- }
-
// To avoid increasing the memory usage every time the graph is re-connected it's
// important that all filters are released; also the ones added by the "Intelligent Connect".
IEnumFilters *enumFilters = NULL;
- hr = m_filterGraph->EnumFilters(&enumFilters);
- if (SUCCEEDED(hr)) {
+ if (SUCCEEDED(m_filterGraph->EnumFilters(&enumFilters))) {
IBaseFilter *filter = NULL;
while (enumFilters->Next(1, &filter, NULL) == S_OK) {
m_filterGraph->RemoveFilter(filter);
@@ -1137,8 +944,6 @@ void DSCameraSession::updateSourceCapabilities()
m_supportedViewfinderSettings.clear();
m_needsHorizontalMirroring = false;
- for (AM_MEDIA_TYPE f : qAsConst(m_supportedFormats))
- _FreeMediaType(f);
m_supportedFormats.clear();
m_imageProcessingParametersInfos.clear();
@@ -1150,8 +955,7 @@ void DSCameraSession::updateSourceCapabilities()
qWarning() << "Failed to get the video control";
} else {
IPin *pPin = 0;
- hr = getPin(m_sourceFilter, PINDIR_OUTPUT, &pPin);
- if (FAILED(hr)) {
+ if (!DirectShowUtils::getPin(m_sourceFilter, PINDIR_OUTPUT, &pPin, &hr)) {
qWarning() << "Failed to get the pin for the video control";
} else {
long supportedModes;
@@ -1190,7 +994,7 @@ void DSCameraSession::updateSourceCapabilities()
for (int iIndex = 0; iIndex < iCount; ++iIndex) {
hr = pConfig->GetStreamCaps(iIndex, &pmt, reinterpret_cast<BYTE*>(&scc));
if (hr == S_OK) {
- QVideoFrame::PixelFormat pixelFormat = pixelFormatFromMediaSubtype(pmt->subtype);
+ QVideoFrame::PixelFormat pixelFormat = DirectShowMediaType::pixelFormatFromType(pmt);
if (pmt->majortype == MEDIATYPE_Video
&& pmt->formattype == FORMAT_VideoInfo
@@ -1203,8 +1007,7 @@ void DSCameraSession::updateSourceCapabilities()
if (pVideoControl) {
IPin *pPin = 0;
- hr = getPin(m_sourceFilter, PINDIR_OUTPUT, &pPin);
- if (FAILED(hr)) {
+ if (!DirectShowUtils::getPin(m_sourceFilter, PINDIR_OUTPUT, &pPin, &hr)) {
qWarning() << "Failed to get the pin for the video control";
} else {
long listSize = 0;
@@ -1237,15 +1040,12 @@ void DSCameraSession::updateSourceCapabilities()
settings.setPixelFormat(pixelFormat);
settings.setPixelAspectRatio(1, 1);
m_supportedViewfinderSettings.append(settings);
-
- AM_MEDIA_TYPE format;
- _CopyMediaType(&format, pmt);
- m_supportedFormats.append(format);
+ m_supportedFormats.append(DirectShowMediaType(*pmt));
}
}
- _FreeMediaType(*pmt);
+ DirectShowMediaType::deleteType(pmt);
}
}
@@ -1254,30 +1054,4 @@ void DSCameraSession::updateSourceCapabilities()
updateImageProcessingParametersInfos();
}
-HRESULT getPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir, IPin **ppPin)
-{
- *ppPin = 0;
- IEnumPins *pEnum = 0;
- IPin *pPin = 0;
-
- HRESULT hr = pFilter->EnumPins(&pEnum);
- if (FAILED(hr)) {
- return hr;
- }
-
- pEnum->Reset();
- while (pEnum->Next(1, &pPin, NULL) == S_OK) {
- PIN_DIRECTION ThisPinDir;
- pPin->QueryDirection(&ThisPinDir);
- if (ThisPinDir == PinDir) {
- pEnum->Release();
- *ppPin = pPin;
- return S_OK;
- }
- pPin->Release();
- }
- pEnum->Release();
- return E_FAIL;
-}
-
QT_END_NAMESPACE
diff --git a/src/plugins/directshow/camera/dscamerasession.h b/src/plugins/directshow/camera/dscamerasession.h
index 61b156d8a..37730736f 100644
--- a/src/plugins/directshow/camera/dscamerasession.h
+++ b/src/plugins/directshow/camera/dscamerasession.h
@@ -56,6 +56,7 @@
#include <dshow.h>
#include <objbase.h>
#include <initguid.h>
+#include "directshowmediatype.h"
#ifdef Q_CC_MSVC
# pragma comment(lib, "strmiids.lib")
# pragma comment(lib, "ole32.lib")
@@ -71,11 +72,10 @@
#define __IDxtKey_INTERFACE_DEFINED__
struct ICaptureGraphBuilder2;
-struct ISampleGrabber;
QT_BEGIN_NAMESPACE
-class SampleGrabberCallbackPrivate;
+class DirectShowSampleGrabber;
class DSCameraSession : public QObject
{
@@ -154,7 +154,7 @@ private:
void setStatus(QCamera::Status status);
- void onFrameAvailable(const char *frameData, long len);
+ void onFrameAvailable(double time, quint8 *buffer, long len);
void saveCapturedImage(int id, const QImage &image, const QString &path);
bool createFilterGraph();
@@ -182,14 +182,13 @@ private:
QString m_sourceDeviceName;
IBaseFilter* m_sourceFilter;
bool m_needsHorizontalMirroring;
- QList<AM_MEDIA_TYPE> m_supportedFormats;
+ QList<DirectShowMediaType> m_supportedFormats;
QList<QCameraViewfinderSettings> m_supportedViewfinderSettings;
- AM_MEDIA_TYPE m_sourceFormat;
+ DirectShowMediaType m_sourceFormat;
QMap<QCameraImageProcessingControl::ProcessingParameter, ImageProcessingParameterInfo> m_imageProcessingParametersInfos;
// Preview
- IBaseFilter *m_previewFilter;
- ISampleGrabber *m_previewSampleGrabber;
+ DirectShowSampleGrabber *m_previewSampleGrabber;
IBaseFilter *m_nullRendererFilter;
QVideoFrame m_currentFrame;
bool m_previewStarted;
diff --git a/src/plugins/directshow/common/common.pri b/src/plugins/directshow/common/common.pri
new file mode 100644
index 000000000..9b7c1e3f4
--- /dev/null
+++ b/src/plugins/directshow/common/common.pri
@@ -0,0 +1,11 @@
+INCLUDEPATH += $$PWD
+
+HEADERS += \
+ $$PWD/directshowvideoprobecontrol.h \
+ $$PWD/directshowaudioprobecontrol.h \
+ $$PWD/directshowsamplegrabber.h
+
+SOURCES += \
+ $$PWD/directshowvideoprobecontrol.cpp \
+ $$PWD/directshowaudioprobecontrol.cpp \
+ $$PWD/directshowsamplegrabber.cpp
diff --git a/src/plugins/directshow/common/directshowaudioprobecontrol.cpp b/src/plugins/directshow/common/directshowaudioprobecontrol.cpp
new file mode 100644
index 000000000..55ef70178
--- /dev/null
+++ b/src/plugins/directshow/common/directshowaudioprobecontrol.cpp
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** 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 "directshowaudioprobecontrol.h"
+#include "directshowglobal.h"
+
+QT_BEGIN_NAMESPACE
+
+DirectShowAudioProbeControl::DirectShowAudioProbeControl(QObject *p)
+ : QMediaAudioProbeControl(p)
+{
+
+}
+
+DirectShowAudioProbeControl::~DirectShowAudioProbeControl()
+{
+ if (m_ref.deref())
+ qCWarning(qtDirectShowPlugin, "QAudioProbe control destroyed while it's still being referenced!!!");
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/directshow/common/directshowaudioprobecontrol.h b/src/plugins/directshow/common/directshowaudioprobecontrol.h
new file mode 100644
index 000000000..553bd1178
--- /dev/null
+++ b/src/plugins/directshow/common/directshowaudioprobecontrol.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** 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 DIRECTSHOWAUDIOPROBECONTROL_H
+#define DIRECTSHOWAUDIOPROBECONTROL_H
+
+#include <qmediaaudioprobecontrol.h>
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class DirectShowAudioProbeControl : public QMediaAudioProbeControl
+{
+ Q_OBJECT
+public:
+ explicit DirectShowAudioProbeControl(QObject *p = nullptr);
+ ~DirectShowAudioProbeControl();
+
+ bool ref() { return m_ref.ref(); }
+ bool deref() { return m_ref.deref(); }
+private:
+ QAtomicInt m_ref;
+};
+
+QT_END_NAMESPACE
+
+#endif // DIRECTSHOWAUDIOPROBECONTROL_H
diff --git a/src/plugins/directshow/common/directshowsamplegrabber.cpp b/src/plugins/directshow/common/directshowsamplegrabber.cpp
new file mode 100644
index 000000000..b33c3cfc6
--- /dev/null
+++ b/src/plugins/directshow/common/directshowsamplegrabber.cpp
@@ -0,0 +1,196 @@
+/****************************************************************************
+**
+** 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 "directshowsamplegrabber.h"
+
+#include "directshowglobal.h"
+#include "directshowutils.h"
+
+
+QT_BEGIN_NAMESPACE
+
+// Previously contained in <qedit.h>.
+static const IID iID_ISampleGrabber = { 0x6B652FFF, 0x11FE, 0x4fce, { 0x92, 0xAD, 0x02, 0x66, 0xB5, 0xD7, 0xC7, 0x8F } };
+static const CLSID cLSID_SampleGrabber = { 0xC1F400A0, 0x3F08, 0x11d3, { 0x9F, 0x0B, 0x00, 0x60, 0x08, 0x03, 0x9E, 0x37 } };
+
+class SampleGrabberCallbackPrivate : public ISampleGrabberCB
+{
+public:
+ explicit SampleGrabberCallbackPrivate(DirectShowSampleGrabber *grabber)
+ : m_ref(1)
+ , m_grabber(grabber)
+ { }
+
+ virtual ~SampleGrabberCallbackPrivate() { }
+
+ STDMETHODIMP_(ULONG) AddRef()
+ {
+ return InterlockedIncrement(&m_ref);
+ }
+
+ STDMETHODIMP_(ULONG) Release()
+ {
+ ULONG ref = InterlockedDecrement(&m_ref);
+ if (ref == 0)
+ delete this;
+ return ref;
+ }
+
+ STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject)
+ {
+ if (NULL == ppvObject)
+ return E_POINTER;
+
+ if (riid == IID_IUnknown /*__uuidof(IUnknown) */ ) {
+ AddRef();
+ *ppvObject = static_cast<IUnknown *>(this);
+ return S_OK;
+ } else if (riid == IID_ISampleGrabberCB /*__uuidof(ISampleGrabberCB)*/ ) {
+ AddRef();
+ *ppvObject = static_cast<ISampleGrabberCB *>(this);
+ return S_OK;
+ }
+ return E_NOTIMPL;
+ }
+
+ STDMETHODIMP SampleCB(double time, IMediaSample *mediaSample)
+ {
+ if (m_grabber)
+ Q_EMIT m_grabber->sampleAvailable(time, mediaSample);
+
+ return S_OK;
+ }
+
+ STDMETHODIMP BufferCB(double time, BYTE *buffer, long bufferLen)
+ {
+ if (m_grabber)
+ Q_EMIT m_grabber->bufferAvailable(time, buffer, bufferLen);
+
+ return S_OK;
+ }
+
+private:
+ ULONG m_ref;
+ DirectShowSampleGrabber *m_grabber;
+};
+
+DirectShowSampleGrabber::DirectShowSampleGrabber(QObject *p)
+ : QObject(p)
+ , m_sampleGrabber(nullptr)
+ , m_sampleGabberCb(nullptr)
+ , m_callbackType(CallbackMethod::BufferCB)
+{
+ // Create sample grabber filter
+ HRESULT hr = CoCreateInstance(cLSID_SampleGrabber, NULL, CLSCTX_INPROC, iID_ISampleGrabber, reinterpret_cast<void **>(&m_sampleGrabber));
+
+ if (FAILED(hr)) {
+ qCWarning(qtDirectShowPlugin, "Failed to create sample grabber");
+ return;
+ }
+
+ hr = m_sampleGrabber->QueryInterface(IID_IBaseFilter, reinterpret_cast<void **>(&m_filter));
+ if (FAILED(hr))
+ qCWarning(qtDirectShowPlugin, "Failed to get base filter interface");
+}
+
+DirectShowSampleGrabber::~DirectShowSampleGrabber()
+{
+ stop();
+ SAFE_RELEASE(m_sampleGabberCb);
+ SAFE_RELEASE(m_filter);
+ SAFE_RELEASE(m_sampleGrabber);
+}
+
+void DirectShowSampleGrabber::stop()
+{
+ if (!m_sampleGrabber)
+ return;
+
+ if (FAILED(m_sampleGrabber->SetCallback(nullptr, static_cast<long>(m_callbackType)))) {
+ qCWarning(qtDirectShowPlugin, "Failed to stop sample grabber callback");
+ return;
+ }
+}
+
+bool DirectShowSampleGrabber::getConnectedMediaType(AM_MEDIA_TYPE *mediaType)
+{
+ Q_ASSERT(mediaType);
+
+ if (!isValid())
+ return false;
+
+ if (FAILED(m_sampleGrabber->GetConnectedMediaType(mediaType))) {
+ qCWarning(qtDirectShowPlugin, "Failed to retrieve the connected media type");
+ return false;
+ }
+
+ return true;
+}
+
+bool DirectShowSampleGrabber::setMediaType(const AM_MEDIA_TYPE *mediaType)
+{
+ Q_ASSERT(mediaType);
+
+ if (FAILED(m_sampleGrabber->SetMediaType(mediaType))) {
+ qCWarning(qtDirectShowPlugin, "Failed to set media type");
+ return false;
+ }
+
+ return true;
+}
+
+void DirectShowSampleGrabber::start(DirectShowSampleGrabber::CallbackMethod method,
+ bool oneShot,
+ bool bufferSamples)
+{
+ if (!m_sampleGrabber)
+ return;
+
+ stop();
+
+ if (!m_sampleGabberCb)
+ m_sampleGabberCb = new SampleGrabberCallbackPrivate(this);
+
+ m_callbackType = method;
+ m_sampleGrabber->SetCallback(m_sampleGabberCb, static_cast<long>(method));
+ m_sampleGrabber->SetOneShot(oneShot);
+ m_sampleGrabber->SetBufferSamples(bufferSamples);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/directshow/common/directshowsamplegrabber.h b/src/plugins/directshow/common/directshowsamplegrabber.h
new file mode 100644
index 000000000..edabae2db
--- /dev/null
+++ b/src/plugins/directshow/common/directshowsamplegrabber.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** 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 DIRECTSHOWSAMPLEGRABBER_H
+#define DIRECTSHOWSAMPLEGRABBER_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qobject.h>
+
+// TODO: Fix this.
+#include <directshowcameraglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class SampleGrabberCallbackPrivate;
+
+class DirectShowSampleGrabber : public QObject
+{
+ Q_OBJECT
+public:
+ DirectShowSampleGrabber(QObject *p = nullptr);
+ ~DirectShowSampleGrabber();
+
+ // 0 = ISampleGrabberCB::SampleCB, 1 = ISampleGrabberCB::BufferCB
+ enum class CallbackMethod : long
+ {
+ SampleCB,
+ BufferCB
+ };
+
+ bool isValid() const { return m_filter && m_sampleGrabber; }
+ bool getConnectedMediaType(AM_MEDIA_TYPE *mediaType);
+ bool setMediaType(const AM_MEDIA_TYPE *mediaType);
+
+ void stop();
+ void start(CallbackMethod method, bool oneShot = false, bool bufferSamples = false);
+
+ IBaseFilter *filter() const { return m_filter; }
+
+Q_SIGNALS:
+ void sampleAvailable(double time, IMediaSample *sample);
+ void bufferAvailable(double time, quint8 *buffer, long len);
+
+private:
+ IBaseFilter *m_filter;
+ ISampleGrabber *m_sampleGrabber;
+ SampleGrabberCallbackPrivate *m_sampleGabberCb;
+ CallbackMethod m_callbackType;
+};
+
+QT_END_NAMESPACE
+
+#endif // DIRECTSHOWSAMPLEGRABBER_H
diff --git a/src/plugins/directshow/common/directshowvideoprobecontrol.cpp b/src/plugins/directshow/common/directshowvideoprobecontrol.cpp
new file mode 100644
index 000000000..5ec1ff064
--- /dev/null
+++ b/src/plugins/directshow/common/directshowvideoprobecontrol.cpp
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** 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 "directshowvideoprobecontrol.h"
+#include "directshowglobal.h"
+
+QT_BEGIN_NAMESPACE
+
+DirectShowVideoProbeControl::DirectShowVideoProbeControl(QObject *p)
+ : QMediaVideoProbeControl(p)
+{
+
+}
+
+DirectShowVideoProbeControl::~DirectShowVideoProbeControl()
+{
+ if (m_ref.deref())
+ qCWarning(qtDirectShowPlugin, "QVideoProbe control destroyed while it's still being referenced!!!");
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/directshow/common/directshowvideoprobecontrol.h b/src/plugins/directshow/common/directshowvideoprobecontrol.h
new file mode 100644
index 000000000..458263234
--- /dev/null
+++ b/src/plugins/directshow/common/directshowvideoprobecontrol.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** 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 DIRECTSHOWVIDEOPROBECONTROL_H
+#define DIRECTSHOWVIDEOPROBECONTROL_H
+
+#include <qmediavideoprobecontrol.h>
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class DirectShowVideoProbeControl : public QMediaVideoProbeControl
+{
+ Q_OBJECT
+public:
+ explicit DirectShowVideoProbeControl(QObject *p = nullptr);
+ ~DirectShowVideoProbeControl();
+
+ bool ref() { return m_ref.ref(); }
+ bool deref() { return m_ref.deref(); }
+private:
+ QAtomicInt m_ref;
+};
+
+QT_END_NAMESPACE
+
+#endif // DIRECTSHOWVIDEOPROBECONTROL_H
diff --git a/src/plugins/directshow/directshow.pro b/src/plugins/directshow/directshow.pro
index 8e31527da..35301474f 100644
--- a/src/plugins/directshow/directshow.pro
+++ b/src/plugins/directshow/directshow.pro
@@ -10,6 +10,7 @@ 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/dsserviceplugin.cpp b/src/plugins/directshow/dsserviceplugin.cpp
index 6d8f97f52..9060bac7c 100644
--- a/src/plugins/directshow/dsserviceplugin.cpp
+++ b/src/plugins/directshow/dsserviceplugin.cpp
@@ -44,6 +44,7 @@
#include <QtCore/qdebug.h>
#include <QtCore/QFile>
+#include "directshowglobal.h"
#include "dsserviceplugin.h"
#include "dsvideodevicecontrol.h"
@@ -72,6 +73,10 @@ extern const CLSID CLSID_VideoInputDeviceCategory;
#include <windows.h>
#include <ocidl.h>
+QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(qtDirectShowPlugin, "qt.multimedia.plugins.directshow")
+QT_END_NAMESPACE
+
QT_USE_NAMESPACE
static int g_refCount = 0;
diff --git a/src/plugins/directshow/helpers/directshowglobal.h b/src/plugins/directshow/helpers/directshowglobal.h
index f7890c52b..5f391710e 100644
--- a/src/plugins/directshow/helpers/directshowglobal.h
+++ b/src/plugins/directshow/helpers/directshowglobal.h
@@ -43,6 +43,13 @@
#include <dshow.h>
#include <QtCore/qglobal.h>
+#include <QtCore/qloggingcategory.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(qtDirectShowPlugin)
+
+QT_END_NAMESPACE
template <typename T> T *com_cast(IUnknown *unknown, const IID &iid)
{
@@ -77,6 +84,9 @@ template <typename T> T *com_new(const IID &clsid, const IID &iid)
: 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
diff --git a/src/plugins/directshow/helpers/directshowmediatype.cpp b/src/plugins/directshow/helpers/directshowmediatype.cpp
index 60c0ee040..d9ddf8248 100644
--- a/src/plugins/directshow/helpers/directshowmediatype.cpp
+++ b/src/plugins/directshow/helpers/directshowmediatype.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "directshowmediatype.h"
+#include "directshowglobal.h"
namespace
{
@@ -49,85 +50,168 @@ namespace
static const TypeLookup qt_typeLookup[] =
{
- { QVideoFrame::Format_RGB32, /*MEDIASUBTYPE_RGB32*/ {0xe436eb7e, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}} },
- { QVideoFrame::Format_BGR24, /*MEDIASUBTYPE_RGB24*/ {0xe436eb7d, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}} },
- { QVideoFrame::Format_RGB565, /*MEDIASUBTYPE_RGB565*/ {0xe436eb7b, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}} },
- { QVideoFrame::Format_RGB555, /*MEDIASUBTYPE_RGB555*/ {0xe436eb7c, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}} },
- { QVideoFrame::Format_AYUV444, /*MEDIASUBTYPE_AYUV*/ {0x56555941, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
- { QVideoFrame::Format_YUYV, /*MEDIASUBTYPE_YUY2*/ {0x32595559, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
- { QVideoFrame::Format_UYVY, /*MEDIASUBTYPE_UYVY*/ {0x59565955, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
- { QVideoFrame::Format_IMC1, /*MEDIASUBTYPE_IMC1*/ {0x31434D49, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
- { QVideoFrame::Format_IMC2, /*MEDIASUBTYPE_IMC2*/ {0x32434D49, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
- { QVideoFrame::Format_IMC3, /*MEDIASUBTYPE_IMC3*/ {0x33434D49, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
- { QVideoFrame::Format_IMC4, /*MEDIASUBTYPE_IMC4*/ {0x34434D49, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
- { QVideoFrame::Format_YV12, /*MEDIASUBTYPE_YV12*/ {0x32315659, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
- { QVideoFrame::Format_NV12, /*MEDIASUBTYPE_NV12*/ {0x3231564E, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
- { QVideoFrame::Format_YUV420P, /*MEDIASUBTYPE_IYUV*/ {0x56555949, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
- { QVideoFrame::Format_YUV420P, /*MEDIASUBTYPE_I420*/ {0x30323449, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} }
+ { 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
+bool DirectShowMediaType::isPartiallySpecified(const AM_MEDIA_TYPE *mediaType)
{
- return majortype == GUID_NULL || formattype == GUID_NULL;
+ return mediaType->majortype == GUID_NULL || mediaType->formattype == GUID_NULL;
}
-bool DirectShowMediaType::isCompatibleWith(const DirectShowMediaType *type) const
+DirectShowMediaType::DirectShowMediaType()
+ : mediaType({ GUID_NULL, GUID_NULL, TRUE, FALSE, 1, GUID_NULL, nullptr, 0, nullptr})
{
- if (type->majortype != GUID_NULL && majortype != type->majortype)
- return false;
+}
- if (type->subtype != GUID_NULL && subtype != type->subtype)
- return false;
+DirectShowMediaType::DirectShowMediaType(const AM_MEDIA_TYPE &type)
+ : DirectShowMediaType()
+{
+ copy(&mediaType, &type);
+}
- if (type->formattype != GUID_NULL) {
- if (formattype != type->formattype)
- return false;
- if (cbFormat != type->cbFormat)
- return false;
- if (cbFormat != 0 && memcmp(pbFormat, type->pbFormat, cbFormat) != 0)
- return false;
- }
+DirectShowMediaType::DirectShowMediaType(AM_MEDIA_TYPE &&type)
+ : DirectShowMediaType()
+{
+ move(&mediaType, type);
+}
- return true;
+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)
{
- ZeroMemory((PVOID)type, sizeof(*type));
+ Q_ASSERT(type);
+ SecureZeroMemory(reinterpret_cast<void *>(type), sizeof(AM_MEDIA_TYPE));
type->lSampleSize = 1;
type->bFixedSizeSamples = TRUE;
}
-void DirectShowMediaType::copy(AM_MEDIA_TYPE *target, const AM_MEDIA_TYPE &source)
+void DirectShowMediaType::copy(AM_MEDIA_TYPE *target, const AM_MEDIA_TYPE *source)
{
- if (!target)
+ if (!(target && source))
+ return;
+
+ if (target == source)
return;
- *target = source;
+ clear(*target);
- if (source.cbFormat > 0) {
- target->pbFormat = reinterpret_cast<PBYTE>(CoTaskMemAlloc(source.cbFormat));
- memcpy(target->pbFormat, source.pbFormat, source.cbFormat);
+ *target = *source;
+
+ if (source->cbFormat > 0) {
+ target->pbFormat = reinterpret_cast<PBYTE>(CoTaskMemAlloc(source->cbFormat));
+ memcpy(target->pbFormat, source->pbFormat, source->cbFormat);
}
if (target->pUnk)
target->pUnk->AddRef();
}
+void DirectShowMediaType::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<void *>(*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)
{
- freeData(type);
+ if (!type)
+ return;
+ clear(*type);
CoTaskMemFree(type);
}
-void DirectShowMediaType::freeData(AM_MEDIA_TYPE *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.cbFormat > 0)
+ CoTaskMemFree(type.pbFormat);
+
+ if (type.pUnk)
+ type.pUnk->Release();
- if (type->pUnk)
- type->pUnk->Release();
+ SecureZeroMemory(&type, sizeof(type));
}
@@ -142,14 +226,17 @@ GUID DirectShowMediaType::convertPixelFormat(QVideoFrame::PixelFormat format)
return MEDIASUBTYPE_None;
}
-QVideoSurfaceFormat DirectShowMediaType::formatFromType(const AM_MEDIA_TYPE &type)
+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<VIDEOINFOHEADER *>(type.pbFormat);
+ if (IsEqualGUID(qt_typeLookup[i].mediaType, type->subtype) && type->cbFormat > 0) {
+ if (IsEqualGUID(type->formattype, FORMAT_VideoInfo)) {
+ VIDEOINFOHEADER *header = reinterpret_cast<VIDEOINFOHEADER *>(type->pbFormat);
QVideoSurfaceFormat format(
QSize(header->bmiHeader.biWidth, qAbs(header->bmiHeader.biHeight)),
@@ -161,8 +248,8 @@ QVideoSurfaceFormat DirectShowMediaType::formatFromType(const AM_MEDIA_TYPE &typ
format.setScanLineDirection(scanLineDirection(format.pixelFormat(), header->bmiHeader));
return format;
- } else if (IsEqualGUID(type.formattype, FORMAT_VideoInfo2)) {
- VIDEOINFOHEADER2 *header = reinterpret_cast<VIDEOINFOHEADER2 *>(type.pbFormat);
+ } else if (IsEqualGUID(type->formattype, FORMAT_VideoInfo2)) {
+ VIDEOINFOHEADER2 *header = reinterpret_cast<VIDEOINFOHEADER2 *>(type->pbFormat);
QVideoSurfaceFormat format(
QSize(header->bmiHeader.biWidth, qAbs(header->bmiHeader.biHeight)),
@@ -180,12 +267,15 @@ QVideoSurfaceFormat DirectShowMediaType::formatFromType(const AM_MEDIA_TYPE &typ
return QVideoSurfaceFormat();
}
-QVideoFrame::PixelFormat DirectShowMediaType::pixelFormatFromType(const AM_MEDIA_TYPE &type)
+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)) {
+ if (IsEqualGUID(qt_typeLookup[i].mediaType, type->subtype)) {
return qt_typeLookup[i].pixelFormat;
}
}
@@ -198,6 +288,7 @@ 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;
@@ -240,8 +331,9 @@ QVideoSurfaceFormat::Direction DirectShowMediaType::scanLineDirection(QVideoFram
*/
switch (pixelFormat)
{
+ case QVideoFrame::Format_ARGB32:
case QVideoFrame::Format_RGB32:
- case QVideoFrame::Format_BGR24:
+ case QVideoFrame::Format_RGB24:
case QVideoFrame::Format_RGB565:
case QVideoFrame::Format_RGB555:
return bmiHeader.biHeight < 0
diff --git a/src/plugins/directshow/helpers/directshowmediatype.h b/src/plugins/directshow/helpers/directshowmediatype.h
index b2b074ccc..7849ca9b0 100644
--- a/src/plugins/directshow/helpers/directshowmediatype.h
+++ b/src/plugins/directshow/helpers/directshowmediatype.h
@@ -45,39 +45,48 @@
#include <qvideosurfaceformat.h>
#include <dvdmedia.h>
+#include <QtCore/qglobal.h>
QT_USE_NAMESPACE
-class DirectShowMediaType : public AM_MEDIA_TYPE
+class DirectShowMediaType
{
public:
- DirectShowMediaType() { init(this); }
- DirectShowMediaType(const AM_MEDIA_TYPE &type) { copy(this, type); }
- DirectShowMediaType(const DirectShowMediaType &other) { copy(this, other); }
- DirectShowMediaType &operator =(const AM_MEDIA_TYPE &type) {
- freeData(this); copy(this, type); return *this; }
- DirectShowMediaType &operator =(const DirectShowMediaType &other) {
- freeData(this); copy(this, other); return *this; }
- ~DirectShowMediaType() { freeData(this); }
+ DirectShowMediaType();
+ DirectShowMediaType(const DirectShowMediaType &other);
+ DirectShowMediaType(DirectShowMediaType &&other);
+ explicit DirectShowMediaType(const AM_MEDIA_TYPE &type);
+ explicit DirectShowMediaType(AM_MEDIA_TYPE &&type);
+ ~DirectShowMediaType() { clear(mediaType); }
- void clear() { freeData(this); init(this); }
+ DirectShowMediaType &operator =(const DirectShowMediaType &other);
+ DirectShowMediaType &operator =(DirectShowMediaType &&other);
- bool isPartiallySpecified() const;
- bool isCompatibleWith(const DirectShowMediaType *type) const;
+ 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 freeData(AM_MEDIA_TYPE *type);
+ static void copy(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 formatFromType(const AM_MEDIA_TYPE &type);
- static QVideoFrame::PixelFormat pixelFormatFromType(const AM_MEDIA_TYPE &type);
+ 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:
- static QVideoSurfaceFormat::Direction scanLineDirection(QVideoFrame::PixelFormat pixelFormat, const BITMAPINFOHEADER &bmiHeader);
+ AM_MEDIA_TYPE mediaType;
};
Q_DECLARE_TYPEINFO(DirectShowMediaType, Q_MOVABLE_TYPE);
diff --git a/src/plugins/directshow/helpers/directshowmediatypeenum.cpp b/src/plugins/directshow/helpers/directshowmediatypeenum.cpp
index a1c8b2306..a58993f7f 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<AM_MEDIA_TYPE *>(CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE)));
- DirectShowMediaType::copy(ppMediaTypes[i], m_mediaTypes.at(m_index));
+ DirectShowMediaType::copy(ppMediaTypes[i], &m_mediaTypes.at(m_index));
}
if (pcFetched)
diff --git a/src/plugins/directshow/helpers/directshowpin.cpp b/src/plugins/directshow/helpers/directshowpin.cpp
index 6cf4da321..f501747f9 100644
--- a/src/plugins/directshow/helpers/directshowpin.cpp
+++ b/src/plugins/directshow/helpers/directshowpin.cpp
@@ -81,22 +81,20 @@ HRESULT DirectShowPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
if (pd == m_direction)
return VFW_E_INVALID_DIRECTION;
- const DirectShowMediaType *type = reinterpret_cast<const DirectShowMediaType*>(pmt);
-
- if (type != NULL && !type->isPartiallySpecified()) {
+ if (pmt != NULL && DirectShowMediaType::isPartiallySpecified(pmt)) {
// If the type is fully specified, use it
- hr = tryConnect(pReceivePin, type);
+ hr = tryConnect(pReceivePin, pmt);
} else {
IEnumMediaTypes *enumMediaTypes = NULL;
// First, try the receiving pin's preferred types
if (SUCCEEDED(pReceivePin->EnumMediaTypes(&enumMediaTypes))) {
- hr = tryMediaTypes(pReceivePin, type, enumMediaTypes);
+ hr = tryMediaTypes(pReceivePin, pmt, enumMediaTypes);
enumMediaTypes->Release();
}
// Then, try this pin's preferred types
if (FAILED(hr) && SUCCEEDED(EnumMediaTypes(&enumMediaTypes))) {
- hr = tryMediaTypes(pReceivePin, type, enumMediaTypes);
+ hr = tryMediaTypes(pReceivePin, pmt, enumMediaTypes);
enumMediaTypes->Release();
}
}
@@ -109,19 +107,19 @@ HRESULT DirectShowPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
return S_OK;
}
-HRESULT DirectShowPin::tryMediaTypes(IPin *pin, const DirectShowMediaType *partialType, IEnumMediaTypes *enumMediaTypes)
+HRESULT DirectShowPin::tryMediaTypes(IPin *pin, const AM_MEDIA_TYPE *partialType, IEnumMediaTypes *enumMediaTypes)
{
HRESULT hr = enumMediaTypes->Reset();
if (FAILED(hr))
return hr;
- DirectShowMediaType *mediaType = NULL;
+ AM_MEDIA_TYPE *mediaType = NULL;
ULONG mediaCount = 0;
HRESULT hrFailure = VFW_E_NO_ACCEPTABLE_TYPES;
- for (; enumMediaTypes->Next(1, reinterpret_cast<AM_MEDIA_TYPE**>(&mediaType), &mediaCount) == S_OK;) {
+ for (; enumMediaTypes->Next(1, &mediaType, &mediaCount) == S_OK;) {
- if (mediaType && (partialType == NULL || mediaType->isCompatibleWith(partialType))) {
+ if (mediaType && (partialType == NULL || DirectShowMediaType::isCompatible(mediaType, partialType))) {
hr = tryConnect(pin, mediaType);
if (FAILED(hr) && (hr != E_FAIL)
@@ -141,7 +139,7 @@ HRESULT DirectShowPin::tryMediaTypes(IPin *pin, const DirectShowMediaType *parti
return hrFailure;
}
-HRESULT DirectShowPin::tryConnect(IPin *pin, const DirectShowMediaType *type)
+HRESULT DirectShowPin::tryConnect(IPin *pin, const AM_MEDIA_TYPE *type)
{
if (!isMediaTypeSupported(type))
return VFW_E_TYPE_NOT_ACCEPTED;
@@ -189,15 +187,14 @@ HRESULT DirectShowPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *
if (pd == m_direction)
return VFW_E_INVALID_DIRECTION;
- const DirectShowMediaType *type = reinterpret_cast<const DirectShowMediaType*>(pmt);
- if (!isMediaTypeSupported(type))
+ if (!isMediaTypeSupported(pmt))
return VFW_E_TYPE_NOT_ACCEPTED;
m_peerPin = pConnector;
m_peerPin->AddRef();
HRESULT hr;
- if (!setMediaType(type))
+ if (!setMediaType(pmt))
hr = VFW_E_TYPE_NOT_ACCEPTED;
else
hr = completeConnection(pConnector);
@@ -265,7 +262,7 @@ HRESULT DirectShowPin::ConnectionMediaType(AM_MEDIA_TYPE *pmt)
DirectShowMediaType::init(pmt);
return VFW_E_NOT_CONNECTED;
} else {
- DirectShowMediaType::copy(pmt, m_mediaType);
+ DirectShowMediaType::copy(pmt, &m_mediaType);
return S_OK;
}
}
@@ -309,7 +306,7 @@ HRESULT DirectShowPin::QueryAccept(const AM_MEDIA_TYPE *pmt)
if (!pmt)
return E_POINTER;
- if (!isMediaTypeSupported(reinterpret_cast<const DirectShowMediaType*>(pmt)))
+ if (!isMediaTypeSupported(pmt))
return S_FALSE;
return S_OK;
@@ -370,12 +367,12 @@ QList<DirectShowMediaType> DirectShowPin::supportedMediaTypes()
return QList<DirectShowMediaType>();
}
-bool DirectShowPin::setMediaType(const DirectShowMediaType *type)
+bool DirectShowPin::setMediaType(const AM_MEDIA_TYPE *type)
{
if (!type)
m_mediaType.clear();
else
- m_mediaType = *type;
+ DirectShowMediaType::copy(&m_mediaType, type);
return true;
}
@@ -673,7 +670,7 @@ HRESULT DirectShowInputPin::Receive(IMediaSample *pSample)
if (!(m_sampleProperties.dwSampleFlags & AM_SAMPLE_TYPECHANGED))
return S_OK;
- if (isMediaTypeSupported(reinterpret_cast<DirectShowMediaType*>(m_sampleProperties.pMediaType)))
+ if (isMediaTypeSupported(m_sampleProperties.pMediaType))
return S_OK;
m_inErrorState = true;
diff --git a/src/plugins/directshow/helpers/directshowpin.h b/src/plugins/directshow/helpers/directshowpin.h
index 823223956..b8207abae 100644
--- a/src/plugins/directshow/helpers/directshowpin.h
+++ b/src/plugins/directshow/helpers/directshowpin.h
@@ -55,9 +55,9 @@ public:
QString name() const { return m_name; }
bool isConnected() const { return m_peerPin != NULL; }
- virtual bool isMediaTypeSupported(const DirectShowMediaType *type) = 0;
+ virtual bool isMediaTypeSupported(const AM_MEDIA_TYPE *type) = 0;
virtual QList<DirectShowMediaType> supportedMediaTypes();
- virtual bool setMediaType(const DirectShowMediaType *type);
+ virtual bool setMediaType(const AM_MEDIA_TYPE *type);
virtual HRESULT completeConnection(IPin *pin);
virtual HRESULT connectionEnded();
@@ -107,8 +107,8 @@ protected:
private:
Q_DISABLE_COPY(DirectShowPin)
- HRESULT tryMediaTypes(IPin *pin, const DirectShowMediaType *type, IEnumMediaTypes *enumMediaTypes);
- HRESULT tryConnect(IPin *pin, const DirectShowMediaType *type);
+ HRESULT tryMediaTypes(IPin *pin, const AM_MEDIA_TYPE *type, IEnumMediaTypes *enumMediaTypes);
+ HRESULT tryConnect(IPin *pin, const AM_MEDIA_TYPE *type);
};
diff --git a/src/plugins/directshow/helpers/directshowutils.cpp b/src/plugins/directshow/helpers/directshowutils.cpp
new file mode 100644
index 000000000..d9701fd99
--- /dev/null
+++ b/src/plugins/directshow/helpers/directshowutils.cpp
@@ -0,0 +1,309 @@
+/****************************************************************************
+**
+** 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"
+
+/**
+ * @brief DirectShowUtils::isPinConnected
+ * @param pin
+ * @param hrOut
+ * @return
+ */
+bool DirectShowUtils::isPinConnected(IPin *pin, HRESULT *hrOut)
+{
+ IPin *connectedPin = nullptr;
+ const ScopedSafeRelease<IPin> 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<IEnumPins> 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<IPin> releasePin { &nextPin };
+ PIN_DIRECTION currentPinDir;
+ *hrOut = nextPin->QueryDirection(&currentPinDir);
+ 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<IEnumPins> 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<IPin> 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<IPin> 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<IPin> 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<IPin> 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<IEnumFilters> releaseEnumFilters { &filters };
+ if (!filters) {
+ qCDebug(qtDirectShowPlugin, "No filters found!");
+ return false;
+ }
+
+ IBaseFilter *nextFilter = nullptr;
+ while (S_OK == filters->Next(1, &nextFilter, 0)) {
+ const ScopedSafeRelease<IBaseFilter> releaseNextFilter { &nextFilter };
+ if (nextFilter && findAndConnect(nextFilter))
+ break;
+ }
+
+ return SUCCEEDED(*hrOut);
+}
diff --git a/src/plugins/directshow/helpers/directshowutils.h b/src/plugins/directshow/helpers/directshowutils.h
new file mode 100644
index 000000000..09c81c257
--- /dev/null
+++ b/src/plugins/directshow/helpers/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 <typename T>
+void safeRelease(T **iface) {
+ if (!iface)
+ return;
+
+ if (!*iface)
+ return;
+
+ (*iface)->Release();
+ *iface = nullptr;
+}
+
+template <typename T>
+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/helpers.pri b/src/plugins/directshow/helpers/helpers.pri
index b3743a680..ca883eeb8 100644
--- a/src/plugins/directshow/helpers/helpers.pri
+++ b/src/plugins/directshow/helpers/helpers.pri
@@ -9,7 +9,8 @@ HEADERS += \
$$PWD/directshowobject.h \
$$PWD/directshowpin.h \
$$PWD/directshowpinenum.h \
- $$PWD/directshowvideobuffer.h
+ $$PWD/directshowvideobuffer.h \
+ $$PWD/directshowutils.h
SOURCES += \
$$PWD/directshowbasefilter.cpp \
@@ -19,4 +20,5 @@ SOURCES += \
$$PWD/directshowobject.cpp \
$$PWD/directshowpin.cpp \
$$PWD/directshowpinenum.cpp \
- $$PWD/directshowvideobuffer.cpp
+ $$PWD/directshowvideobuffer.cpp \
+ $$PWD/directshowutils.cpp
diff --git a/src/plugins/directshow/player/directshowiosource.cpp b/src/plugins/directshow/player/directshowiosource.cpp
index 3c44dd1ed..96b4b14bf 100644
--- a/src/plugins/directshow/player/directshowiosource.cpp
+++ b/src/plugins/directshow/player/directshowiosource.cpp
@@ -82,7 +82,7 @@ DirectShowIOSource::DirectShowIOSource(DirectShowEventLoop *loop)
// The filter works in pull mode, the downstream filter is responsible for requesting
// samples from this one.
//
- AM_MEDIA_TYPE type =
+ AM_MEDIA_TYPE type
{
MEDIATYPE_Stream, // majortype
MEDIASUBTYPE_NULL, // subtype
@@ -99,7 +99,7 @@ DirectShowIOSource::DirectShowIOSource(DirectShowEventLoop *loop)
for (int i = 0; i < count; ++i) {
type.subtype = directshow_subtypes[i];
- m_supportedMediaTypes.append(type);
+ m_supportedMediaTypes.append(DirectShowMediaType(type));
}
}
@@ -371,12 +371,12 @@ HRESULT DirectShowIOSource::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
hr = pReceivePin->ReceiveConnection(this, pmt);
// Update the media type for the current connection.
if (SUCCEEDED(hr))
- m_connectionMediaType = *pmt;
+ DirectShowMediaType::copy(&m_connectionMediaType, pmt);
} else if (pmt && pmt->subtype == MEDIATYPE_NULL) { // - Partial type (Stream, but no subtype specified).
- m_connectionMediaType = *pmt;
+ DirectShowMediaType::copy(&m_connectionMediaType, pmt);
// Check if the receiving pin accepts any of the streaming subtypes.
for (const DirectShowMediaType &t : qAsConst(m_supportedMediaTypes)) {
- m_connectionMediaType.subtype = t.subtype;
+ m_connectionMediaType->subtype = t->subtype;
hr = pReceivePin->ReceiveConnection(this, &m_connectionMediaType);
if (SUCCEEDED(hr))
break;
@@ -477,7 +477,7 @@ HRESULT DirectShowIOSource::ConnectionMediaType(AM_MEDIA_TYPE *pmt)
return VFW_E_NOT_CONNECTED;
} else {
- DirectShowMediaType::copy(pmt, m_connectionMediaType);
+ DirectShowMediaType::copy(pmt, &m_connectionMediaType);
return S_OK;
}
diff --git a/src/plugins/directshow/player/directshowplayercontrol.cpp b/src/plugins/directshow/player/directshowplayercontrol.cpp
index fce488af2..2d0ee2d59 100644
--- a/src/plugins/directshow/player/directshowplayercontrol.cpp
+++ b/src/plugins/directshow/player/directshowplayercontrol.cpp
@@ -200,7 +200,7 @@ qreal DirectShowPlayerControl::playbackRate() const
void DirectShowPlayerControl::setPlaybackRate(qreal rate)
{
- if (m_playbackRate != rate) {
+ if (!qFuzzyCompare(m_playbackRate, rate)) {
m_service->setRate(rate);
emit playbackRateChanged(m_playbackRate = rate);
@@ -370,7 +370,7 @@ void DirectShowPlayerControl::updateMediaInfo(qint64 duration, int streamTypes,
void DirectShowPlayerControl::updatePlaybackRate(qreal rate)
{
- if (m_playbackRate != rate) {
+ if (!qFuzzyCompare(m_playbackRate, rate)) {
m_playbackRate = rate;
scheduleUpdate(PlaybackRateProperty);
diff --git a/src/plugins/directshow/player/directshowplayerservice.cpp b/src/plugins/directshow/player/directshowplayerservice.cpp
index 1554d194d..5fbb6ef05 100644
--- a/src/plugins/directshow/player/directshowplayerservice.cpp
+++ b/src/plugins/directshow/player/directshowplayerservice.cpp
@@ -629,13 +629,13 @@ int DirectShowPlayerService::findStreamTypes(IBaseFilter *source) const
for (IPin *pin = 0; pins->Next(1, &pin, 0) == S_OK; pin->Release()) {
PIN_DIRECTION direction;
if (pin->QueryDirection(&direction) == S_OK && direction == PINDIR_OUTPUT) {
- AM_MEDIA_TYPE connectionType;
+ DirectShowMediaType connectionType;
if (SUCCEEDED(pin->ConnectionMediaType(&connectionType))) {
IPin *peer = 0;
- if (connectionType.majortype == MEDIATYPE_Audio) {
+ if (connectionType->majortype == MEDIATYPE_Audio) {
streamTypes |= AudioStream;
- } else if (connectionType.majortype == MEDIATYPE_Video) {
+ } else if (connectionType->majortype == MEDIATYPE_Video) {
streamTypes |= VideoStream;
} else if (SUCCEEDED(pin->ConnectedTo(&peer))) {
PIN_INFO peerInfo;
diff --git a/src/plugins/directshow/player/directshowplayerservice.h b/src/plugins/directshow/player/directshowplayerservice.h
index b8d30e79a..d933bd660 100644
--- a/src/plugins/directshow/player/directshowplayerservice.h
+++ b/src/plugins/directshow/player/directshowplayerservice.h
@@ -186,6 +186,7 @@ private:
int m_pendingTasks;
int m_executingTask;
int m_executedTasks;
+ int m_streamTypes;
HANDLE m_taskHandle;
HANDLE m_eventHandle;
GraphStatus m_graphStatus;
@@ -195,20 +196,19 @@ private:
IBaseFilter *m_source;
IBaseFilter *m_audioOutput;
IBaseFilter *m_videoOutput;
- int m_streamTypes;
qreal m_rate;
qint64 m_position;
qint64 m_seekPosition;
qint64 m_duration;
- bool m_buffering;
- bool m_seekable;
- bool m_atEnd;
- bool m_dontCacheNextSeekResult;
QMediaTimeRange m_playbackRange;
QUrl m_url;
QMediaResourceList m_resources;
QString m_errorString;
QMutex m_mutex;
+ bool m_buffering;
+ bool m_seekable;
+ bool m_atEnd;
+ bool m_dontCacheNextSeekResult;
friend class DirectShowPlayerServiceThread;
};
diff --git a/src/plugins/directshow/player/videosurfacefilter.cpp b/src/plugins/directshow/player/videosurfacefilter.cpp
index 4cb97be39..13f767a85 100644
--- a/src/plugins/directshow/player/videosurfacefilter.cpp
+++ b/src/plugins/directshow/player/videosurfacefilter.cpp
@@ -63,8 +63,8 @@ public:
VideoSurfaceInputPin(VideoSurfaceFilter *filter);
// DirectShowPin
- bool isMediaTypeSupported(const DirectShowMediaType *type);
- bool setMediaType(const DirectShowMediaType *type);
+ bool isMediaTypeSupported(const AM_MEDIA_TYPE *type) override;
+ bool setMediaType(const AM_MEDIA_TYPE *type) override;
HRESULT completeConnection(IPin *pin);
HRESULT connectionEnded();
@@ -90,12 +90,12 @@ VideoSurfaceInputPin::VideoSurfaceInputPin(VideoSurfaceFilter *filter)
{
}
-bool VideoSurfaceInputPin::isMediaTypeSupported(const DirectShowMediaType *type)
+bool VideoSurfaceInputPin::isMediaTypeSupported(const AM_MEDIA_TYPE *type)
{
return m_videoSurfaceFilter->isMediaTypeSupported(type);
}
-bool VideoSurfaceInputPin::setMediaType(const DirectShowMediaType *type)
+bool VideoSurfaceInputPin::setMediaType(const AM_MEDIA_TYPE *type)
{
if (!DirectShowInputPin::setMediaType(type))
return false;
@@ -282,7 +282,7 @@ void VideoSurfaceFilter::supportedFormatsChanged()
}
}
-bool VideoSurfaceFilter::isMediaTypeSupported(const DirectShowMediaType *type)
+bool VideoSurfaceFilter::isMediaTypeSupported(const AM_MEDIA_TYPE *type)
{
if (type->majortype != MEDIATYPE_Video || type->bFixedSizeSamples == FALSE)
return false;
@@ -297,7 +297,7 @@ bool VideoSurfaceFilter::isMediaTypeSupported(const DirectShowMediaType *type)
return false;
}
-bool VideoSurfaceFilter::setMediaType(const DirectShowMediaType *type)
+bool VideoSurfaceFilter::setMediaType(const AM_MEDIA_TYPE *type)
{
if (!type) {
qCDebug(qLcRenderFilter, "clear media type");
@@ -305,7 +305,7 @@ bool VideoSurfaceFilter::setMediaType(const DirectShowMediaType *type)
m_bytesPerLine = 0;
return true;
} else {
- m_surfaceFormat = DirectShowMediaType::formatFromType(*type);
+ m_surfaceFormat = DirectShowMediaType::videoFormatFromType(type);
m_bytesPerLine = DirectShowMediaType::bytesPerLine(m_surfaceFormat);
qCDebug(qLcRenderFilter) << "setMediaType -->" << m_surfaceFormat;
return m_surfaceFormat.isValid();
@@ -478,7 +478,7 @@ HRESULT VideoSurfaceFilter::Receive(IMediaSample *pMediaSample)
// If the format dynamically changed, the sample contains information about the new format.
// We need to reset the format and restart the QAbstractVideoSurface.
if (m_pin->currentSampleProperties()->pMediaType
- && (!m_pin->setMediaType(reinterpret_cast<const DirectShowMediaType *>(m_pin->currentSampleProperties()->pMediaType))
+ && (!m_pin->setMediaType(m_pin->currentSampleProperties()->pMediaType)
|| !restartSurface())) {
qCWarning(qLcRenderFilter, " dynamic format change failed, aborting rendering");
NotifyEvent(EC_ERRORABORT, VFW_E_TYPE_NOT_ACCEPTED, 0);
diff --git a/src/plugins/directshow/player/videosurfacefilter.h b/src/plugins/directshow/player/videosurfacefilter.h
index 581e33c70..6d6cc7593 100644
--- a/src/plugins/directshow/player/videosurfacefilter.h
+++ b/src/plugins/directshow/player/videosurfacefilter.h
@@ -83,8 +83,8 @@ public:
STDMETHODIMP_(ULONG) GetMiscFlags();
// DirectShowPin (delegate)
- bool isMediaTypeSupported(const DirectShowMediaType *type);
- bool setMediaType(const DirectShowMediaType *type);
+ bool isMediaTypeSupported(const AM_MEDIA_TYPE *type);
+ bool setMediaType(const AM_MEDIA_TYPE *type);
HRESULT completeConnection(IPin *pin);
HRESULT connectionEnded();