diff options
author | Christian Strømme <christian.stromme@theqtcompany.com> | 2016-01-15 17:27:32 +0100 |
---|---|---|
committer | Christian Strømme <christian.stromme@theqtcompany.com> | 2016-01-15 17:28:17 +0100 |
commit | 84e426c3af2a3bb1b7f916e54263aea758db38d0 (patch) | |
tree | 4fe09a8da5b15ba466e5771239d06f29a6c123da /src/plugins/directshow | |
parent | 84aaa48fdfc1f35c9870518a3d4b6f08a1f99449 (diff) | |
parent | 924dc7f48c7003b46079623738ae531f34aed903 (diff) |
Merge remote-tracking branch 'origin/5.6' into dev
Conflicts:
src/plugins/android/src/mediacapture/qandroidcamerasession.cpp
src/plugins/wmf/mftvideo.cpp
Change-Id: I78868b416ea4baec89ca3e2dc9eb4712db16d5fc
Diffstat (limited to 'src/plugins/directshow')
17 files changed, 598 insertions, 53 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 24dad94c5..ede5e4763 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() for (AM_MEDIA_TYPE f : qAsConst(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/player/directshowevrvideowindowcontrol.cpp b/src/plugins/directshow/player/directshowevrvideowindowcontrol.cpp index 7bffe47d2..22771bd4c 100644 --- a/src/plugins/directshow/player/directshowevrvideowindowcontrol.cpp +++ b/src/plugins/directshow/player/directshowevrvideowindowcontrol.cpp @@ -49,10 +49,8 @@ DirectShowEvrVideoWindowControl::~DirectShowEvrVideoWindowControl() IBaseFilter *DirectShowEvrVideoWindowControl::filter() { - static const GUID clsid_EnhancendVideoRenderer = { 0xfa10746c, 0x9b63, 0x4b6c, {0xbc, 0x49, 0xfc, 0x30, 0xe, 0xa5, 0xf2, 0x56} }; - if (!m_evrFilter) { - m_evrFilter = com_new<IBaseFilter>(clsid_EnhancendVideoRenderer); + m_evrFilter = com_new<IBaseFilter>(clsid_EnhancedVideoRenderer); if (!setEvr(m_evrFilter)) { m_evrFilter->Release(); m_evrFilter = NULL; diff --git a/src/plugins/directshow/player/directshowmetadatacontrol.cpp b/src/plugins/directshow/player/directshowmetadatacontrol.cpp index 3da02aa45..f1581e129 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(); @@ -569,13 +580,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 e988cbdd3..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) @@ -75,7 +64,7 @@ DirectShowPlayerControl::DirectShowPlayerControl(DirectShowPlayerService *servic , m_streamTypes(0) , m_volume(100) , m_muted(false) - , m_position(0) + , m_emitPosition(-1) , m_pendingPosition(-1) , m_duration(0) , m_playbackRate(0) @@ -109,7 +98,7 @@ 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) @@ -226,6 +215,7 @@ 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; @@ -258,6 +248,7 @@ void DirectShowPlayerControl::playOrPause(QMediaPlayer::State state) return; } + m_emitPosition = -1; m_state = state; if (m_pendingPosition != -1) @@ -273,6 +264,7 @@ void DirectShowPlayerControl::playOrPause(QMediaPlayer::State state) void DirectShowPlayerControl::stop() { + m_emitPosition = -1; m_service->stop(); emit stateChanged(m_state = QMediaPlayer::StoppedState); } @@ -304,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); @@ -400,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 ab842f511..f67c4108b 100644 --- a/src/plugins/directshow/player/directshowplayercontrol.h +++ b/src/plugins/directshow/player/directshowplayercontrol.h @@ -130,7 +130,7 @@ private: int m_streamTypes; int m_volume; bool m_muted; - qint64 m_position; + 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 07427583d..8e9e50cbf 100644 --- a/src/plugins/directshow/player/directshowplayerservice.cpp +++ b/src/plugins/directshow/player/directshowplayerservice.cpp @@ -103,6 +103,7 @@ DirectShowPlayerService::DirectShowPlayerService(QObject *parent) , m_buffering(false) , m_seekable(false) , m_atEnd(false) + , m_dontCacheNextSeekResult(false) { m_playerControl = new DirectShowPlayerControl(this); m_metaDataControl = new DirectShowMetaDataControl(this); @@ -229,7 +230,8 @@ void DirectShowPlayerService::load(const QMediaContent &media, QIODevice *stream 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; @@ -568,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; @@ -672,7 +671,9 @@ void DirectShowPlayerService::play() if (m_executedTasks & Stop) { m_atEnd = false; if (m_seekPosition == -1) { + m_dontCacheNextSeekResult = true; m_seekPosition = 0; + m_position = 0; m_pendingTasks |= Seek; } m_executedTasks ^= Stop; @@ -718,7 +719,9 @@ void DirectShowPlayerService::pause() if (m_executedTasks & Stop) { m_atEnd = false; if (m_seekPosition == -1) { + m_dontCacheNextSeekResult = true; m_seekPosition = 0; + m_position = 0; m_pendingTasks |= Seek; } m_executedTasks ^= Stop; @@ -791,6 +794,8 @@ void DirectShowPlayerService::doStop(QMutexLocker *locker) } m_seekPosition = 0; + m_position = 0; + m_dontCacheNextSeekResult = true; m_pendingTasks |= Seek; m_executedTasks &= ~(Play | Pause); @@ -913,8 +918,10 @@ void DirectShowPlayerService::doSeek(QMutexLocker *locker) // 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(¤tPosition); - m_position = currentPosition / qt_directShowTimeScale; + if (!m_dontCacheNextSeekResult) { + seeking->GetCurrentPosition(¤tPosition); + m_position = currentPosition / qt_directShowTimeScale; + } LONGLONG minimum = 0; LONGLONG maximum = 0; @@ -928,8 +935,10 @@ void DirectShowPlayerService::doSeek(QMutexLocker *locker) &seekPosition, AM_SEEKING_AbsolutePositioning, 0, AM_SEEKING_NoPositioning); locker->relock(); - seeking->GetCurrentPosition(¤tPosition); - m_position = currentPosition / qt_directShowTimeScale; + if (!m_dontCacheNextSeekResult) { + seeking->GetCurrentPosition(¤tPosition); + m_position = currentPosition / qt_directShowTimeScale; + } seeking->Release(); @@ -937,6 +946,7 @@ void DirectShowPlayerService::doSeek(QMutexLocker *locker) } m_seekPosition = -1; + m_dontCacheNextSeekResult = false; } int DirectShowPlayerService::bufferStatus() const @@ -1125,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 edfde105e..4d3762f74 100644 --- a/src/plugins/directshow/player/directshowplayerservice.h +++ b/src/plugins/directshow/player/directshowplayerservice.h @@ -195,6 +195,7 @@ private: 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 6a1580ea5..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) @@ -56,22 +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(); - - if (existingFilter) - existingFilter->Release(); + 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 8586ea5da..5ecb912b2 100644 --- a/src/plugins/directshow/player/player.pri +++ b/src/plugins/directshow/player/player.pri @@ -46,8 +46,11 @@ config_evr { include($$PWD/../../common/evr.pri) - HEADERS += $$PWD/directshowevrvideowindowcontrol.h - SOURCES += $$PWD/directshowevrvideowindowcontrol.cpp + HEADERS += \ + $$PWD/directshowevrvideowindowcontrol.h + + SOURCES += \ + $$PWD/directshowevrvideowindowcontrol.cpp } config_wshellitem { |