From cac5f507e1f84c99c7627129eaeba4a52231d2e3 Mon Sep 17 00:00:00 2001 From: Val Doroshchuk Date: Wed, 27 Dec 2017 13:32:44 +0100 Subject: DirectShow: Implement image capture settings Added camera image encoder control that 1. applies image encoder settings (resolution and codec) used to capture images 2. returns supported image codecs from QImageWriter::supportedImageFormats 3. returns supported resolutions Since DirectShow camera session uses QImage based on QVideoFrame image encoder control returns viewfinder supported resolutions. Not available if camera is not loaded. Setting resolution via encoder control causes viewfinder resolution to be ignored. Task-number: QTBUG-32743 Change-Id: I1de3ca9c6543937cb62f73cb64a81d23b0d5c4c9 Reviewed-by: Oliver Wolff Reviewed-by: Andy Shaw Reviewed-by: Christian Stromme --- src/plugins/directshow/camera/camera.pri | 6 +- .../camera/directshowcameraimageencodercontrol.cpp | 95 ++++++++++++++++++++++ .../camera/directshowcameraimageencodercontrol.h | 70 ++++++++++++++++ src/plugins/directshow/camera/dscameraservice.cpp | 6 ++ src/plugins/directshow/camera/dscameraservice.h | 2 + src/plugins/directshow/camera/dscamerasession.cpp | 31 ++++++- src/plugins/directshow/camera/dscamerasession.h | 8 ++ 7 files changed, 213 insertions(+), 5 deletions(-) create mode 100644 src/plugins/directshow/camera/directshowcameraimageencodercontrol.cpp create mode 100644 src/plugins/directshow/camera/directshowcameraimageencodercontrol.h (limited to 'src/plugins/directshow') diff --git a/src/plugins/directshow/camera/camera.pri b/src/plugins/directshow/camera/camera.pri index 0e1c1e895..3be1acc49 100644 --- a/src/plugins/directshow/camera/camera.pri +++ b/src/plugins/directshow/camera/camera.pri @@ -15,7 +15,8 @@ HEADERS += \ $$PWD/directshowcameraexposurecontrol.h \ $$PWD/directshowcameracapturedestinationcontrol.h \ $$PWD/directshowcameracapturebufferformatcontrol.h \ - $$PWD/directshowcamerazoomcontrol.h + $$PWD/directshowcamerazoomcontrol.h \ + $$PWD/directshowcameraimageencodercontrol.h SOURCES += \ $$PWD/dscameraservice.cpp \ @@ -29,7 +30,8 @@ SOURCES += \ $$PWD/directshowcameraexposurecontrol.cpp \ $$PWD/directshowcameracapturedestinationcontrol.cpp \ $$PWD/directshowcameracapturebufferformatcontrol.cpp \ - $$PWD/directshowcamerazoomcontrol.cpp + $$PWD/directshowcamerazoomcontrol.cpp \ + $$PWD/directshowcameraimageencodercontrol.cpp *-msvc*:INCLUDEPATH += $$(DXSDK_DIR)/include QMAKE_USE += directshow diff --git a/src/plugins/directshow/camera/directshowcameraimageencodercontrol.cpp b/src/plugins/directshow/camera/directshowcameraimageencodercontrol.cpp new file mode 100644 index 000000000..912f67a2d --- /dev/null +++ b/src/plugins/directshow/camera/directshowcameraimageencodercontrol.cpp @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "directshowcameraimageencodercontrol.h" +#include "dscamerasession.h" +#include + +QT_BEGIN_NAMESPACE + +DirectShowCameraImageEncoderControl::DirectShowCameraImageEncoderControl(DSCameraSession *session) + : QImageEncoderControl(session) + , m_session(session) +{ +} + +QList DirectShowCameraImageEncoderControl::supportedResolutions(const QImageEncoderSettings &settings, bool *continuous) const +{ + QList res; + if (!settings.codec().isEmpty() && !supportedImageCodecs().contains(settings.codec(), Qt::CaseInsensitive)) + return res; + + QList resolutions = m_session->supportedResolutions(continuous); + QSize r = settings.resolution(); + if (!r.isValid()) + return resolutions; + + if (resolutions.contains(r)) + res << settings.resolution(); + + return res; +} + +QStringList DirectShowCameraImageEncoderControl::supportedImageCodecs() const +{ + QStringList supportedCodecs; + for (const QByteArray &type: QImageWriter::supportedImageFormats()) { + supportedCodecs << type; + } + + return supportedCodecs; +} + +QString DirectShowCameraImageEncoderControl::imageCodecDescription(const QString &codecName) const +{ + Q_UNUSED(codecName); + return QString(); +} + +QImageEncoderSettings DirectShowCameraImageEncoderControl::imageSettings() const +{ + return m_session->imageEncoderSettings(); +} + +void DirectShowCameraImageEncoderControl::setImageSettings(const QImageEncoderSettings &settings) +{ + m_session->setImageEncoderSettings(settings); +} + +QT_END_NAMESPACE diff --git a/src/plugins/directshow/camera/directshowcameraimageencodercontrol.h b/src/plugins/directshow/camera/directshowcameraimageencodercontrol.h new file mode 100644 index 000000000..6891bea77 --- /dev/null +++ b/src/plugins/directshow/camera/directshowcameraimageencodercontrol.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DIRECTSHOWCAMERAIMAGEENCODERCONTROL_H +#define DIRECTSHOWCAMERAIMAGEENCODERCONTROL_H + +#include + +QT_BEGIN_NAMESPACE + +class DSCameraSession; +class DirectShowCameraImageEncoderControl : public QImageEncoderControl +{ + Q_OBJECT +public: + DirectShowCameraImageEncoderControl(DSCameraSession *session); + + QList supportedResolutions( + const QImageEncoderSettings &settings = QImageEncoderSettings(), + bool *continuous = nullptr) const override; + + QStringList supportedImageCodecs() const override; + QString imageCodecDescription(const QString &formatName) const override; + + QImageEncoderSettings imageSettings() const override; + void setImageSettings(const QImageEncoderSettings &settings) override; + +private: + DSCameraSession *m_session; +}; + +QT_END_NAMESPACE + +#endif // DIRECTSHOWCAMERAIMAGEENCODERCONTROL_H diff --git a/src/plugins/directshow/camera/dscameraservice.cpp b/src/plugins/directshow/camera/dscameraservice.cpp index a806cabe3..8115ef385 100644 --- a/src/plugins/directshow/camera/dscameraservice.cpp +++ b/src/plugins/directshow/camera/dscameraservice.cpp @@ -53,6 +53,7 @@ #include "directshowcameracapturebufferformatcontrol.h" #include "directshowvideoprobecontrol.h" #include "directshowcamerazoomcontrol.h" +#include "directshowcameraimageencodercontrol.h" QT_BEGIN_NAMESPACE @@ -70,6 +71,7 @@ DSCameraService::DSCameraService(QObject *parent): , m_captureBufferFormatControl(new DirectShowCameraCaptureBufferFormatControl) , m_videoProbeControl(nullptr) , m_zoomControl(new DirectShowCameraZoomControl(m_session)) + , m_imageEncoderControl(new DirectShowCameraImageEncoderControl(m_session)) { } @@ -81,6 +83,7 @@ DSCameraService::~DSCameraService() delete m_videoDevice; delete m_videoRenderer; delete m_imageCapture; + delete m_imageEncoderControl; delete m_session; delete m_exposureControl; delete m_captureDestinationControl; @@ -134,6 +137,9 @@ QMediaControl* DSCameraService::requestControl(const char *name) if (qstrcmp(name, QCameraZoomControl_iid) == 0) return m_zoomControl; + if (qstrcmp(name, QImageEncoderControl_iid) == 0) + return m_imageEncoderControl; + return 0; } diff --git a/src/plugins/directshow/camera/dscameraservice.h b/src/plugins/directshow/camera/dscameraservice.h index 2e45edcce..9a8f745f6 100644 --- a/src/plugins/directshow/camera/dscameraservice.h +++ b/src/plugins/directshow/camera/dscameraservice.h @@ -57,6 +57,7 @@ class DirectShowCameraCaptureDestinationControl; class DirectShowCameraCaptureBufferFormatControl; class DirectShowVideoProbeControl; class DirectShowCameraZoomControl; +class DirectShowCameraImageEncoderControl; class DSCameraService : public QMediaService { @@ -82,6 +83,7 @@ private: DirectShowCameraCaptureBufferFormatControl *m_captureBufferFormatControl; DirectShowVideoProbeControl *m_videoProbeControl; DirectShowCameraZoomControl *m_zoomControl; + DirectShowCameraImageEncoderControl *m_imageEncoderControl; }; QT_END_NAMESPACE diff --git a/src/plugins/directshow/camera/dscamerasession.cpp b/src/plugins/directshow/camera/dscamerasession.cpp index bf81262d6..85947c655 100644 --- a/src/plugins/directshow/camera/dscamerasession.cpp +++ b/src/plugins/directshow/camera/dscamerasession.cpp @@ -584,10 +584,13 @@ int DSCameraSession::captureImage(const QString &fileName) return m_imageIdCounter; } + const QString ext = !m_imageEncoderSettings.codec().isEmpty() + ? m_imageEncoderSettings.codec().toLower() + : QLatin1String("jpg"); m_imageCaptureFileName = m_fileNameGenerator.generateFileName(fileName, QMediaStorageLocation::Pictures, QLatin1String("IMG_"), - QLatin1String("jpg")); + ext); updateReadyForCapture(); @@ -687,8 +690,9 @@ void DSCameraSession::processCapturedImage(int id, const QImage &image, const QString &path) { + const QString format = m_imageEncoderSettings.codec(); if (captureDestinations & QCameraImageCapture::CaptureToFile) { - if (image.save(path, "JPG")) { + if (image.save(path, !format.isEmpty() ? format.toUtf8().constData() : "JPG")) { Q_EMIT imageSaved(id, path); } else { Q_EMIT captureError(id, QCameraImageCapture::ResourceError, @@ -844,9 +848,11 @@ bool DSCameraSession::configurePreviewFormat() { // Resolve viewfinder settings int settingsIndex = 0; + const QSize captureResolution = m_imageEncoderSettings.resolution(); + const QSize resolution = captureResolution.isValid() ? captureResolution : m_viewfinderSettings.resolution(); QCameraViewfinderSettings resolvedViewfinderSettings; for (const QCameraViewfinderSettings &s : qAsConst(m_supportedViewfinderSettings)) { - if ((m_viewfinderSettings.resolution().isEmpty() || m_viewfinderSettings.resolution() == s.resolution()) + if ((resolution.isEmpty() || resolution == s.resolution()) && (qFuzzyIsNull(m_viewfinderSettings.minimumFrameRate()) || qFuzzyCompare((float)m_viewfinderSettings.minimumFrameRate(), (float)s.minimumFrameRate())) && (qFuzzyIsNull(m_viewfinderSettings.maximumFrameRate()) || qFuzzyCompare((float)m_viewfinderSettings.maximumFrameRate(), (float)s.maximumFrameRate())) && (m_viewfinderSettings.pixelFormat() == QVideoFrame::Format_Invalid || m_viewfinderSettings.pixelFormat() == s.pixelFormat()) @@ -1171,4 +1177,23 @@ void DSCameraSession::updateSourceCapabilities() updateImageProcessingParametersInfos(); } +QList DSCameraSession::supportedResolutions(bool *continuous) const +{ + if (continuous) + *continuous = false; + + QList res; + for (auto &settings : m_supportedViewfinderSettings) { + auto size = settings.resolution(); + if (!res.contains(size)) + res << size; + } + + std::sort(res.begin(), res.end(), [](const QSize &r1, const QSize &r2) { + return qlonglong(r1.width()) * r1.height() < qlonglong(r2.width()) * r2.height(); + }); + + return res; +} + QT_END_NAMESPACE diff --git a/src/plugins/directshow/camera/dscamerasession.h b/src/plugins/directshow/camera/dscamerasession.h index ac861ae58..361a0220e 100644 --- a/src/plugins/directshow/camera/dscamerasession.h +++ b/src/plugins/directshow/camera/dscamerasession.h @@ -51,6 +51,7 @@ #include #include #include +#include #include #include @@ -129,6 +130,11 @@ public: void addVideoProbe(DirectShowVideoProbeControl *probe); void removeVideoProbe(DirectShowVideoProbeControl *probe); + QList supportedResolutions(bool *continuous) const; + QImageEncoderSettings imageEncoderSettings() const { return m_imageEncoderSettings; } + void setImageEncoderSettings(const QImageEncoderSettings &settings) + { m_imageEncoderSettings = settings; } + Q_SIGNALS: void statusChanged(QCamera::Status); void imageExposed(int id); @@ -217,6 +223,8 @@ private: QMutex m_probeMutex; DirectShowVideoProbeControl *m_videoProbeControl; + QImageEncoderSettings m_imageEncoderSettings; + // Internal state QCamera::Status m_status; QTimer m_deviceLostEventTimer; -- cgit v1.2.3