summaryrefslogtreecommitdiff
path: root/src/plugins/directshow
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/directshow')
-rw-r--r--src/plugins/directshow/camera/camera.pri6
-rw-r--r--src/plugins/directshow/camera/dscameraimageprocessingcontrol.cpp74
-rw-r--r--src/plugins/directshow/camera/dscameraimageprocessingcontrol.h63
-rw-r--r--src/plugins/directshow/camera/dscameraservice.cpp6
-rw-r--r--src/plugins/directshow/camera/dscameraservice.h2
-rw-r--r--src/plugins/directshow/camera/dscamerasession.cpp312
-rw-r--r--src/plugins/directshow/camera/dscamerasession.h45
-rw-r--r--src/plugins/directshow/directshow.pro5
-rw-r--r--src/plugins/directshow/player/directshowaudioendpointcontrol.cpp2
-rw-r--r--src/plugins/directshow/player/directshowevrvideowindowcontrol.cpp61
-rw-r--r--src/plugins/directshow/player/directshowevrvideowindowcontrol.h55
-rw-r--r--src/plugins/directshow/player/directshowglobal.h12
-rw-r--r--src/plugins/directshow/player/directshowioreader.cpp2
-rw-r--r--src/plugins/directshow/player/directshowiosource.cpp2
-rw-r--r--src/plugins/directshow/player/directshowmetadatacontrol.cpp27
-rw-r--r--src/plugins/directshow/player/directshowmetadatacontrol.h7
-rw-r--r--src/plugins/directshow/player/directshowplayercontrol.cpp126
-rw-r--r--src/plugins/directshow/player/directshowplayercontrol.h8
-rw-r--r--src/plugins/directshow/player/directshowplayerservice.cpp93
-rw-r--r--src/plugins/directshow/player/directshowplayerservice.h10
-rw-r--r--src/plugins/directshow/player/directshowvideorenderercontrol.cpp40
-rw-r--r--src/plugins/directshow/player/directshowvideorenderercontrol.h3
-rw-r--r--src/plugins/directshow/player/player.pri23
-rw-r--r--src/plugins/directshow/player/videosurfacefilter.cpp36
-rw-r--r--src/plugins/directshow/player/vmr9videowindowcontrol.cpp7
25 files changed, 871 insertions, 156 deletions
diff --git a/src/plugins/directshow/camera/camera.pri b/src/plugins/directshow/camera/camera.pri
index 3a532f472..c6b16da59 100644
--- a/src/plugins/directshow/camera/camera.pri
+++ b/src/plugins/directshow/camera/camera.pri
@@ -14,7 +14,8 @@ HEADERS += \
$$PWD/dsimagecapturecontrol.h \
$$PWD/dscamerasession.h \
$$PWD/directshowglobal.h \
- $$PWD/dscameraviewfindersettingscontrol.h
+ $$PWD/dscameraviewfindersettingscontrol.h \
+ $$PWD/dscameraimageprocessingcontrol.h
SOURCES += \
$$PWD/dscameraservice.cpp \
@@ -23,7 +24,8 @@ SOURCES += \
$$PWD/dsvideodevicecontrol.cpp \
$$PWD/dsimagecapturecontrol.cpp \
$$PWD/dscamerasession.cpp \
- $$PWD/dscameraviewfindersettingscontrol.cpp
+ $$PWD/dscameraviewfindersettingscontrol.cpp \
+ $$PWD/dscameraimageprocessingcontrol.cpp
*-msvc*:INCLUDEPATH += $$(DXSDK_DIR)/include
LIBS += -lstrmiids -ldmoguids -luuid -lmsdmo -lole32 -loleaut32
diff --git a/src/plugins/directshow/camera/dscameraimageprocessingcontrol.cpp b/src/plugins/directshow/camera/dscameraimageprocessingcontrol.cpp
new file mode 100644
index 000000000..39fa471ec
--- /dev/null
+++ b/src/plugins/directshow/camera/dscameraimageprocessingcontrol.cpp
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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.
+**
+** 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.
+**
+** 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.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "dscameraimageprocessingcontrol.h"
+#include "dscamerasession.h"
+
+QT_BEGIN_NAMESPACE
+
+DSCameraImageProcessingControl::DSCameraImageProcessingControl(DSCameraSession *session)
+ : QCameraImageProcessingControl(session)
+ , m_session(session)
+{
+}
+
+DSCameraImageProcessingControl::~DSCameraImageProcessingControl()
+{
+}
+
+bool DSCameraImageProcessingControl::isParameterSupported(
+ QCameraImageProcessingControl::ProcessingParameter parameter) const
+{
+ return m_session->isImageProcessingParameterSupported(parameter);
+}
+
+bool DSCameraImageProcessingControl::isParameterValueSupported(
+ QCameraImageProcessingControl::ProcessingParameter parameter,
+ const QVariant &value) const
+{
+ return m_session->isImageProcessingParameterValueSupported(parameter, value);
+}
+
+QVariant DSCameraImageProcessingControl::parameter(
+ QCameraImageProcessingControl::ProcessingParameter parameter) const
+{
+ return m_session->imageProcessingParameter(parameter);
+}
+
+void DSCameraImageProcessingControl::setParameter(QCameraImageProcessingControl::ProcessingParameter parameter,
+ const QVariant &value)
+{
+ m_session->setImageProcessingParameter(parameter, value);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/directshow/camera/dscameraimageprocessingcontrol.h b/src/plugins/directshow/camera/dscameraimageprocessingcontrol.h
new file mode 100644
index 000000000..2e50fe14d
--- /dev/null
+++ b/src/plugins/directshow/camera/dscameraimageprocessingcontrol.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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.
+**
+** 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.
+**
+** 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.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DSCAMERAIMAGEPROCESSINGCONTROL_H
+#define DSCAMERAIMAGEPROCESSINGCONTROL_H
+
+#include <qcamera.h>
+#include <qcameraimageprocessingcontrol.h>
+
+QT_BEGIN_NAMESPACE
+
+class DSCameraSession;
+
+class DSCameraImageProcessingControl : public QCameraImageProcessingControl
+{
+ Q_OBJECT
+
+public:
+ DSCameraImageProcessingControl(DSCameraSession *session);
+ virtual ~DSCameraImageProcessingControl();
+
+ bool isParameterSupported(ProcessingParameter) const;
+ bool isParameterValueSupported(ProcessingParameter parameter, const QVariant &value) const;
+ QVariant parameter(ProcessingParameter parameter) const;
+ void setParameter(ProcessingParameter parameter, const QVariant &value);
+
+private:
+ DSCameraSession *m_session;
+};
+
+QT_END_NAMESPACE
+
+#endif // DSCAMERAIMAGEPROCESSINGCONTROL_H
diff --git a/src/plugins/directshow/camera/dscameraservice.cpp b/src/plugins/directshow/camera/dscameraservice.cpp
index 9fcd4de70..6c92df04b 100644
--- a/src/plugins/directshow/camera/dscameraservice.cpp
+++ b/src/plugins/directshow/camera/dscameraservice.cpp
@@ -41,6 +41,7 @@
#include "dsvideodevicecontrol.h"
#include "dsimagecapturecontrol.h"
#include "dscameraviewfindersettingscontrol.h"
+#include "dscameraimageprocessingcontrol.h"
QT_BEGIN_NAMESPACE
@@ -53,12 +54,14 @@ DSCameraService::DSCameraService(QObject *parent):
m_videoDevice = new DSVideoDeviceControl(m_session);
m_imageCapture = new DSImageCaptureControl(m_session);
m_viewfinderSettings = new DSCameraViewfinderSettingsControl(m_session);
+ m_imageProcessingControl = new DSCameraImageProcessingControl(m_session);
}
DSCameraService::~DSCameraService()
{
delete m_control;
delete m_viewfinderSettings;
+ delete m_imageProcessingControl;
delete m_videoDevice;
delete m_videoRenderer;
delete m_imageCapture;
@@ -86,6 +89,9 @@ QMediaControl* DSCameraService::requestControl(const char *name)
if (qstrcmp(name, QCameraViewfinderSettingsControl2_iid) == 0)
return m_viewfinderSettings;
+ if (qstrcmp(name, QCameraImageProcessingControl_iid) == 0)
+ return m_imageProcessingControl;
+
return 0;
}
diff --git a/src/plugins/directshow/camera/dscameraservice.h b/src/plugins/directshow/camera/dscameraservice.h
index c3c881d0e..05222ebc4 100644
--- a/src/plugins/directshow/camera/dscameraservice.h
+++ b/src/plugins/directshow/camera/dscameraservice.h
@@ -46,6 +46,7 @@ class DSVideoOutputControl;
class DSVideoDeviceControl;
class DSImageCaptureControl;
class DSCameraViewfinderSettingsControl;
+class DSCameraImageProcessingControl;
class DSCameraService : public QMediaService
{
@@ -66,6 +67,7 @@ private:
QMediaControl *m_videoRenderer;
DSImageCaptureControl *m_imageCapture;
DSCameraViewfinderSettingsControl *m_viewfinderSettings;
+ DSCameraImageProcessingControl *m_imageProcessingControl;
};
QT_END_NAMESPACE
diff --git a/src/plugins/directshow/camera/dscamerasession.cpp b/src/plugins/directshow/camera/dscamerasession.cpp
index 2d3aa1bce..2e92cb37d 100644
--- a/src/plugins/directshow/camera/dscamerasession.cpp
+++ b/src/plugins/directshow/camera/dscamerasession.cpp
@@ -230,6 +230,240 @@ void DSCameraSession::setViewfinderSettings(const QCameraViewfinderSettings &set
m_viewfinderSettings = settings;
}
+qreal DSCameraSession::scaledImageProcessingParameterValue(
+ const ImageProcessingParameterInfo &sourceValueInfo)
+{
+ if (sourceValueInfo.currentValue == sourceValueInfo.defaultValue) {
+ return 0.0f;
+ } else if (sourceValueInfo.currentValue < sourceValueInfo.defaultValue) {
+ return ((sourceValueInfo.currentValue - sourceValueInfo.minimumValue)
+ / qreal(sourceValueInfo.defaultValue - sourceValueInfo.minimumValue))
+ + (-1.0f);
+ } else {
+ return ((sourceValueInfo.currentValue - sourceValueInfo.defaultValue)
+ / qreal(sourceValueInfo.maximumValue - sourceValueInfo.defaultValue));
+ }
+}
+
+qint32 DSCameraSession::sourceImageProcessingParameterValue(
+ qreal scaledValue, const ImageProcessingParameterInfo &valueRange)
+{
+ if (qFuzzyIsNull(scaledValue)) {
+ return valueRange.defaultValue;
+ } else if (scaledValue < 0.0f) {
+ return ((scaledValue - (-1.0f)) * (valueRange.defaultValue - valueRange.minimumValue))
+ + valueRange.minimumValue;
+ } else {
+ return (scaledValue * (valueRange.maximumValue - valueRange.defaultValue))
+ + valueRange.defaultValue;
+ }
+}
+
+static QCameraImageProcessingControl::ProcessingParameter searchRelatedResultingParameter(
+ QCameraImageProcessingControl::ProcessingParameter sourceParameter)
+{
+ if (sourceParameter == QCameraImageProcessingControl::WhiteBalancePreset)
+ return QCameraImageProcessingControl::ColorTemperature;
+ return sourceParameter;
+}
+
+bool DSCameraSession::isImageProcessingParameterSupported(
+ QCameraImageProcessingControl::ProcessingParameter parameter) const
+{
+ const QCameraImageProcessingControl::ProcessingParameter resultingParameter =
+ searchRelatedResultingParameter(parameter);
+
+ return m_imageProcessingParametersInfos.contains(resultingParameter);
+}
+
+bool DSCameraSession::isImageProcessingParameterValueSupported(
+ QCameraImageProcessingControl::ProcessingParameter parameter,
+ const QVariant &value) const
+{
+ const QCameraImageProcessingControl::ProcessingParameter resultingParameter =
+ searchRelatedResultingParameter(parameter);
+
+ QMap<QCameraImageProcessingControl::ProcessingParameter,
+ ImageProcessingParameterInfo>::const_iterator sourceValueInfo =
+ m_imageProcessingParametersInfos.constFind(resultingParameter);
+
+ if (sourceValueInfo == m_imageProcessingParametersInfos.constEnd())
+ return false;
+
+ switch (parameter) {
+
+ case QCameraImageProcessingControl::WhiteBalancePreset: {
+ const QCameraImageProcessing::WhiteBalanceMode checkedValue =
+ value.value<QCameraImageProcessing::WhiteBalanceMode>();
+ // Supports only the Manual and the Auto values
+ if (checkedValue != QCameraImageProcessing::WhiteBalanceManual
+ && checkedValue != QCameraImageProcessing::WhiteBalanceAuto) {
+ return false;
+ }
+ }
+ break;
+
+ case QCameraImageProcessingControl::ColorTemperature: {
+ const qint32 checkedValue = value.toInt();
+ if (checkedValue < (*sourceValueInfo).minimumValue
+ || checkedValue > (*sourceValueInfo).maximumValue) {
+ return false;
+ }
+ }
+ break;
+
+ case QCameraImageProcessingControl::ContrastAdjustment: // falling back
+ case QCameraImageProcessingControl::SaturationAdjustment: // falling back
+ case QCameraImageProcessingControl::BrightnessAdjustment: // falling back
+ case QCameraImageProcessingControl::SharpeningAdjustment: {
+ const qint32 sourceValue = sourceImageProcessingParameterValue(
+ value.toReal(), (*sourceValueInfo));
+ if (sourceValue < (*sourceValueInfo).minimumValue
+ || sourceValue > (*sourceValueInfo).maximumValue)
+ return false;
+ }
+ break;
+
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+QVariant DSCameraSession::imageProcessingParameter(
+ QCameraImageProcessingControl::ProcessingParameter parameter) const
+{
+ if (!m_graphBuilder) {
+ qWarning() << "failed to access to the graph builder";
+ return QVariant();
+ }
+
+ const QCameraImageProcessingControl::ProcessingParameter resultingParameter =
+ searchRelatedResultingParameter(parameter);
+
+ QMap<QCameraImageProcessingControl::ProcessingParameter,
+ ImageProcessingParameterInfo>::const_iterator sourceValueInfo =
+ m_imageProcessingParametersInfos.constFind(resultingParameter);
+
+ if (sourceValueInfo == m_imageProcessingParametersInfos.constEnd())
+ return QVariant();
+
+ switch (parameter) {
+
+ case QCameraImageProcessingControl::WhiteBalancePreset:
+ return QVariant::fromValue<QCameraImageProcessing::WhiteBalanceMode>(
+ (*sourceValueInfo).capsFlags == VideoProcAmp_Flags_Auto
+ ? QCameraImageProcessing::WhiteBalanceAuto
+ : QCameraImageProcessing::WhiteBalanceManual);
+
+ case QCameraImageProcessingControl::ColorTemperature:
+ return QVariant::fromValue<qint32>((*sourceValueInfo).currentValue);
+
+ case QCameraImageProcessingControl::ContrastAdjustment: // falling back
+ case QCameraImageProcessingControl::SaturationAdjustment: // falling back
+ case QCameraImageProcessingControl::BrightnessAdjustment: // falling back
+ case QCameraImageProcessingControl::SharpeningAdjustment:
+ return scaledImageProcessingParameterValue((*sourceValueInfo));
+
+ default:
+ return QVariant();
+ }
+}
+
+void DSCameraSession::setImageProcessingParameter(
+ QCameraImageProcessingControl::ProcessingParameter parameter,
+ const QVariant &value)
+{
+ if (!m_graphBuilder) {
+ qWarning() << "failed to access to the graph builder";
+ return;
+ }
+
+ const QCameraImageProcessingControl::ProcessingParameter resultingParameter =
+ searchRelatedResultingParameter(parameter);
+
+ QMap<QCameraImageProcessingControl::ProcessingParameter,
+ ImageProcessingParameterInfo>::iterator sourceValueInfo =
+ m_imageProcessingParametersInfos.find(resultingParameter);
+
+ if (sourceValueInfo == m_imageProcessingParametersInfos.constEnd())
+ return;
+
+ LONG sourceValue = 0;
+ LONG capsFlags = VideoProcAmp_Flags_Manual;
+
+ switch (parameter) {
+
+ case QCameraImageProcessingControl::WhiteBalancePreset: {
+ const QCameraImageProcessing::WhiteBalanceMode checkedValue =
+ value.value<QCameraImageProcessing::WhiteBalanceMode>();
+ // Supports only the Manual and the Auto values
+ if (checkedValue == QCameraImageProcessing::WhiteBalanceManual)
+ capsFlags = VideoProcAmp_Flags_Manual;
+ else if (checkedValue == QCameraImageProcessing::WhiteBalanceAuto)
+ capsFlags = VideoProcAmp_Flags_Auto;
+ else
+ return;
+
+ sourceValue = ((*sourceValueInfo).hasBeenExplicitlySet)
+ ? (*sourceValueInfo).currentValue
+ : (*sourceValueInfo).defaultValue;
+ }
+ break;
+
+ case QCameraImageProcessingControl::ColorTemperature:
+ sourceValue = value.isValid() ?
+ value.value<qint32>() : (*sourceValueInfo).defaultValue;
+ capsFlags = (*sourceValueInfo).capsFlags;
+ break;
+
+ case QCameraImageProcessingControl::ContrastAdjustment: // falling back
+ case QCameraImageProcessingControl::SaturationAdjustment: // falling back
+ case QCameraImageProcessingControl::BrightnessAdjustment: // falling back
+ case QCameraImageProcessingControl::SharpeningAdjustment:
+ if (value.isValid()) {
+ sourceValue = sourceImageProcessingParameterValue(
+ value.toReal(), (*sourceValueInfo));
+ } else {
+ sourceValue = (*sourceValueInfo).defaultValue;
+ }
+ break;
+
+ default:
+ return;
+ }
+
+ IAMVideoProcAmp *pVideoProcAmp = NULL;
+ HRESULT hr = m_graphBuilder->FindInterface(
+ NULL,
+ NULL,
+ m_sourceFilter,
+ IID_IAMVideoProcAmp,
+ reinterpret_cast<void**>(&pVideoProcAmp)
+ );
+
+ if (FAILED(hr) || !pVideoProcAmp) {
+ qWarning() << "failed to find the video proc amp";
+ return;
+ }
+
+ hr = pVideoProcAmp->Set(
+ (*sourceValueInfo).videoProcAmpProperty,
+ sourceValue,
+ capsFlags);
+
+ pVideoProcAmp->Release();
+
+ if (FAILED(hr)) {
+ qWarning() << "failed to set the parameter value";
+ } else {
+ (*sourceValueInfo).capsFlags = capsFlags;
+ (*sourceValueInfo).hasBeenExplicitlySet = true;
+ (*sourceValueInfo).currentValue = sourceValue;
+ }
+}
+
bool DSCameraSession::load()
{
unload();
@@ -720,6 +954,81 @@ bool DSCameraSession::configurePreviewFormat()
return true;
}
+void DSCameraSession::updateImageProcessingParametersInfos()
+{
+ if (!m_graphBuilder) {
+ qWarning() << "failed to access to the graph builder";
+ return;
+ }
+
+ IAMVideoProcAmp *pVideoProcAmp = NULL;
+ const HRESULT hr = m_graphBuilder->FindInterface(
+ NULL,
+ NULL,
+ m_sourceFilter,
+ IID_IAMVideoProcAmp,
+ reinterpret_cast<void**>(&pVideoProcAmp)
+ );
+
+ if (FAILED(hr) || !pVideoProcAmp) {
+ qWarning() << "failed to find the video proc amp";
+ return;
+ }
+
+ for (int property = VideoProcAmp_Brightness; property <= VideoProcAmp_Gain; ++property) {
+
+ QCameraImageProcessingControl::ProcessingParameter processingParameter; // not initialized
+
+ switch (property) {
+ case VideoProcAmp_Brightness:
+ processingParameter = QCameraImageProcessingControl::BrightnessAdjustment;
+ break;
+ case VideoProcAmp_Contrast:
+ processingParameter = QCameraImageProcessingControl::ContrastAdjustment;
+ break;
+ case VideoProcAmp_Saturation:
+ processingParameter = QCameraImageProcessingControl::SaturationAdjustment;
+ break;
+ case VideoProcAmp_Sharpness:
+ processingParameter = QCameraImageProcessingControl::SharpeningAdjustment;
+ break;
+ case VideoProcAmp_WhiteBalance:
+ processingParameter = QCameraImageProcessingControl::ColorTemperature;
+ break;
+ default: // unsupported or not implemented yet parameter
+ continue;
+ }
+
+ ImageProcessingParameterInfo sourceValueInfo;
+ LONG steppingDelta = 0;
+
+ HRESULT hr = pVideoProcAmp->GetRange(
+ property,
+ &sourceValueInfo.minimumValue,
+ &sourceValueInfo.maximumValue,
+ &steppingDelta,
+ &sourceValueInfo.defaultValue,
+ &sourceValueInfo.capsFlags);
+
+ if (FAILED(hr))
+ continue;
+
+ hr = pVideoProcAmp->Get(
+ property,
+ &sourceValueInfo.currentValue,
+ &sourceValueInfo.capsFlags);
+
+ if (FAILED(hr))
+ continue;
+
+ sourceValueInfo.videoProcAmpProperty = static_cast<VideoProcAmpProperty>(property);
+
+ m_imageProcessingParametersInfos.insert(processingParameter, sourceValueInfo);
+ }
+
+ pVideoProcAmp->Release();
+}
+
bool DSCameraSession::connectGraph()
{
HRESULT hr = m_filterGraph->AddFilter(m_sourceFilter, L"Capture Filter");
@@ -806,6 +1115,7 @@ void DSCameraSession::updateSourceCapabilities()
Q_FOREACH (AM_MEDIA_TYPE f, m_supportedFormats)
_FreeMediaType(f);
m_supportedFormats.clear();
+ m_imageProcessingParametersInfos.clear();
IAMVideoControl *pVideoControl = 0;
hr = m_graphBuilder->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,
@@ -915,6 +1225,8 @@ void DSCameraSession::updateSourceCapabilities()
}
pConfig->Release();
+
+ updateImageProcessingParametersInfos();
}
HRESULT getPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir, IPin **ppPin)
diff --git a/src/plugins/directshow/camera/dscamerasession.h b/src/plugins/directshow/camera/dscamerasession.h
index 9ac121463..768e3583a 100644
--- a/src/plugins/directshow/camera/dscamerasession.h
+++ b/src/plugins/directshow/camera/dscamerasession.h
@@ -43,6 +43,7 @@
#include <QtMultimedia/qvideoframe.h>
#include <QtMultimedia/qabstractvideosurface.h>
#include <QtMultimedia/qvideosurfaceformat.h>
+#include <QtMultimedia/qcameraimageprocessingcontrol.h>
#include <private/qmediastoragelocation_p.h>
#include <tchar.h>
@@ -97,6 +98,20 @@ public:
QList<QCameraViewfinderSettings> supportedViewfinderSettings() const
{ return m_supportedViewfinderSettings; }
+ bool isImageProcessingParameterSupported(
+ QCameraImageProcessingControl::ProcessingParameter) const;
+
+ bool isImageProcessingParameterValueSupported(
+ QCameraImageProcessingControl::ProcessingParameter,
+ const QVariant &) const;
+
+ QVariant imageProcessingParameter(
+ QCameraImageProcessingControl::ProcessingParameter) const;
+
+ void setImageProcessingParameter(
+ QCameraImageProcessingControl::ProcessingParameter,
+ const QVariant &);
+
Q_SIGNALS:
void statusChanged(QCamera::Status);
void imageExposed(int id);
@@ -110,6 +125,27 @@ private Q_SLOTS:
void updateReadyForCapture();
private:
+ struct ImageProcessingParameterInfo {
+ ImageProcessingParameterInfo()
+ : minimumValue(0)
+ , maximumValue(0)
+ , defaultValue(0)
+ , currentValue(0)
+ , capsFlags(0)
+ , hasBeenExplicitlySet(false)
+ , videoProcAmpProperty(VideoProcAmp_Brightness)
+ {
+ }
+
+ LONG minimumValue;
+ LONG maximumValue;
+ LONG defaultValue;
+ LONG currentValue;
+ LONG capsFlags;
+ bool hasBeenExplicitlySet;
+ VideoProcAmpProperty videoProcAmpProperty;
+ };
+
void setStatus(QCamera::Status status);
void onFrameAvailable(const char *frameData, long len);
@@ -120,6 +156,14 @@ private:
void disconnectGraph();
void updateSourceCapabilities();
bool configurePreviewFormat();
+ void updateImageProcessingParametersInfos();
+
+ // These static functions are used for scaling of adjustable parameters,
+ // which have the ranges from -1.0 to +1.0 in the QCameraImageProcessing API.
+ static qreal scaledImageProcessingParameterValue(
+ const ImageProcessingParameterInfo &sourceValueInfo);
+ static qint32 sourceImageProcessingParameterValue(
+ qreal scaledValue, const ImageProcessingParameterInfo &sourceValueInfo);
QMutex m_presentMutex;
QMutex m_captureMutex;
@@ -135,6 +179,7 @@ private:
QList<AM_MEDIA_TYPE> m_supportedFormats;
QList<QCameraViewfinderSettings> m_supportedViewfinderSettings;
AM_MEDIA_TYPE m_sourceFormat;
+ QMap<QCameraImageProcessingControl::ProcessingParameter, ImageProcessingParameterInfo> m_imageProcessingParametersInfos;
// Preview
IBaseFilter *m_previewFilter;
diff --git a/src/plugins/directshow/directshow.pro b/src/plugins/directshow/directshow.pro
index 7815927db..4d7183923 100644
--- a/src/plugins/directshow/directshow.pro
+++ b/src/plugins/directshow/directshow.pro
@@ -13,11 +13,6 @@ SOURCES += dsserviceplugin.cpp
!config_wmsdk: DEFINES += QT_NO_WMSDK
-qtHaveModule(widgets) {
- QT += multimediawidgets
- DEFINES += HAVE_WIDGETS
-}
-
mingw: DEFINES += NO_DSHOW_STRSAFE
!config_wmf: include(player/player.pri)
diff --git a/src/plugins/directshow/player/directshowaudioendpointcontrol.cpp b/src/plugins/directshow/player/directshowaudioendpointcontrol.cpp
index 798a94102..d063447e3 100644
--- a/src/plugins/directshow/player/directshowaudioendpointcontrol.cpp
+++ b/src/plugins/directshow/player/directshowaudioendpointcontrol.cpp
@@ -44,7 +44,7 @@ DirectShowAudioEndpointControl::DirectShowAudioEndpointControl(
, m_deviceEnumerator(0)
{
if (CreateBindCtx(0, &m_bindContext) == S_OK) {
- m_deviceEnumerator = com_new<ICreateDevEnum>(CLSID_SystemDeviceEnum, IID_ICreateDevEnum);
+ m_deviceEnumerator = com_new<ICreateDevEnum>(CLSID_SystemDeviceEnum);
updateEndpoints();
diff --git a/src/plugins/directshow/player/directshowevrvideowindowcontrol.cpp b/src/plugins/directshow/player/directshowevrvideowindowcontrol.cpp
new file mode 100644
index 000000000..22771bd4c
--- /dev/null
+++ b/src/plugins/directshow/player/directshowevrvideowindowcontrol.cpp
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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.
+**
+** 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.
+**
+** 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.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "directshowevrvideowindowcontrol.h"
+
+#include "directshowglobal.h"
+
+DirectShowEvrVideoWindowControl::DirectShowEvrVideoWindowControl(QObject *parent)
+ : EvrVideoWindowControl(parent)
+ , m_evrFilter(NULL)
+{
+}
+
+DirectShowEvrVideoWindowControl::~DirectShowEvrVideoWindowControl()
+{
+ if (m_evrFilter)
+ m_evrFilter->Release();
+}
+
+IBaseFilter *DirectShowEvrVideoWindowControl::filter()
+{
+ if (!m_evrFilter) {
+ m_evrFilter = com_new<IBaseFilter>(clsid_EnhancedVideoRenderer);
+ if (!setEvr(m_evrFilter)) {
+ m_evrFilter->Release();
+ m_evrFilter = NULL;
+ }
+ }
+
+ return m_evrFilter;
+}
diff --git a/src/plugins/directshow/player/directshowevrvideowindowcontrol.h b/src/plugins/directshow/player/directshowevrvideowindowcontrol.h
new file mode 100644
index 000000000..46171812b
--- /dev/null
+++ b/src/plugins/directshow/player/directshowevrvideowindowcontrol.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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.
+**
+** 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.
+**
+** 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.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DIRECTSHOWEVRVIDEOWINDOWCONTROL_H
+#define DIRECTSHOWEVRVIDEOWINDOWCONTROL_H
+
+#include "evrvideowindowcontrol.h"
+
+struct IBaseFilter;
+
+QT_USE_NAMESPACE
+
+class DirectShowEvrVideoWindowControl : public EvrVideoWindowControl
+{
+public:
+ DirectShowEvrVideoWindowControl(QObject *parent = 0);
+ ~DirectShowEvrVideoWindowControl();
+
+ IBaseFilter *filter();
+
+private:
+ IBaseFilter *m_evrFilter;
+};
+
+#endif // DIRECTSHOWEVRVIDEOWINDOWCONTROL_H
diff --git a/src/plugins/directshow/player/directshowglobal.h b/src/plugins/directshow/player/directshowglobal.h
index 68cb23649..d8f1d1200 100644
--- a/src/plugins/directshow/player/directshowglobal.h
+++ b/src/plugins/directshow/player/directshowglobal.h
@@ -46,6 +46,18 @@ template <typename T> T *com_cast(IUnknown *unknown, const IID &iid)
: 0;
}
+template <typename T> T *com_new(const IID &clsid)
+{
+ T *object = 0;
+ return CoCreateInstance(
+ clsid,
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ IID_PPV_ARGS(&object)) == S_OK
+ ? object
+ : 0;
+}
+
template <typename T> T *com_new(const IID &clsid, const IID &iid)
{
T *object = 0;
diff --git a/src/plugins/directshow/player/directshowioreader.cpp b/src/plugins/directshow/player/directshowioreader.cpp
index bee072d3b..298d099d2 100644
--- a/src/plugins/directshow/player/directshowioreader.cpp
+++ b/src/plugins/directshow/player/directshowioreader.cpp
@@ -132,7 +132,7 @@ HRESULT DirectShowIOReader::RequestAllocator(
return S_OK;
} else {
- *ppActual = com_new<IMemAllocator>(CLSID_MemoryAllocator, IID_IMemAllocator);
+ *ppActual = com_new<IMemAllocator>(CLSID_MemoryAllocator);
if (*ppActual) {
if ((*ppActual)->SetProperties(pProps, &actualProperties) != S_OK) {
diff --git a/src/plugins/directshow/player/directshowiosource.cpp b/src/plugins/directshow/player/directshowiosource.cpp
index 424120fd8..e1034a9c6 100644
--- a/src/plugins/directshow/player/directshowiosource.cpp
+++ b/src/plugins/directshow/player/directshowiosource.cpp
@@ -413,7 +413,7 @@ HRESULT DirectShowIOSource::tryConnect(IPin *pin, const AM_MEDIA_TYPE *type)
hr = VFW_E_NO_TRANSPORT;
if (IMemInputPin *memPin = com_cast<IMemInputPin>(pin, IID_IMemInputPin)) {
- if ((m_allocator = com_new<IMemAllocator>(CLSID_MemoryAllocator, IID_IMemAllocator))) {
+ if ((m_allocator = com_new<IMemAllocator>(CLSID_MemoryAllocator))) {
ALLOCATOR_PROPERTIES properties;
if (memPin->GetAllocatorRequirements(&properties) == S_OK
|| m_allocator->GetProperties(&properties) == S_OK) {
diff --git a/src/plugins/directshow/player/directshowmetadatacontrol.cpp b/src/plugins/directshow/player/directshowmetadatacontrol.cpp
index 3f58be249..5400ac8d4 100644
--- a/src/plugins/directshow/player/directshowmetadatacontrol.cpp
+++ b/src/plugins/directshow/player/directshowmetadatacontrol.cpp
@@ -362,7 +362,18 @@ static QString convertBSTR(BSTR *string)
return value;
}
-void DirectShowMetaDataControl::updateGraph(IFilterGraph2 *graph, IBaseFilter *source, const QString &fileSrc)
+void DirectShowMetaDataControl::reset()
+{
+ bool hadMetadata = !m_metadata.isEmpty();
+ m_metadata.clear();
+
+ setMetadataAvailable(false);
+
+ if (hadMetadata)
+ emit metaDataChanged();
+}
+
+void DirectShowMetaDataControl::updateMetadata(IFilterGraph2 *graph, IBaseFilter *source, const QString &fileSrc)
{
m_metadata.clear();
@@ -568,13 +579,19 @@ void DirectShowMetaDataControl::customEvent(QEvent *event)
if (event->type() == QEvent::Type(MetaDataChanged)) {
event->accept();
- bool oldAvailable = m_available;
- m_available = !m_metadata.isEmpty();
- if (m_available != oldAvailable)
- emit metaDataAvailableChanged(m_available);
+ setMetadataAvailable(!m_metadata.isEmpty());
emit metaDataChanged();
} else {
QMetaDataReaderControl::customEvent(event);
}
}
+
+void DirectShowMetaDataControl::setMetadataAvailable(bool available)
+{
+ if (m_available == available)
+ return;
+
+ m_available = available;
+ emit metaDataAvailableChanged(m_available);
+}
diff --git a/src/plugins/directshow/player/directshowmetadatacontrol.h b/src/plugins/directshow/player/directshowmetadatacontrol.h
index d32ae8508..55504ba4b 100644
--- a/src/plugins/directshow/player/directshowmetadatacontrol.h
+++ b/src/plugins/directshow/player/directshowmetadatacontrol.h
@@ -56,13 +56,16 @@ public:
QVariant metaData(const QString &key) const;
QStringList availableMetaData() const;
- void updateGraph(IFilterGraph2 *graph, IBaseFilter *source,
- const QString &fileSrc = QString());
+ void reset();
+ void updateMetadata(IFilterGraph2 *graph, IBaseFilter *source,
+ const QString &fileSrc = QString());
protected:
void customEvent(QEvent *event);
private:
+ void setMetadataAvailable(bool available);
+
enum Event
{
MetaDataChanged = QEvent::User
diff --git a/src/plugins/directshow/player/directshowplayercontrol.cpp b/src/plugins/directshow/player/directshowplayercontrol.cpp
index a5fed4b95..3449c9270 100644
--- a/src/plugins/directshow/player/directshowplayercontrol.cpp
+++ b/src/plugins/directshow/player/directshowplayercontrol.cpp
@@ -53,17 +53,6 @@ static int volumeToDecibels(int volume)
}
}
-static int decibelsToVolume(int dB)
-{
- if (dB == -10000) {
- return 0;
- } else if (dB == 0) {
- return 100;
- } else {
- return qRound(100 * qPow(10, qreal(dB) / 5000));
- }
-}
-
DirectShowPlayerControl::DirectShowPlayerControl(DirectShowPlayerService *service, QObject *parent)
: QMediaPlayerControl(parent)
, m_service(service)
@@ -73,8 +62,9 @@ DirectShowPlayerControl::DirectShowPlayerControl(DirectShowPlayerService *servic
, m_status(QMediaPlayer::NoMedia)
, m_error(QMediaPlayer::NoError)
, m_streamTypes(0)
- , m_muteVolume(-1)
- , m_position(0)
+ , m_volume(100)
+ , m_muted(false)
+ , m_emitPosition(-1)
, m_pendingPosition(-1)
, m_duration(0)
, m_playbackRate(0)
@@ -108,11 +98,16 @@ qint64 DirectShowPlayerControl::position() const
if (m_pendingPosition != -1)
return m_pendingPosition;
- return const_cast<qint64 &>(m_position) = m_service->position();
+ return m_service->position();
}
void DirectShowPlayerControl::setPosition(qint64 position)
{
+ if (m_status == QMediaPlayer::EndOfMedia) {
+ m_status = QMediaPlayer::LoadedMedia;
+ emit mediaStatusChanged(m_status);
+ }
+
if (m_state == QMediaPlayer::StoppedState && m_pendingPosition != position) {
m_pendingPosition = position;
emit positionChanged(m_pendingPosition);
@@ -125,63 +120,47 @@ void DirectShowPlayerControl::setPosition(qint64 position)
int DirectShowPlayerControl::volume() const
{
- if (m_muteVolume >= 0) {
- return m_muteVolume;
- } else if (m_audio) {
- long dB = 0;
-
- m_audio->get_Volume(&dB);
-
- return decibelsToVolume(dB);
- } else {
- return 0;
- }
+ return m_volume;
}
void DirectShowPlayerControl::setVolume(int volume)
{
int boundedVolume = qBound(0, volume, 100);
- if (m_muteVolume >= 0) {
- m_muteVolume = boundedVolume;
+ if (m_volume == boundedVolume)
+ return;
- emit volumeChanged(m_muteVolume);
- } else if (m_audio) {
- m_audio->put_Volume(volumeToDecibels(volume));
+ m_volume = boundedVolume;
- emit volumeChanged(boundedVolume);
- }
+ if (!m_muted)
+ setVolumeHelper(m_volume);
+
+ emit volumeChanged(m_volume);
}
bool DirectShowPlayerControl::isMuted() const
{
- return m_muteVolume >= 0;
+ return m_muted;
}
void DirectShowPlayerControl::setMuted(bool muted)
{
- if (muted && m_muteVolume < 0) {
- if (m_audio) {
- long dB = 0;
+ if (m_muted == muted)
+ return;
- m_audio->get_Volume(&dB);
+ m_muted = muted;
- m_muteVolume = decibelsToVolume(dB);
+ setVolumeHelper(m_muted ? 0 : m_volume);
- m_audio->put_Volume(-10000);
- } else {
- m_muteVolume = 0;
- }
+ emit mutedChanged(m_muted);
+}
- emit mutedChanged(muted);
- } else if (!muted && m_muteVolume >= 0) {
- if (m_audio) {
- m_audio->put_Volume(volumeToDecibels(m_muteVolume));
- }
- m_muteVolume = -1;
+void DirectShowPlayerControl::setVolumeHelper(int volume)
+{
+ if (!m_audio)
+ return;
- emit mutedChanged(muted);
- }
+ m_audio->put_Volume(volumeToDecibels(volume));
}
int DirectShowPlayerControl::bufferStatus() const
@@ -235,6 +214,9 @@ const QIODevice *DirectShowPlayerControl::mediaStream() const
void DirectShowPlayerControl::setMedia(const QMediaContent &media, QIODevice *stream)
{
+ m_pendingPosition = -1;
+ m_emitPosition = -1;
+
m_media = media;
m_stream = stream;
@@ -248,34 +230,41 @@ void DirectShowPlayerControl::setMedia(const QMediaContent &media, QIODevice *st
void DirectShowPlayerControl::play()
{
- if (m_status == QMediaPlayer::NoMedia)
- return;
- if (m_status == QMediaPlayer::InvalidMedia) {
- setMedia(m_media, m_stream);
- if (m_error != QMediaPlayer::NoError)
- return;
- }
- m_service->play();
- if (m_pendingPosition != -1)
- setPosition(m_pendingPosition);
- emit stateChanged(m_state = QMediaPlayer::PlayingState);
+ playOrPause(QMediaPlayer::PlayingState);
}
void DirectShowPlayerControl::pause()
{
- if (m_status == QMediaPlayer::NoMedia)
+ playOrPause(QMediaPlayer::PausedState);
+}
+
+void DirectShowPlayerControl::playOrPause(QMediaPlayer::State state)
+{
+ if (m_status == QMediaPlayer::NoMedia || state == QMediaPlayer::StoppedState)
return;
if (m_status == QMediaPlayer::InvalidMedia) {
setMedia(m_media, m_stream);
if (m_error != QMediaPlayer::NoError)
return;
}
- m_service->pause();
- emit stateChanged(m_state = QMediaPlayer::PausedState);
+
+ m_emitPosition = -1;
+ m_state = state;
+
+ if (m_pendingPosition != -1)
+ setPosition(m_pendingPosition);
+
+ if (state == QMediaPlayer::PausedState)
+ m_service->pause();
+ else
+ m_service->play();
+
+ emit stateChanged(m_state);
}
void DirectShowPlayerControl::stop()
{
+ m_emitPosition = -1;
m_service->stop();
emit stateChanged(m_state = QMediaPlayer::StoppedState);
}
@@ -307,8 +296,8 @@ void DirectShowPlayerControl::emitPropertyChanges()
emit videoAvailableChanged(m_streamTypes & DirectShowPlayerService::VideoStream);
}
- if (properties & PositionProperty)
- emit positionChanged(m_position);
+ if (properties & PositionProperty && m_emitPosition != -1)
+ emit positionChanged(m_emitPosition);
if (properties & DurationProperty)
emit durationChanged(m_duration);
@@ -389,6 +378,7 @@ void DirectShowPlayerControl::updateAudioOutput(IBaseFilter *filter)
m_audio->Release();
m_audio = com_cast<IBasicAudio>(filter, IID_IBasicAudio);
+ setVolumeHelper(m_muted ? 0 : m_volume);
}
void DirectShowPlayerControl::updateError(QMediaPlayer::Error error, const QString &errorString)
@@ -402,8 +392,8 @@ void DirectShowPlayerControl::updateError(QMediaPlayer::Error error, const QStri
void DirectShowPlayerControl::updatePosition(qint64 position)
{
- if (m_position != position) {
- m_position = position;
+ if (m_emitPosition != position) {
+ m_emitPosition = position;
scheduleUpdate(PositionProperty);
}
diff --git a/src/plugins/directshow/player/directshowplayercontrol.h b/src/plugins/directshow/player/directshowplayercontrol.h
index a42d3c7b1..f67c4108b 100644
--- a/src/plugins/directshow/player/directshowplayercontrol.h
+++ b/src/plugins/directshow/player/directshowplayercontrol.h
@@ -114,8 +114,11 @@ private:
PropertiesChanged = QEvent::User
};
+ void playOrPause(QMediaPlayer::State state);
+
void scheduleUpdate(int properties);
void emitPropertyChanges();
+ void setVolumeHelper(int volume);
DirectShowPlayerService *m_service;
IBasicAudio *m_audio;
@@ -125,8 +128,9 @@ private:
QMediaPlayer::MediaStatus m_status;
QMediaPlayer::Error m_error;
int m_streamTypes;
- int m_muteVolume;
- qint64 m_position;
+ int m_volume;
+ bool m_muted;
+ qint64 m_emitPosition;
qint64 m_pendingPosition;
qint64 m_duration;
qreal m_playbackRate;
diff --git a/src/plugins/directshow/player/directshowplayerservice.cpp b/src/plugins/directshow/player/directshowplayerservice.cpp
index 67aea6e9a..8e9e50cbf 100644
--- a/src/plugins/directshow/player/directshowplayerservice.cpp
+++ b/src/plugins/directshow/player/directshowplayerservice.cpp
@@ -38,8 +38,10 @@
#include "directshowmetadatacontrol.h"
#include "directshowplayercontrol.h"
#include "directshowvideorenderercontrol.h"
-#if defined(HAVE_WIDGETS) && !defined(Q_WS_SIMULATOR)
#include "vmr9videowindowcontrol.h"
+
+#ifdef HAVE_EVR
+#include "directshowevrvideowindowcontrol.h"
#endif
#ifndef QT_NO_WMSDK
@@ -79,9 +81,7 @@ DirectShowPlayerService::DirectShowPlayerService(QObject *parent)
, m_playerControl(0)
, m_metaDataControl(0)
, m_videoRendererControl(0)
-#if defined(HAVE_WIDGETS) && !defined(Q_WS_SIMULATOR)
, m_videoWindowControl(0)
-#endif
, m_audioEndpointControl(0)
, m_taskThread(0)
, m_loop(qt_directShowEventLoop())
@@ -98,10 +98,12 @@ DirectShowPlayerService::DirectShowPlayerService(QObject *parent)
, m_videoOutput(0)
, m_rate(1.0)
, m_position(0)
+ , m_seekPosition(-1)
, m_duration(0)
, m_buffering(false)
, m_seekable(false)
, m_atEnd(false)
+ , m_dontCacheNextSeekResult(false)
{
m_playerControl = new DirectShowPlayerControl(this);
m_metaDataControl = new DirectShowMetaDataControl(this);
@@ -139,9 +141,7 @@ DirectShowPlayerService::~DirectShowPlayerService()
delete m_audioEndpointControl;
delete m_metaDataControl;
delete m_videoRendererControl;
-#if defined(HAVE_WIDGETS) && !defined(Q_WS_SIMULATOR)
delete m_videoWindowControl;
-#endif
::CloseHandle(m_taskHandle);
}
@@ -155,11 +155,7 @@ QMediaControl *DirectShowPlayerService::requestControl(const char *name)
} else if (qstrcmp(name, QMetaDataReaderControl_iid) == 0) {
return m_metaDataControl;
} else if (qstrcmp(name, QVideoRendererControl_iid) == 0) {
-#if defined(HAVE_WIDGETS) && !defined(Q_WS_SIMULATOR)
if (!m_videoRendererControl && !m_videoWindowControl) {
-#else
- if (!m_videoRendererControl) {
-#endif
m_videoRendererControl = new DirectShowVideoRendererControl(m_loop);
connect(m_videoRendererControl, SIGNAL(filterChanged()),
@@ -167,16 +163,28 @@ QMediaControl *DirectShowPlayerService::requestControl(const char *name)
return m_videoRendererControl;
}
-#if defined(HAVE_WIDGETS) && !defined(Q_WS_SIMULATOR)
} else if (qstrcmp(name, QVideoWindowControl_iid) == 0) {
if (!m_videoRendererControl && !m_videoWindowControl) {
- m_videoWindowControl = new Vmr9VideoWindowControl;
+ IBaseFilter *filter;
- setVideoOutput(m_videoWindowControl->filter());
+#ifdef HAVE_EVR
+ DirectShowEvrVideoWindowControl *evrControl = new DirectShowEvrVideoWindowControl;
+ if ((filter = evrControl->filter()))
+ m_videoWindowControl = evrControl;
+ else
+ delete evrControl;
+#endif
+ // Fall back to the VMR9 if the EVR is not available
+ if (!m_videoWindowControl) {
+ Vmr9VideoWindowControl *vmr9Control = new Vmr9VideoWindowControl;
+ filter = vmr9Control->filter();
+ m_videoWindowControl = vmr9Control;
+ }
+
+ setVideoOutput(filter);
return m_videoWindowControl;
}
-#endif
}
return 0;
}
@@ -192,14 +200,12 @@ void DirectShowPlayerService::releaseControl(QMediaControl *control)
delete m_videoRendererControl;
m_videoRendererControl = 0;
-#if defined(HAVE_WIDGETS) && !defined(Q_WS_SIMULATOR)
} else if (control == m_videoWindowControl) {
setVideoOutput(0);
delete m_videoWindowControl;
m_videoWindowControl = 0;
-#endif
}
}
@@ -217,13 +223,15 @@ void DirectShowPlayerService::load(const QMediaContent &media, QIODevice *stream
m_error = QMediaPlayer::NoError;
m_errorString = QString();
m_position = 0;
+ m_seekPosition = -1;
m_duration = 0;
m_streamTypes = 0;
m_executedTasks = 0;
m_buffering = false;
m_seekable = false;
m_atEnd = false;
- m_metaDataControl->updateGraph(0, 0);
+ m_dontCacheNextSeekResult = false;
+ m_metaDataControl->reset();
if (m_resources.isEmpty() && !stream) {
m_pendingTasks = 0;
@@ -273,8 +281,7 @@ void DirectShowPlayerService::doSetUrlSource(QMutexLocker *locker)
static const GUID iid_IFileSourceFilter = {
0x56a868a6, 0x0ad4, 0x11ce, {0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70} };
- if (IFileSourceFilter *fileSource = com_new<IFileSourceFilter>(
- clsid_WMAsfReader, iid_IFileSourceFilter)) {
+ if (IFileSourceFilter *fileSource = com_new<IFileSourceFilter>(clsid_WMAsfReader, iid_IFileSourceFilter)) {
locker->unlock();
hr = fileSource->Load(reinterpret_cast<const OLECHAR *>(m_url.toString().utf16()), 0);
@@ -322,6 +329,7 @@ void DirectShowPlayerService::doSetUrlSource(QMutexLocker *locker)
m_error = QMediaPlayer::FormatError;
m_errorString = QString();
break;
+ case E_FAIL:
case E_OUTOFMEMORY:
case VFW_E_CANNOT_LOAD_SOURCE_FILTER:
case VFW_E_NOT_FOUND:
@@ -562,9 +570,6 @@ void DirectShowPlayerService::doReleaseGraph(QMutexLocker *locker)
control->Release();
}
- //release m_headerInfo -> decrease ref counter of m_source
- m_metaDataControl->updateGraph(0, 0);
-
if (m_source) {
m_source->Release();
m_source = 0;
@@ -665,8 +670,12 @@ void DirectShowPlayerService::play()
if (m_executedTasks & Render) {
if (m_executedTasks & Stop) {
m_atEnd = false;
- m_position = 0;
- m_pendingTasks |= Seek;
+ if (m_seekPosition == -1) {
+ m_dontCacheNextSeekResult = true;
+ m_seekPosition = 0;
+ m_position = 0;
+ m_pendingTasks |= Seek;
+ }
m_executedTasks ^= Stop;
}
@@ -709,8 +718,12 @@ void DirectShowPlayerService::pause()
if (m_executedTasks & Render) {
if (m_executedTasks & Stop) {
m_atEnd = false;
- m_position = 0;
- m_pendingTasks |= Seek;
+ if (m_seekPosition == -1) {
+ m_dontCacheNextSeekResult = true;
+ m_seekPosition = 0;
+ m_position = 0;
+ m_pendingTasks |= Seek;
+ }
m_executedTasks ^= Stop;
}
@@ -780,7 +793,9 @@ void DirectShowPlayerService::doStop(QMutexLocker *locker)
control->Release();
}
+ m_seekPosition = 0;
m_position = 0;
+ m_dontCacheNextSeekResult = true;
m_pendingTasks |= Seek;
m_executedTasks &= ~(Play | Pause);
@@ -884,7 +899,7 @@ void DirectShowPlayerService::seek(qint64 position)
{
QMutexLocker locker(&m_mutex);
- m_position = position;
+ m_seekPosition = position;
m_pendingTasks |= Seek;
@@ -894,14 +909,19 @@ void DirectShowPlayerService::seek(qint64 position)
void DirectShowPlayerService::doSeek(QMutexLocker *locker)
{
+ if (m_seekPosition == -1)
+ return;
+
if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) {
- LONGLONG seekPosition = LONGLONG(m_position) * qt_directShowTimeScale;
+ LONGLONG seekPosition = LONGLONG(m_seekPosition) * qt_directShowTimeScale;
// Cache current values as we can't query IMediaSeeking during a seek due to the
// possibility of a deadlock when flushing the VideoSurfaceFilter.
LONGLONG currentPosition = 0;
- seeking->GetCurrentPosition(&currentPosition);
- m_position = currentPosition / qt_directShowTimeScale;
+ if (!m_dontCacheNextSeekResult) {
+ seeking->GetCurrentPosition(&currentPosition);
+ m_position = currentPosition / qt_directShowTimeScale;
+ }
LONGLONG minimum = 0;
LONGLONG maximum = 0;
@@ -915,15 +935,18 @@ void DirectShowPlayerService::doSeek(QMutexLocker *locker)
&seekPosition, AM_SEEKING_AbsolutePositioning, 0, AM_SEEKING_NoPositioning);
locker->relock();
- seeking->GetCurrentPosition(&currentPosition);
- m_position = currentPosition / qt_directShowTimeScale;
+ if (!m_dontCacheNextSeekResult) {
+ seeking->GetCurrentPosition(&currentPosition);
+ m_position = currentPosition / qt_directShowTimeScale;
+ }
seeking->Release();
- } else {
- m_position = 0;
+
+ QCoreApplication::postEvent(this, new QEvent(QEvent::Type(PositionChange)));
}
- QCoreApplication::postEvent(this, new QEvent(QEvent::Type(PositionChange)));
+ m_seekPosition = -1;
+ m_dontCacheNextSeekResult = false;
}
int DirectShowPlayerService::bufferStatus() const
@@ -1112,7 +1135,7 @@ void DirectShowPlayerService::customEvent(QEvent *event)
QMutexLocker locker(&m_mutex);
m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable);
- m_metaDataControl->updateGraph(m_graph, m_source, m_url.toString());
+ m_metaDataControl->updateMetadata(m_graph, m_source, m_url.toString());
updateStatus();
} else if (event->type() == QEvent::Type(Error)) {
diff --git a/src/plugins/directshow/player/directshowplayerservice.h b/src/plugins/directshow/player/directshowplayerservice.h
index c9d10351e..4d3762f74 100644
--- a/src/plugins/directshow/player/directshowplayerservice.h
+++ b/src/plugins/directshow/player/directshowplayerservice.h
@@ -51,12 +51,10 @@ class DirectShowAudioEndpointControl;
class DirectShowMetaDataControl;
class DirectShowPlayerControl;
class DirectShowVideoRendererControl;
-#if defined(HAVE_WIDGETS) && !defined(Q_WS_SIMULATOR)
-class Vmr9VideoWindowControl;
-#endif
QT_BEGIN_NAMESPACE
class QMediaContent;
+class QVideoWindowControl;
QT_END_NAMESPACE
QT_USE_NAMESPACE
@@ -172,9 +170,7 @@ private:
DirectShowPlayerControl *m_playerControl;
DirectShowMetaDataControl *m_metaDataControl;
DirectShowVideoRendererControl *m_videoRendererControl;
-#if defined(HAVE_WIDGETS) && !defined(Q_WS_SIMULATOR)
- Vmr9VideoWindowControl *m_videoWindowControl;
-#endif
+ QVideoWindowControl *m_videoWindowControl;
DirectShowAudioEndpointControl *m_audioEndpointControl;
QThread *m_taskThread;
@@ -194,10 +190,12 @@ private:
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;
diff --git a/src/plugins/directshow/player/directshowvideorenderercontrol.cpp b/src/plugins/directshow/player/directshowvideorenderercontrol.cpp
index da4764880..027d2ce55 100644
--- a/src/plugins/directshow/player/directshowvideorenderercontrol.cpp
+++ b/src/plugins/directshow/player/directshowvideorenderercontrol.cpp
@@ -35,6 +35,12 @@
#include "videosurfacefilter.h"
+#ifdef HAVE_EVR
+#include "evrcustompresenter.h"
+#endif
+
+#include <qabstractvideosurface.h>
+
DirectShowVideoRendererControl::DirectShowVideoRendererControl(DirectShowEventLoop *loop, QObject *parent)
: QVideoRendererControl(parent)
, m_loop(loop)
@@ -45,7 +51,8 @@ DirectShowVideoRendererControl::DirectShowVideoRendererControl(DirectShowEventLo
DirectShowVideoRendererControl::~DirectShowVideoRendererControl()
{
- delete m_filter;
+ if (m_filter)
+ m_filter->Release();
}
QAbstractVideoSurface *DirectShowVideoRendererControl::surface() const
@@ -55,21 +62,34 @@ QAbstractVideoSurface *DirectShowVideoRendererControl::surface() const
void DirectShowVideoRendererControl::setSurface(QAbstractVideoSurface *surface)
{
- if (surface != m_surface) {
- m_surface = surface;
+ if (m_surface == surface)
+ return;
+
+ if (m_filter) {
+ m_filter->Release();
+ m_filter = 0;
+ }
- VideoSurfaceFilter *existingFilter = m_filter;
+ m_surface = surface;
- if (surface) {
- m_filter = new VideoSurfaceFilter(surface, m_loop);
- } else {
+ if (m_surface) {
+#ifdef HAVE_EVR
+ m_filter = com_new<IBaseFilter>(clsid_EnhancedVideoRenderer);
+ EVRCustomPresenter *evrPresenter = new EVRCustomPresenter(m_surface);
+ if (!evrPresenter->isValid() || !qt_evr_setCustomPresenter(m_filter, evrPresenter)) {
+ m_filter->Release();
m_filter = 0;
}
+ evrPresenter->Release();
- emit filterChanged();
-
- delete existingFilter;
+ if (!m_filter)
+#endif
+ {
+ m_filter = new VideoSurfaceFilter(m_surface, m_loop);
+ }
}
+
+ emit filterChanged();
}
IBaseFilter *DirectShowVideoRendererControl::filter()
diff --git a/src/plugins/directshow/player/directshowvideorenderercontrol.h b/src/plugins/directshow/player/directshowvideorenderercontrol.h
index b4828d1b0..484fda263 100644
--- a/src/plugins/directshow/player/directshowvideorenderercontrol.h
+++ b/src/plugins/directshow/player/directshowvideorenderercontrol.h
@@ -39,7 +39,6 @@
#include <dshow.h>
class DirectShowEventLoop;
-class VideoSurfaceFilter;
QT_USE_NAMESPACE
@@ -61,7 +60,7 @@ Q_SIGNALS:
private:
DirectShowEventLoop *m_loop;
QAbstractVideoSurface *m_surface;
- VideoSurfaceFilter *m_filter;
+ IBaseFilter *m_filter;
};
#endif
diff --git a/src/plugins/directshow/player/player.pri b/src/plugins/directshow/player/player.pri
index c5c934a38..5ecb912b2 100644
--- a/src/plugins/directshow/player/player.pri
+++ b/src/plugins/directshow/player/player.pri
@@ -1,5 +1,9 @@
INCLUDEPATH += $$PWD
+LIBS += -lstrmiids -ldmoguids -luuid -lmsdmo -lole32 -loleaut32 -lgdi32
+
+qtHaveModule(widgets): QT += widgets
+
DEFINES += QMEDIA_DIRECTSHOW_PLAYER
HEADERS += \
@@ -17,7 +21,8 @@ HEADERS += \
$$PWD/directshowsamplescheduler.h \
$$PWD/directshowvideorenderercontrol.h \
$$PWD/mediasamplevideobuffer.h \
- $$PWD/videosurfacefilter.h
+ $$PWD/videosurfacefilter.h \
+ $$PWD/vmr9videowindowcontrol.h
SOURCES += \
$$PWD/directshowaudioendpointcontrol.cpp \
@@ -33,14 +38,19 @@ SOURCES += \
$$PWD/directshowsamplescheduler.cpp \
$$PWD/directshowvideorenderercontrol.cpp \
$$PWD/mediasamplevideobuffer.cpp \
- $$PWD/videosurfacefilter.cpp
+ $$PWD/videosurfacefilter.cpp \
+ $$PWD/vmr9videowindowcontrol.cpp
+
+config_evr {
+ DEFINES += HAVE_EVR
+
+ include($$PWD/../../common/evr.pri)
-qtHaveModule(widgets):!simulator {
HEADERS += \
- $$PWD/vmr9videowindowcontrol.h
+ $$PWD/directshowevrvideowindowcontrol.h
SOURCES += \
- $$PWD/vmr9videowindowcontrol.cpp
+ $$PWD/directshowevrvideowindowcontrol.cpp
}
config_wshellitem {
@@ -48,6 +58,3 @@ config_wshellitem {
} else {
DEFINES += QT_NO_SHELLITEM
}
-
-LIBS += -lstrmiids -ldmoguids -luuid -lmsdmo -lole32 -loleaut32 -lgdi32
-
diff --git a/src/plugins/directshow/player/videosurfacefilter.cpp b/src/plugins/directshow/player/videosurfacefilter.cpp
index 2f52e33de..1fa7329cc 100644
--- a/src/plugins/directshow/player/videosurfacefilter.cpp
+++ b/src/plugins/directshow/player/videosurfacefilter.cpp
@@ -69,7 +69,7 @@ VideoSurfaceFilter::VideoSurfaceFilter(
VideoSurfaceFilter::~VideoSurfaceFilter()
{
- Q_ASSERT(m_ref == 1);
+ Q_ASSERT(m_ref == 0);
}
HRESULT VideoSurfaceFilter::QueryInterface(REFIID riid, void **ppvObject)
@@ -110,8 +110,8 @@ ULONG VideoSurfaceFilter::AddRef()
ULONG VideoSurfaceFilter::Release()
{
ULONG ref = InterlockedDecrement(&m_ref);
-
- Q_ASSERT(ref != 0);
+ if (ref == 0)
+ delete this;
return ref;
}
@@ -147,6 +147,14 @@ HRESULT VideoSurfaceFilter::Stop()
m_sampleScheduler.stop();
+ if (thread() == QThread::currentThread()) {
+ flush();
+ } else {
+ QMutexLocker locker(&m_mutex);
+ m_loop->postEvent(this, new QEvent(QEvent::Type(FlushSurface)));
+ m_wait.wait(&m_mutex);
+ }
+
return S_OK;
}
@@ -606,10 +614,24 @@ void VideoSurfaceFilter::sampleReady()
IMediaSample *sample = m_sampleScheduler.takeSample(&eos);
if (sample) {
- m_surface->present(QVideoFrame(
- new MediaSampleVideoBuffer(sample, m_bytesPerLine),
- m_surfaceFormat.frameSize(),
- m_surfaceFormat.pixelFormat()));
+ QVideoFrame frame(new MediaSampleVideoBuffer(sample, m_bytesPerLine),
+ m_surfaceFormat.frameSize(),
+ m_surfaceFormat.pixelFormat());
+
+ if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) {
+ LONGLONG position = 0;
+ seeking->GetCurrentPosition(&position);
+ seeking->Release();
+
+ frame.setStartTime(position * 0.1);
+
+ REFERENCE_TIME startTime = -1;
+ REFERENCE_TIME endTime = -1;
+ if (sample->GetTime(&startTime, &endTime) == S_OK)
+ frame.setEndTime(frame.startTime() + (endTime - startTime) * 0.1);
+ }
+
+ m_surface->present(frame);
sample->Release();
diff --git a/src/plugins/directshow/player/vmr9videowindowcontrol.cpp b/src/plugins/directshow/player/vmr9videowindowcontrol.cpp
index 48ff6c2c3..853ca031c 100644
--- a/src/plugins/directshow/player/vmr9videowindowcontrol.cpp
+++ b/src/plugins/directshow/player/vmr9videowindowcontrol.cpp
@@ -35,13 +35,16 @@
#include "directshowglobal.h"
+#ifndef QT_NO_WIDGETS
#include <QtGui/QPalette>
#include <QtWidgets/QWidget>
+#endif
Vmr9VideoWindowControl::Vmr9VideoWindowControl(QObject *parent)
: QVideoWindowControl(parent)
- , m_filter(com_new<IBaseFilter>(CLSID_VideoMixingRenderer9, IID_IBaseFilter))
+ , m_filter(com_new<IBaseFilter>(CLSID_VideoMixingRenderer9))
, m_windowId(0)
+ , m_windowColor(RGB(0, 0, 0))
, m_dirtyValues(0)
, m_aspectRatioMode(Qt::KeepAspectRatio)
, m_brightness(0)
@@ -74,11 +77,13 @@ void Vmr9VideoWindowControl::setWinId(WId id)
{
m_windowId = id;
+#ifndef QT_NO_WIDGETS
if (QWidget *widget = QWidget::find(m_windowId)) {
const QColor color = widget->palette().color(QPalette::Window);
m_windowColor = RGB(color.red(), color.green(), color.blue());
}
+#endif
if (IVMRWindowlessControl9 *control = com_cast<IVMRWindowlessControl9>(
m_filter, IID_IVMRWindowlessControl9)) {