diff options
Diffstat (limited to 'src/plugins/winrt/qwinrtcameraimagecapturecontrol.cpp')
-rw-r--r-- | src/plugins/winrt/qwinrtcameraimagecapturecontrol.cpp | 338 |
1 files changed, 0 insertions, 338 deletions
diff --git a/src/plugins/winrt/qwinrtcameraimagecapturecontrol.cpp b/src/plugins/winrt/qwinrtcameraimagecapturecontrol.cpp deleted file mode 100644 index 4ed208feb..000000000 --- a/src/plugins/winrt/qwinrtcameraimagecapturecontrol.cpp +++ /dev/null @@ -1,338 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). -** 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 "qwinrtcameraimagecapturecontrol.h" -#include "qwinrtcameracontrol.h" -#include "qwinrtimageencodercontrol.h" - -#include <QtCore/QCoreApplication> -#include <QtCore/QDir> -#include <QtCore/QFileInfo> -#include <QtCore/QGlobalStatic> -#include <QtCore/QPointer> -#include <QtCore/QStandardPaths> -#include <QtCore/QVector> -#include <QtCore/qfunctions_winrt.h> -#include <QtCore/private/qeventdispatcher_winrt_p.h> -#include <QtMultimedia/private/qmediastoragelocation_p.h> - -#include <functional> -#include <wrl.h> -#include <windows.media.capture.h> -#include <windows.media.devices.h> -#include <windows.media.mediaproperties.h> -#include <windows.storage.streams.h> -#include <windows.graphics.imaging.h> -#include <robuffer.h> - -using namespace Microsoft::WRL; -using namespace Microsoft::WRL::Wrappers; -using namespace ABI::Windows::Foundation; -using namespace ABI::Windows::Media::Capture; -using namespace ABI::Windows::Media::Devices; -using namespace ABI::Windows::Media::MediaProperties; -using namespace ABI::Windows::Storage::Streams; -using namespace ABI::Windows::Graphics::Imaging; - -QT_BEGIN_NAMESPACE - -#define wchar(str) reinterpret_cast<const wchar_t *>(str.utf16()) - -struct QWinRTCameraImageCaptureControlGlobal -{ - QWinRTCameraImageCaptureControlGlobal() - { - HRESULT hr; - hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Media_MediaProperties_ImageEncodingProperties).Get(), - &encodingPropertiesFactory); - Q_ASSERT_SUCCEEDED(hr); - - hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_Buffer).Get(), - &bufferFactory); - Q_ASSERT_SUCCEEDED(hr); - - hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_DataReader).Get(), - &dataReaderFactory); - } - - ComPtr<IImageEncodingPropertiesStatics2> encodingPropertiesFactory; - ComPtr<IBufferFactory> bufferFactory; - ComPtr<IDataReaderFactory> dataReaderFactory; -}; -Q_GLOBAL_STATIC(QWinRTCameraImageCaptureControlGlobal, g) - -struct CaptureRequest -{ - quint16 id; - QString fileName; - ComPtr<IImageEncodingProperties> imageFormat; - ComPtr<IRandomAccessStream> stream; - ComPtr<IAsyncAction> op; -}; - -// Do not use CoTaskMemFree directly for image cleanup as it leads to crashes in release -static void freeImageData(void *data) -{ - CoTaskMemFree(data); -} - -class QWinRTCameraImageCaptureControlPrivate -{ -public: - QWinRTCameraImageCaptureControlPrivate() - : isActive(false) - { - } - - QPointer<QWinRTCameraControl> cameraControl; - QHash<IAsyncAction *, CaptureRequest> requests; - quint16 currentCaptureId; - QMediaStorageLocation location; - bool isActive; -}; - -QWinRTCameraImageCaptureControl::QWinRTCameraImageCaptureControl(QWinRTCameraControl *parent) - : QCameraImageCaptureControl(parent), d_ptr(new QWinRTCameraImageCaptureControlPrivate) -{ - qCDebug(lcMMCamera) << __FUNCTION__ << parent; - Q_D(QWinRTCameraImageCaptureControl); - - d->cameraControl = parent; - connect(d->cameraControl, &QCameraControl::stateChanged, - this, &QWinRTCameraImageCaptureControl::onCameraStateChanged); - d->currentCaptureId = 0; -} - -bool QWinRTCameraImageCaptureControl::isReadyForCapture() const -{ - Q_D(const QWinRTCameraImageCaptureControl); - return d->isActive; -} - -QCameraImageCapture::DriveMode QWinRTCameraImageCaptureControl::driveMode() const -{ - return QCameraImageCapture::SingleImageCapture; -} - -void QWinRTCameraImageCaptureControl::setDriveMode(QCameraImageCapture::DriveMode mode) -{ - Q_UNUSED(mode); -} - -int QWinRTCameraImageCaptureControl::capture(const QString &fileName) -{ - qCDebug(lcMMCamera) << __FUNCTION__ << fileName; - Q_D(QWinRTCameraImageCaptureControl); - - ++d->currentCaptureId; - ComPtr<IMediaCapture> capture = d->cameraControl->handle(); - if (!capture) { - emit error(d->currentCaptureId, QCameraImageCapture::NotReadyError, tr("Camera not ready")); - return -1; - } - - CaptureRequest request = { - d->currentCaptureId, - d->location.generateFileName(fileName, QMediaStorageLocation::Pictures, QStringLiteral("IMG_"), - fileName.isEmpty() ? QStringLiteral("jpg") : QFileInfo(fileName).suffix()), - nullptr, nullptr, nullptr - }; - - HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([this, d, capture, &request]() { - HRESULT hr; - hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_InMemoryRandomAccessStream).Get(), - &request.stream); - Q_ASSERT_SUCCEEDED(hr); - - hr = g->encodingPropertiesFactory->CreateBmp(&request.imageFormat); - Q_ASSERT_SUCCEEDED(hr); - - const QSize imageSize = static_cast<QWinRTImageEncoderControl*>(d->cameraControl->imageEncoderControl())->imageSettings().resolution(); - hr = request.imageFormat->put_Width(UINT32(imageSize.width())); - Q_ASSERT_SUCCEEDED(hr); - hr = request.imageFormat->put_Height(UINT32(imageSize.height())); - Q_ASSERT_SUCCEEDED(hr); - - hr = capture->CapturePhotoToStreamAsync(request.imageFormat.Get(), request.stream.Get(), &request.op); - Q_ASSERT_SUCCEEDED(hr); - if (!request.op) { - qErrnoWarning("Camera photo capture failed."); - return E_FAIL; - } - emit captureQueueChanged(false); - d->requests.insert(request.op.Get(), request); - - hr = request.op->put_Completed(Callback<IAsyncActionCompletedHandler>( - this, &QWinRTCameraImageCaptureControl::onCaptureCompleted).Get()); - Q_ASSERT_SUCCEEDED(hr); - return hr; - }); - if (FAILED(hr)) - return -1; - return request.id; -} - -void QWinRTCameraImageCaptureControl::cancelCapture() -{ - qCDebug(lcMMCamera) << __FUNCTION__; - Q_D(QWinRTCameraImageCaptureControl); - - QHash<IAsyncAction *, CaptureRequest>::iterator it = d->requests.begin(); - while (it != d->requests.end()) { - ComPtr<IAsyncInfo> info; - it->op.As(&info); - info->Cancel(); - it = d->requests.erase(it); - } - emit captureQueueChanged(true); -} - -void QWinRTCameraImageCaptureControl::onCameraStateChanged(QCamera::State state) -{ - Q_D(QWinRTCameraImageCaptureControl); - const bool newActive = state == QCamera::ActiveState; - if (d->isActive == newActive) - return; - - d->isActive = newActive; - emit readyForCaptureChanged(newActive); -} - -HRESULT QWinRTCameraImageCaptureControl::onCaptureCompleted(IAsyncAction *asyncInfo, AsyncStatus status) -{ - qCDebug(lcMMCamera) << __FUNCTION__; - Q_D(QWinRTCameraImageCaptureControl); - - if (status == Canceled || !d->requests.contains(asyncInfo)) - return S_OK; - - CaptureRequest request = d->requests.take(asyncInfo); - emit captureQueueChanged(d->requests.isEmpty()); - HRESULT hr; - if (status == Error) { - hr = asyncInfo->GetResults(); - emit error(request.id, QCameraImageCapture::ResourceError, qt_error_string(hr)); - return S_OK; - } - - quint64 dataLength; - hr = request.stream->get_Size(&dataLength); - Q_ASSERT_SUCCEEDED(hr); - if (dataLength == 0 || dataLength > INT_MAX) { - emit error(request.id, QCameraImageCapture::FormatError, tr("Invalid photo data length.")); - return S_OK; - } - - ComPtr<IBitmapDecoderStatics> bitmapFactory; - hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Graphics_Imaging_BitmapDecoder).Get(), - &bitmapFactory); - Q_ASSERT_SUCCEEDED(hr); - - ComPtr<IAsyncOperation<BitmapDecoder *>> op; - hr = bitmapFactory->CreateAsync(request.stream.Get(), &op); - Q_ASSERT_SUCCEEDED(hr); - ComPtr<IBitmapDecoder> decoder; - hr = QWinRTFunctions::await(op, decoder.GetAddressOf()); - Q_ASSERT_SUCCEEDED(hr); - - ComPtr<IAsyncOperation<BitmapFrame *>> op2; - hr = decoder->GetFrameAsync(0, &op2); - Q_ASSERT_SUCCEEDED(hr); - ComPtr<IBitmapFrame> frame; - hr = QWinRTFunctions::await(op2, frame.GetAddressOf()); - Q_ASSERT_SUCCEEDED(hr); - - ComPtr<IBitmapTransform> transform; - hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Graphics_Imaging_BitmapTransform).Get(), - &transform); - Q_ASSERT_SUCCEEDED(hr); - - ComPtr<IAsyncOperation<PixelDataProvider *>> op3; - hr = frame->GetPixelDataTransformedAsync(BitmapPixelFormat_Rgba8, BitmapAlphaMode_Straight, - transform.Get(), ExifOrientationMode_IgnoreExifOrientation, - ColorManagementMode_DoNotColorManage, &op3); - Q_ASSERT_SUCCEEDED(hr); - ComPtr<IPixelDataProvider> pixelDataProvider; - hr = QWinRTFunctions::await(op3, pixelDataProvider.GetAddressOf()); - Q_ASSERT_SUCCEEDED(hr); - - UINT32 pixelDataSize; - BYTE *pixelData; - hr = pixelDataProvider->DetachPixelData(&pixelDataSize, &pixelData); - - UINT32 pixelHeight; - hr = frame->get_PixelHeight(&pixelHeight); - Q_ASSERT_SUCCEEDED(hr); - UINT32 pixelWidth; - hr = frame->get_PixelWidth(&pixelWidth); - Q_ASSERT_SUCCEEDED(hr); - const QImage image(pixelData, int(pixelWidth), int(pixelHeight), - QImage::Format_RGBA8888, - reinterpret_cast<QImageCleanupFunction>(&freeImageData), pixelData); - emit imageCaptured(request.id, image); - - 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")); - - return S_OK; -} - -QT_END_NAMESPACE |