diff options
author | Peng Wu <peng.wu@intopalo.com> | 2015-06-12 13:02:38 +0300 |
---|---|---|
committer | PengWu <peng.wu@intopalo.com> | 2015-06-23 13:16:13 +0000 |
commit | dc9e10d4b7acd9e752a7b094c7178a7ecbe96ff7 (patch) | |
tree | 1cd40393f9665daa33ffb967980fd962c5d44886 | |
parent | 3cb698c0fcd05334163ac86f1a5a599dae67025b (diff) | |
download | qtmultimedia-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.cpp | 40 | ||||
-rw-r--r-- | src/plugins/winrt/qwinrtcameracontrol.h | 3 | ||||
-rw-r--r-- | src/plugins/winrt/qwinrtcameraimagecapturecontrol.cpp | 30 | ||||
-rw-r--r-- | src/plugins/winrt/qwinrtcameraservice.cpp | 6 | ||||
-rw-r--r-- | src/plugins/winrt/qwinrtimageencodercontrol.cpp | 124 | ||||
-rw-r--r-- | src/plugins/winrt/qwinrtimageencodercontrol.h | 66 | ||||
-rw-r--r-- | src/plugins/winrt/winrt.pro | 6 |
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 |