summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeng Wu <peng.wu@intopalo.com>2015-06-12 13:02:38 +0300
committerPengWu <peng.wu@intopalo.com>2015-06-23 13:16:13 +0000
commitdc9e10d4b7acd9e752a7b094c7178a7ecbe96ff7 (patch)
tree1cd40393f9665daa33ffb967980fd962c5d44886
parent3cb698c0fcd05334163ac86f1a5a599dae67025b (diff)
downloadqtmultimedia-dc9e10d4b7acd9e752a7b094c7178a7ecbe96ff7.tar.gz
winrt: Implement QImageEncoderControl for camera
Implement QImageEncoderControl for camera still image capture. It provides the functions to set camera capture resolution and get supported resolutions list. Task-number: QTBUG-46456 Change-Id: Ideb1aa02d420be3a30d588bebf31714fa4fa6415 Reviewed-by: Oliver Wolff <oliver.wolff@theqtcompany.com>
-rw-r--r--src/plugins/winrt/qwinrtcameracontrol.cpp40
-rw-r--r--src/plugins/winrt/qwinrtcameracontrol.h3
-rw-r--r--src/plugins/winrt/qwinrtcameraimagecapturecontrol.cpp30
-rw-r--r--src/plugins/winrt/qwinrtcameraservice.cpp6
-rw-r--r--src/plugins/winrt/qwinrtimageencodercontrol.cpp124
-rw-r--r--src/plugins/winrt/qwinrtimageencodercontrol.h66
-rw-r--r--src/plugins/winrt/winrt.pro6
7 files changed, 260 insertions, 15 deletions
diff --git a/src/plugins/winrt/qwinrtcameracontrol.cpp b/src/plugins/winrt/qwinrtcameracontrol.cpp
index e4a577642..f5b75d9ab 100644
--- a/src/plugins/winrt/qwinrtcameracontrol.cpp
+++ b/src/plugins/winrt/qwinrtcameracontrol.cpp
@@ -38,6 +38,7 @@
#include "qwinrtcameravideorenderercontrol.h"
#include "qwinrtvideodeviceselectorcontrol.h"
#include "qwinrtcameraimagecapturecontrol.h"
+#include "qwinrtimageencodercontrol.h"
#include <QtCore/qfunctions_winrt.h>
#include <QtCore/QCoreApplication>
@@ -75,6 +76,10 @@ QT_USE_NAMESPACE
RETURN_VOID_IF_FAILED(msg); \
}
+inline uint qHash (const QSize &key) {
+ return key.width() * key.height();
+}
+
class CriticalSectionLocker
{
public:
@@ -453,6 +458,7 @@ public:
QPointer<QWinRTCameraVideoRendererControl> videoRenderer;
QPointer<QWinRTVideoDeviceSelectorControl> videoDeviceSelector;
QPointer<QWinRTCameraImageCaptureControl> imageCaptureControl;
+ QPointer<QWinRTImageEncoderControl> imageEncoderControl;
};
QWinRTCameraControl::QWinRTCameraControl(QObject *parent)
@@ -470,6 +476,7 @@ QWinRTCameraControl::QWinRTCameraControl(QObject *parent)
this, &QWinRTCameraControl::onBufferRequested);
d->videoDeviceSelector = new QWinRTVideoDeviceSelectorControl(this);
d->imageCaptureControl = new QWinRTCameraImageCaptureControl(this);
+ d->imageEncoderControl = new QWinRTImageEncoderControl(this);
}
QWinRTCameraControl::~QWinRTCameraControl()
@@ -654,16 +661,16 @@ QCameraImageCaptureControl *QWinRTCameraControl::imageCaptureControl() const
return d->imageCaptureControl;
}
-IMediaCapture *QWinRTCameraControl::handle() const
+QImageEncoderControl *QWinRTCameraControl::imageEncoderControl() const
{
Q_D(const QWinRTCameraControl);
- return d->capture.Get();
+ return d->imageEncoderControl;
}
-QSize QWinRTCameraControl::imageSize() const
+IMediaCapture *QWinRTCameraControl::handle() const
{
Q_D(const QWinRTCameraControl);
- return d->size;
+ return d->capture.Get();
}
void QWinRTCameraControl::onBufferRequested()
@@ -763,10 +770,11 @@ HRESULT QWinRTCameraControl::initialize()
Q_ASSERT_SUCCEEDED(hr);
d->size = QSize();
- ComPtr<IVideoEncodingProperties> videoEncodingProperties;
quint32 encodingPropertiesListSize;
hr = encodingPropertiesList->get_Size(&encodingPropertiesListSize);
Q_ASSERT_SUCCEEDED(hr);
+ QHash<QSize, ComPtr<IVideoEncodingProperties>> videoEncodingPropertiesList;
+ int pixelCount = 0;
for (quint32 i = 0; i < encodingPropertiesListSize; ++i) {
ComPtr<IMediaEncodingProperties> properties;
hr = encodingPropertiesList->GetAt(i, &properties);
@@ -779,21 +787,33 @@ HRESULT QWinRTCameraControl::initialize()
Q_ASSERT_SUCCEEDED(hr);
hr = videoProperties->get_Height(&height);
Q_ASSERT_SUCCEEDED(hr);
- // Choose the highest-quality format
- if (int(width * height) > d->size.width() * d->size.height()) {
- d->size = QSize(width, height);
- videoEncodingProperties = videoProperties;
+ if (d->captureMode != QCamera::CaptureStillImage && int(width * height) > pixelCount) {
+ d->size = QSize(width, height);// Choose the Highest-quality format
+ pixelCount = d->size.width() * d->size.height();
}
+ videoEncodingPropertiesList.insert(QSize(width, height), videoProperties);
}
- if (!videoEncodingProperties || d->size.isEmpty()) {
+ if (videoEncodingPropertiesList.isEmpty()) {
hr = MF_E_INVALID_FORMAT;
RETURN_HR_IF_FAILED("Failed to find a suitable video format");
}
+ if (d->captureMode == QCamera::CaptureStillImage) {
+ d->imageEncoderControl->setSupportedResolutionsList(videoEncodingPropertiesList.keys());
+ d->size = d->imageEncoderControl->imageSettings().resolution();
+ }
+
hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Media_MediaProperties_MediaEncodingProfile).Get(),
&d->encodingProfile);
Q_ASSERT_SUCCEEDED(hr);
+
+ const ComPtr<IVideoEncodingProperties> videoEncodingProperties = videoEncodingPropertiesList[d->size];
+ if (!videoEncodingProperties) {
+ hr = MF_E_INVALID_FORMAT;
+ RETURN_HR_IF_FAILED("Failed to find a suitable video format properties");
+ }
+
hr = d->encodingProfile->put_Video(videoEncodingProperties.Get());
Q_ASSERT_SUCCEEDED(hr);
if (d->videoRenderer)
diff --git a/src/plugins/winrt/qwinrtcameracontrol.h b/src/plugins/winrt/qwinrtcameracontrol.h
index 95692cbc7..307667eb1 100644
--- a/src/plugins/winrt/qwinrtcameracontrol.h
+++ b/src/plugins/winrt/qwinrtcameracontrol.h
@@ -60,6 +60,7 @@ QT_BEGIN_NAMESPACE
class QVideoRendererControl;
class QVideoDeviceSelectorControl;
class QCameraImageCaptureControl;
+class QImageEncoderControl;
class QWinRTCameraControlPrivate;
class QWinRTCameraControl : public QCameraControl
@@ -83,9 +84,9 @@ public:
QVideoRendererControl *videoRenderer() const;
QVideoDeviceSelectorControl *videoDeviceSelector() const;
QCameraImageCaptureControl *imageCaptureControl() const;
+ QImageEncoderControl *imageEncoderControl() const;
ABI::Windows::Media::Capture::IMediaCapture *handle() const;
- QSize imageSize() const;
private slots:
void onBufferRequested();
diff --git a/src/plugins/winrt/qwinrtcameraimagecapturecontrol.cpp b/src/plugins/winrt/qwinrtcameraimagecapturecontrol.cpp
index 104484a6e..5a1c27b5e 100644
--- a/src/plugins/winrt/qwinrtcameraimagecapturecontrol.cpp
+++ b/src/plugins/winrt/qwinrtcameraimagecapturecontrol.cpp
@@ -36,6 +36,7 @@
#include "qwinrtcameraimagecapturecontrol.h"
#include "qwinrtcameracontrol.h"
+#include "qwinrtimageencodercontrol.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QDir>
@@ -166,7 +167,7 @@ int QWinRTCameraImageCaptureControl::capture(const QString &fileName)
hr = g->encodingPropertiesFactory->CreateBmp(&request.imageFormat);
Q_ASSERT_SUCCEEDED(hr);
- const QSize imageSize = d->cameraControl->imageSize();
+ const QSize imageSize = static_cast<QWinRTImageEncoderControl*>(d->cameraControl->imageEncoderControl())->imageSettings().resolution();
hr = request.imageFormat->put_Width(imageSize.width());
Q_ASSERT_SUCCEEDED(hr);
hr = request.imageFormat->put_Height(imageSize.height());
@@ -174,6 +175,10 @@ int QWinRTCameraImageCaptureControl::capture(const QString &fileName)
hr = capture->CapturePhotoToStreamAsync(request.imageFormat.Get(), request.stream.Get(), &request.op);
Q_ASSERT_SUCCEEDED(hr);
+ if (!request.op) {
+ qErrnoWarning("Camera photo capture failed.");
+ return -1;
+ }
d->requests.insert(request.op.Get(), request);
hr = request.op->put_Completed(Callback<IAsyncActionCompletedHandler>(
@@ -266,7 +271,28 @@ HRESULT QWinRTCameraImageCaptureControl::onCaptureCompleted(IAsyncAction *asyncI
const QImage image(pixelData, pixelWidth, pixelHeight, QImage::Format_RGBA8888,
reinterpret_cast<QImageCleanupFunction>(&CoTaskMemFree), pixelData);
emit imageCaptured(request.id, image);
- if (image.save(request.fileName))
+
+ QWinRTImageEncoderControl *imageEncoderControl = static_cast<QWinRTImageEncoderControl*>(d->cameraControl->imageEncoderControl());
+ int imageQuality = 100;
+ switch (imageEncoderControl->imageSettings().quality()) {
+ case QMultimedia::VeryLowQuality:
+ imageQuality = 20;
+ break;
+ case QMultimedia::LowQuality:
+ imageQuality = 40;
+ break;
+ case QMultimedia::NormalQuality:
+ imageQuality = 60;
+ break;
+ case QMultimedia::HighQuality:
+ imageQuality = 80;
+ break;
+ case QMultimedia::VeryHighQuality:
+ imageQuality = 100;
+ break;
+ }
+
+ if (image.save(request.fileName, imageEncoderControl->imageSettings().codec().toLatin1().data(), imageQuality))
emit imageSaved(request.id, request.fileName);
else
emit error(request.id, QCameraImageCapture::ResourceError, tr("Image saving failed"));
diff --git a/src/plugins/winrt/qwinrtcameraservice.cpp b/src/plugins/winrt/qwinrtcameraservice.cpp
index 09b565753..dc9d6ee67 100644
--- a/src/plugins/winrt/qwinrtcameraservice.cpp
+++ b/src/plugins/winrt/qwinrtcameraservice.cpp
@@ -44,6 +44,7 @@
#include <QtMultimedia/QCameraImageCaptureControl>
#include <QtMultimedia/QVideoRendererControl>
#include <QtMultimedia/QVideoDeviceSelectorControl>
+#include <QtMultimedia/QImageEncoderControl>
QT_USE_NAMESPACE
@@ -90,6 +91,11 @@ QMediaControl *QWinRTCameraService::requestControl(const char *name)
return d->cameraControl->imageCaptureControl();
}
+ if (qstrcmp(name, QImageEncoderControl_iid) == 0) {
+ if (d->cameraControl)
+ return d->cameraControl->imageEncoderControl();
+ }
+
return Q_NULLPTR;
}
diff --git a/src/plugins/winrt/qwinrtimageencodercontrol.cpp b/src/plugins/winrt/qwinrtimageencodercontrol.cpp
new file mode 100644
index 000000000..0ab7a7cfb
--- /dev/null
+++ b/src/plugins/winrt/qwinrtimageencodercontrol.cpp
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd and/or its subsidiary(-ies).
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwinrtimageencodercontrol.h"
+QT_BEGIN_NAMESPACE
+
+class QWinRTImageEncoderControlPrivate
+{
+public:
+ QList<QSize> supportedResolutions;
+ QImageEncoderSettings imageEncoderSetting;
+};
+
+QWinRTImageEncoderControl::QWinRTImageEncoderControl(QObject *parent)
+ : QImageEncoderControl(parent), d_ptr(new QWinRTImageEncoderControlPrivate)
+{
+}
+
+QStringList QWinRTImageEncoderControl::supportedImageCodecs() const
+{
+ return QStringList() << QStringLiteral("jpeg");
+}
+
+QString QWinRTImageEncoderControl::imageCodecDescription(const QString &codecName) const
+{
+ if (codecName == QStringLiteral("jpeg"))
+ return tr("JPEG image");
+
+ return QString();
+}
+
+QList<QSize> QWinRTImageEncoderControl::supportedResolutions(const QImageEncoderSettings &settings, bool *continuous) const
+{
+ Q_UNUSED(settings);
+ Q_D(const QWinRTImageEncoderControl);
+
+ if (continuous)
+ *continuous = false;
+
+ return d->supportedResolutions;
+}
+
+QImageEncoderSettings QWinRTImageEncoderControl::imageSettings() const
+{
+ Q_D(const QWinRTImageEncoderControl);
+ return d->imageEncoderSetting;
+}
+
+void QWinRTImageEncoderControl::setImageSettings(const QImageEncoderSettings &settings)
+{
+ Q_D(QWinRTImageEncoderControl);
+ if (d->imageEncoderSetting == settings)
+ return;
+
+ d->imageEncoderSetting = settings;
+ applySettings();
+}
+
+void QWinRTImageEncoderControl::setSupportedResolutionsList(const QList<QSize> resolution)
+{
+ Q_D(QWinRTImageEncoderControl);
+ d->supportedResolutions = resolution;
+ applySettings();
+}
+
+void QWinRTImageEncoderControl::applySettings()
+{
+ Q_D(QWinRTImageEncoderControl);
+ d->imageEncoderSetting.setCodec(QStringLiteral("jpeg"));
+
+ QSize requestResolution = d->imageEncoderSetting.resolution();
+ if (d->supportedResolutions.isEmpty() || d->supportedResolutions.contains(requestResolution))
+ return;
+
+ if (!requestResolution.isValid())
+ requestResolution = QSize(0, 0);// Find the minimal available resolution
+
+ // Find closest resolution from the list
+ const int pixelCount = requestResolution.width() * requestResolution.height();
+ int minPixelCountGap = -1;
+ for (int i = 0; i < d->supportedResolutions.size(); ++i) {
+ int gap = qAbs(pixelCount - d->supportedResolutions.at(i).width() * d->supportedResolutions.at(i).height());
+ if (gap < minPixelCountGap || minPixelCountGap < 0) {
+ minPixelCountGap = gap;
+ requestResolution = d->supportedResolutions.at(i);
+ }
+ }
+ d->imageEncoderSetting.setResolution(requestResolution);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/winrt/qwinrtimageencodercontrol.h b/src/plugins/winrt/qwinrtimageencodercontrol.h
new file mode 100644
index 000000000..7682e7626
--- /dev/null
+++ b/src/plugins/winrt/qwinrtimageencodercontrol.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd and/or its subsidiary(-ies).
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTIMAGEENCODERCONTROL_H
+#define QWINRTIMAGEENCODERCONTROL_H
+
+#include <qimageencodercontrol.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWinRTImageEncoderControlPrivate;
+class QWinRTImageEncoderControl : public QImageEncoderControl
+{
+public:
+ explicit QWinRTImageEncoderControl(QObject *parent = 0);
+
+ QStringList supportedImageCodecs() const Q_DECL_OVERRIDE;
+ QString imageCodecDescription(const QString &codecName) const Q_DECL_OVERRIDE;
+ QList<QSize> supportedResolutions(const QImageEncoderSettings &settings, bool *continuous = 0) const Q_DECL_OVERRIDE;
+ QImageEncoderSettings imageSettings() const Q_DECL_OVERRIDE;
+ void setImageSettings(const QImageEncoderSettings &settings) Q_DECL_OVERRIDE;
+
+ void setSupportedResolutionsList(const QList<QSize> resolution);
+ void applySettings();
+
+private:
+ QScopedPointer<QWinRTImageEncoderControlPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QWinRTImageEncoderControl)
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINRTIMAGEENCODERCONTROL_H
diff --git a/src/plugins/winrt/winrt.pro b/src/plugins/winrt/winrt.pro
index 04db71e75..58c2371f9 100644
--- a/src/plugins/winrt/winrt.pro
+++ b/src/plugins/winrt/winrt.pro
@@ -18,7 +18,8 @@ HEADERS += \
qwinrtmediaplayerservice.h \
qwinrtplayerrenderercontrol.h \
qwinrtserviceplugin.h \
- qwinrtvideodeviceselectorcontrol.h
+ qwinrtvideodeviceselectorcontrol.h \
+ qwinrtimageencodercontrol.h
SOURCES += \
qwinrtabstractvideorenderercontrol.cpp \
@@ -31,7 +32,8 @@ SOURCES += \
qwinrtmediaplayerservice.cpp \
qwinrtplayerrenderercontrol.cpp \
qwinrtserviceplugin.cpp \
- qwinrtvideodeviceselectorcontrol.cpp
+ qwinrtvideodeviceselectorcontrol.cpp \
+ qwinrtimageencodercontrol.cpp
OTHER_FILES += \
winrt.json