summaryrefslogtreecommitdiffstats
path: root/src/plugins/winrt/qwinrtcameracontrol.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/winrt/qwinrtcameracontrol.cpp')
-rw-r--r--src/plugins/winrt/qwinrtcameracontrol.cpp1468
1 files changed, 0 insertions, 1468 deletions
diff --git a/src/plugins/winrt/qwinrtcameracontrol.cpp b/src/plugins/winrt/qwinrtcameracontrol.cpp
deleted file mode 100644
index 98dd7c2f7..000000000
--- a/src/plugins/winrt/qwinrtcameracontrol.cpp
+++ /dev/null
@@ -1,1468 +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 "qwinrtcameracontrol.h"
-#include "qwinrtcameravideorenderercontrol.h"
-#include "qwinrtvideodeviceselectorcontrol.h"
-#include "qwinrtcameraimagecapturecontrol.h"
-#include "qwinrtimageencodercontrol.h"
-#include "qwinrtcameraflashcontrol.h"
-#include "qwinrtcamerafocuscontrol.h"
-#include "qwinrtcameralockscontrol.h"
-
-#include <QtCore/qfunctions_winrt.h>
-#include <QtCore/QMutex>
-#include <QtCore/QPointer>
-#include <QtGui/QGuiApplication>
-#include <private/qeventdispatcher_winrt_p.h>
-
-#include <functional>
-#include <mfapi.h>
-#include <mferror.h>
-#include <mfidl.h>
-#include <wrl.h>
-#include <windows.devices.enumeration.h>
-#include <windows.media.capture.h>
-#include <windows.storage.streams.h>
-#include <windows.media.devices.h>
-
-#include <algorithm>
-
-using namespace Microsoft::WRL;
-using namespace Microsoft::WRL::Wrappers;
-using namespace ABI::Windows::Devices::Enumeration;
-using namespace ABI::Windows::Foundation;
-using namespace ABI::Windows::Foundation::Collections;
-using namespace ABI::Windows::Media;
-using namespace ABI::Windows::Media::Capture;
-using namespace ABI::Windows::Media::Devices;
-using namespace ABI::Windows::Media::MediaProperties;
-using namespace ABI::Windows::Storage::Streams;
-
-QT_BEGIN_NAMESPACE
-
-#define RETURN_VOID_AND_EMIT_ERROR(msg) \
- if (FAILED(hr)) { \
- emit error(QCamera::CameraError, qt_error_string(hr)); \
- RETURN_VOID_IF_FAILED(msg); \
- }
-
-#define FOCUS_RECT_SIZE 0.01f
-#define FOCUS_RECT_HALF_SIZE 0.005f // FOCUS_RECT_SIZE / 2
-#define FOCUS_RECT_BOUNDARY 1.0f
-#define FOCUS_RECT_POSITION_MIN 0.0f
-#define FOCUS_RECT_POSITION_MAX 0.995f // FOCUS_RECT_BOUNDARY - FOCUS_RECT_HALF_SIZE
-#define ASPECTRATIO_EPSILON 0.01f
-
-Q_LOGGING_CATEGORY(lcMMCamera, "qt.mm.camera")
-
-HRESULT getMediaStreamResolutions(IMediaDeviceController *device,
- MediaStreamType type,
- IVectorView<IMediaEncodingProperties *> **propertiesList,
- QVector<QSize> *resolutions)
-{
- HRESULT hr;
- hr = device->GetAvailableMediaStreamProperties(type, propertiesList);
- Q_ASSERT_SUCCEEDED(hr);
- quint32 listSize;
- hr = (*propertiesList)->get_Size(&listSize);
- Q_ASSERT_SUCCEEDED(hr);
- resolutions->reserve(int(listSize));
- for (quint32 index = 0; index < listSize; ++index) {
- ComPtr<IMediaEncodingProperties> properties;
- hr = (*propertiesList)->GetAt(index, &properties);
- Q_ASSERT_SUCCEEDED(hr);
- HString propertyType;
- hr = properties->get_Type(propertyType.GetAddressOf());
- Q_ASSERT_SUCCEEDED(hr);
-
- const HStringReference videoRef = HString::MakeReference(L"Video");
- const HStringReference imageRef = HString::MakeReference(L"Image");
- if (propertyType == videoRef) {
- ComPtr<IVideoEncodingProperties> videoProperties;
- hr = properties.As(&videoProperties);
- Q_ASSERT_SUCCEEDED(hr);
- UINT32 width, height;
- hr = videoProperties->get_Width(&width);
- Q_ASSERT_SUCCEEDED(hr);
- hr = videoProperties->get_Height(&height);
- Q_ASSERT_SUCCEEDED(hr);
- resolutions->append(QSize(int(width), int(height)));
- } else if (propertyType == imageRef) {
- ComPtr<IImageEncodingProperties> imageProperties;
- hr = properties.As(&imageProperties);
- Q_ASSERT_SUCCEEDED(hr);
- UINT32 width, height;
- hr = imageProperties->get_Width(&width);
- Q_ASSERT_SUCCEEDED(hr);
- hr = imageProperties->get_Height(&height);
- Q_ASSERT_SUCCEEDED(hr);
- resolutions->append(QSize(int(width), int(height)));
- }
- }
- return resolutions->isEmpty() ? MF_E_INVALID_FORMAT : hr;
-}
-
-template<typename T, size_t typeSize> struct CustomPropertyValue;
-
-inline static ComPtr<IPropertyValueStatics> propertyValueStatics()
-{
- ComPtr<IPropertyValueStatics> valueStatics;
- GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Foundation_PropertyValue).Get(), &valueStatics);
- return valueStatics;
-}
-
-template <typename T>
-struct CustomPropertyValue<T, 4>
-{
- static ComPtr<IReference<T>> create(T value)
- {
- ComPtr<IInspectable> propertyValueObject;
- HRESULT hr = propertyValueStatics()->CreateUInt32(value, &propertyValueObject);
- ComPtr<IReference<UINT32>> uint32Object;
- Q_ASSERT_SUCCEEDED(hr);
- hr = propertyValueObject.As(&uint32Object);
- Q_ASSERT_SUCCEEDED(hr);
- return reinterpret_cast<IReference<T> *>(uint32Object.Get());
- }
-};
-
-template <typename T>
-struct CustomPropertyValue<T, 8>
-{
- static ComPtr<IReference<T>> create(T value)
- {
- ComPtr<IInspectable> propertyValueObject;
- HRESULT hr = propertyValueStatics()->CreateUInt64(value, &propertyValueObject);
- ComPtr<IReference<UINT64>> uint64Object;
- Q_ASSERT_SUCCEEDED(hr);
- hr = propertyValueObject.As(&uint64Object);
- Q_ASSERT_SUCCEEDED(hr);
- return reinterpret_cast<IReference<T> *>(uint64Object.Get());
- }
-};
-
-// Required camera point focus
-class WindowsRegionOfInterestIterableIterator : public RuntimeClass<IIterator<RegionOfInterest *>>
-{
-public:
- explicit WindowsRegionOfInterestIterableIterator(const ComPtr<IRegionOfInterest> &item)
- {
- regionOfInterest = item;
- }
- HRESULT __stdcall get_Current(IRegionOfInterest **current)
- {
- *current = regionOfInterest.Detach();
- return S_OK;
- }
- HRESULT __stdcall get_HasCurrent(boolean *hasCurrent)
- {
- *hasCurrent = true;
- return S_OK;
- }
- HRESULT __stdcall MoveNext(boolean *hasCurrent)
- {
- *hasCurrent = false;
- return S_OK;
- }
-private:
- ComPtr<IRegionOfInterest> regionOfInterest;
-};
-
-class WindowsRegionOfInterestIterable : public RuntimeClass<IIterable<RegionOfInterest *>>
-{
-public:
- explicit WindowsRegionOfInterestIterable(const ComPtr<IRegionOfInterest> &item)
- {
- regionOfInterest = item;
- }
- HRESULT __stdcall First(IIterator<RegionOfInterest *> **first)
- {
- ComPtr<WindowsRegionOfInterestIterableIterator> iterator = Make<WindowsRegionOfInterestIterableIterator>(regionOfInterest);
- *first = iterator.Detach();
- return S_OK;
- }
-private:
- ComPtr<IRegionOfInterest> regionOfInterest;
-};
-
-class MediaStream : public RuntimeClass<RuntimeClassFlags<WinRtClassicComMix>, IMFStreamSink, IMFMediaEventGenerator, IMFMediaTypeHandler>
-{
-public:
- MediaStream(IMFMediaType *type, IMFMediaSink *mediaSink, QWinRTCameraVideoRendererControl *videoRenderer)
- : m_type(type), m_sink(mediaSink), m_videoRenderer(videoRenderer)
- {
- Q_ASSERT(m_videoRenderer);
-
- HRESULT hr;
- hr = MFCreateEventQueue(&m_eventQueue);
- Q_ASSERT_SUCCEEDED(hr);
- hr = MFAllocateSerialWorkQueue(MFASYNC_CALLBACK_QUEUE_STANDARD, &m_workQueueId);
- Q_ASSERT_SUCCEEDED(hr);
- }
-
- ~MediaStream() override
- {
- QMutexLocker locker(&m_mutex);
- m_eventQueue->Shutdown();
- }
-
- HRESULT RequestSample()
- {
- if (m_pendingSamples.load() < 3) {
- m_pendingSamples.ref();
- return QueueEvent(MEStreamSinkRequestSample, GUID_NULL, S_OK, nullptr);
- }
- return S_OK;
- }
-
- HRESULT __stdcall GetEvent(DWORD flags, IMFMediaEvent **event) override
- {
- QMutexLocker locker(&m_mutex);
- // Create an extra reference to avoid deadlock
- ComPtr<IMFMediaEventQueue> eventQueue = m_eventQueue;
- locker.unlock();
-
- return eventQueue->GetEvent(flags, event);
- }
-
- HRESULT __stdcall BeginGetEvent(IMFAsyncCallback *callback, IUnknown *state) override
- {
- QMutexLocker locker(&m_mutex);
- HRESULT hr = m_eventQueue->BeginGetEvent(callback, state);
- return hr;
- }
-
- HRESULT __stdcall EndGetEvent(IMFAsyncResult *result, IMFMediaEvent **event) override
- {
- QMutexLocker locker(&m_mutex);
- return m_eventQueue->EndGetEvent(result, event);
- }
-
- HRESULT __stdcall QueueEvent(MediaEventType eventType, const GUID &extendedType, HRESULT status, const PROPVARIANT *value) override
- {
- QMutexLocker locker(&m_mutex);
- return m_eventQueue->QueueEventParamVar(eventType, extendedType, status, value);
- }
-
- HRESULT __stdcall GetMediaSink(IMFMediaSink **mediaSink) override
- {
- m_sink->AddRef();
- *mediaSink = m_sink;
- return S_OK;
- }
-
- HRESULT __stdcall GetIdentifier(DWORD *identifier) override
- {
- *identifier = 0;
- return S_OK;
- }
-
- HRESULT __stdcall GetMediaTypeHandler(IMFMediaTypeHandler **handler) override
- {
- return QueryInterface(IID_PPV_ARGS(handler));
- }
-
- HRESULT __stdcall ProcessSample(IMFSample *sample) override
- {
- ComPtr<IMFMediaBuffer> buffer;
- HRESULT hr = sample->GetBufferByIndex(0, &buffer);
- RETURN_HR_IF_FAILED("Failed to get buffer from camera sample");
- ComPtr<IMF2DBuffer> buffer2d;
- hr = buffer.As(&buffer2d);
- RETURN_HR_IF_FAILED("Failed to cast camera sample buffer to 2D buffer");
-
- m_pendingSamples.deref();
- m_videoRenderer->queueBuffer(buffer2d.Get());
-
- return hr;
- }
-
- HRESULT __stdcall PlaceMarker(MFSTREAMSINK_MARKER_TYPE type, const PROPVARIANT *value, const PROPVARIANT *context) override
- {
- Q_UNUSED(type);
- Q_UNUSED(value);
- QueueEvent(MEStreamSinkMarker, GUID_NULL, S_OK, context);
- return S_OK;
- }
-
- HRESULT __stdcall Flush() override
- {
- m_videoRenderer->discardBuffers();
- m_pendingSamples.store(0);
- return S_OK;
- }
-
- HRESULT __stdcall IsMediaTypeSupported(IMFMediaType *type, IMFMediaType **) override
- {
- HRESULT hr;
- GUID majorType;
- hr = type->GetMajorType(&majorType);
- Q_ASSERT_SUCCEEDED(hr);
- if (!IsEqualGUID(majorType, MFMediaType_Video))
- return MF_E_INVALIDMEDIATYPE;
- return S_OK;
- }
-
- HRESULT __stdcall GetMediaTypeCount(DWORD *typeCount) override
- {
- *typeCount = 1;
- return S_OK;
- }
-
- HRESULT __stdcall GetMediaTypeByIndex(DWORD index, IMFMediaType **type) override
- {
- if (index == 0)
- return m_type.CopyTo(type);
- return E_BOUNDS;
- }
-
- HRESULT __stdcall SetCurrentMediaType(IMFMediaType *type) override
- {
- if (FAILED(IsMediaTypeSupported(type, nullptr)))
- return MF_E_INVALIDREQUEST;
-
- m_type = type;
- return S_OK;
- }
-
- HRESULT __stdcall GetCurrentMediaType(IMFMediaType **type) override
- {
- return m_type.CopyTo(type);
- }
-
- HRESULT __stdcall GetMajorType(GUID *majorType) override
- {
- return m_type->GetMajorType(majorType);
- }
-
-private:
- QMutex m_mutex;
- ComPtr<IMFMediaType> m_type;
- IMFMediaSink *m_sink;
- ComPtr<IMFMediaEventQueue> m_eventQueue;
- DWORD m_workQueueId;
-
- QWinRTCameraVideoRendererControl *m_videoRenderer;
- QAtomicInt m_pendingSamples;
-};
-
-class MediaSink : public RuntimeClass<RuntimeClassFlags<WinRtClassicComMix>, IMediaExtension, IMFMediaSink, IMFClockStateSink>
-{
-public:
- MediaSink(IMediaEncodingProfile *encodingProfile, QWinRTCameraVideoRendererControl *videoRenderer)
- : m_videoRenderer(videoRenderer)
- {
- HRESULT hr;
- ComPtr<IVideoEncodingProperties> videoProperties;
- hr = encodingProfile->get_Video(&videoProperties);
- RETURN_VOID_IF_FAILED("Failed to get video properties");
- ComPtr<IMFMediaType> videoType;
- hr = MFCreateMediaTypeFromProperties(videoProperties.Get(), &videoType);
- RETURN_VOID_IF_FAILED("Failed to create video type");
- m_stream = Make<MediaStream>(videoType.Get(), this, videoRenderer);
- }
-
- ~MediaSink() override = default;
-
- HRESULT RequestSample()
- {
- return m_stream->RequestSample();
- }
-
- HRESULT __stdcall SetProperties(Collections::IPropertySet *configuration) override
- {
- Q_UNUSED(configuration);
- return E_NOTIMPL;
- }
-
- HRESULT __stdcall GetCharacteristics(DWORD *characteristics) override
- {
- *characteristics = MEDIASINK_FIXED_STREAMS | MEDIASINK_RATELESS;
- return S_OK;
- }
-
- HRESULT __stdcall AddStreamSink(DWORD streamSinkIdentifier, IMFMediaType *mediaType, IMFStreamSink **streamSink) override
- {
- Q_UNUSED(streamSinkIdentifier);
- Q_UNUSED(mediaType);
- Q_UNUSED(streamSink);
- return E_NOTIMPL;
- }
-
- HRESULT __stdcall RemoveStreamSink(DWORD streamSinkIdentifier) override
- {
- Q_UNUSED(streamSinkIdentifier);
- return E_NOTIMPL;
- }
-
- HRESULT __stdcall GetStreamSinkCount(DWORD *streamSinkCount) override
- {
- *streamSinkCount = 1;
- return S_OK;
- }
-
- HRESULT __stdcall GetStreamSinkByIndex(DWORD index, IMFStreamSink **streamSink) override
- {
- if (index == 0)
- return m_stream.CopyTo(streamSink);
- return MF_E_INVALIDINDEX;
- }
-
- HRESULT __stdcall GetStreamSinkById(DWORD streamSinkIdentifier, IMFStreamSink **streamSink) override
- {
- // ID and index are always 0
- HRESULT hr = GetStreamSinkByIndex(streamSinkIdentifier, streamSink);
- return hr == MF_E_INVALIDINDEX ? MF_E_INVALIDSTREAMNUMBER : hr;
- }
-
- HRESULT __stdcall SetPresentationClock(IMFPresentationClock *presentationClock) override
- {
- HRESULT hr = S_OK;
- m_presentationClock = presentationClock;
- if (m_presentationClock)
- hr = m_presentationClock->AddClockStateSink(this);
- return hr;
- }
-
- HRESULT __stdcall GetPresentationClock(IMFPresentationClock **presentationClock) override
- {
- return m_presentationClock.CopyTo(presentationClock);
- }
-
- HRESULT __stdcall Shutdown() override
- {
- m_stream->Flush();
- scheduleSetActive(false);
- return m_presentationClock ? m_presentationClock->Stop() : S_OK;
- }
-
- HRESULT __stdcall OnClockStart(MFTIME systemTime, LONGLONG clockStartOffset) override
- {
- Q_UNUSED(systemTime);
- Q_UNUSED(clockStartOffset);
-
- scheduleSetActive(true);
-
- return S_OK;
- }
-
- HRESULT __stdcall OnClockStop(MFTIME systemTime) override
- {
- Q_UNUSED(systemTime);
-
- scheduleSetActive(false);
-
- return m_stream->QueueEvent(MEStreamSinkStopped, GUID_NULL, S_OK, nullptr);
- }
-
- HRESULT __stdcall OnClockPause(MFTIME systemTime) override
- {
- Q_UNUSED(systemTime);
-
- scheduleSetActive(false);
-
- return m_stream->QueueEvent(MEStreamSinkPaused, GUID_NULL, S_OK, nullptr);
- }
-
- HRESULT __stdcall OnClockRestart(MFTIME systemTime) override
- {
- Q_UNUSED(systemTime);
-
- scheduleSetActive(true);
-
- return m_stream->QueueEvent(MEStreamSinkStarted, GUID_NULL, S_OK, nullptr);
- }
-
- HRESULT __stdcall OnClockSetRate(MFTIME systemTime, float rate) override
- {
- Q_UNUSED(systemTime);
- Q_UNUSED(rate);
- return E_NOTIMPL;
- }
-
-private:
-
- inline void scheduleSetActive(bool active)
- {
- QMetaObject::invokeMethod(m_videoRenderer, "setActive", Qt::QueuedConnection, Q_ARG(bool, active));
- }
-
- ComPtr<MediaStream> m_stream;
- ComPtr<IMFPresentationClock> m_presentationClock;
-
- QWinRTCameraVideoRendererControl *m_videoRenderer;
-};
-
-class QWinRTCameraControlPrivate
-{
-public:
- QCamera::State state;
- QCamera::Status status;
- QCamera::CaptureModes captureMode;
-
- ComPtr<IMediaCapture> capture;
- ComPtr<IMediaCaptureVideoPreview> capturePreview;
- EventRegistrationToken captureFailedCookie;
- EventRegistrationToken recordLimitationCookie;
-
- ComPtr<IMediaEncodingProfileStatics> encodingProfileFactory;
-
- ComPtr<IMediaEncodingProfile> encodingProfile;
- ComPtr<MediaSink> mediaSink;
- ComPtr<IFocusControl> focusControl;
- ComPtr<IRegionsOfInterestControl> regionsOfInterestControl;
- ComPtr<IAsyncAction> focusOperation;
-
- QPointer<QWinRTCameraVideoRendererControl> videoRenderer;
- QPointer<QWinRTVideoDeviceSelectorControl> videoDeviceSelector;
- QPointer<QWinRTCameraImageCaptureControl> imageCaptureControl;
- QPointer<QWinRTImageEncoderControl> imageEncoderControl;
- QPointer<QWinRTCameraFlashControl> cameraFlashControl;
- QPointer<QWinRTCameraFocusControl> cameraFocusControl;
- QPointer<QWinRTCameraLocksControl> cameraLocksControl;
- QAtomicInt framesMapped;
- QEventLoop *delayClose;
-
- bool initializing = false;
- bool initialized = false;
- HANDLE initializationCompleteEvent;
-};
-
-QWinRTCameraControl::QWinRTCameraControl(QObject *parent)
- : QCameraControl(parent), d_ptr(new QWinRTCameraControlPrivate)
-{
- qCDebug(lcMMCamera) << __FUNCTION__ << parent;
- Q_D(QWinRTCameraControl);
-
- d->delayClose = nullptr;
- d->state = QCamera::UnloadedState;
- d->status = QCamera::UnloadedStatus;
- d->captureMode = QCamera::CaptureStillImage;
- d->captureFailedCookie.value = 0;
- d->recordLimitationCookie.value = 0;
- d->videoRenderer = new QWinRTCameraVideoRendererControl(QSize(), this);
- connect(d->videoRenderer, &QWinRTCameraVideoRendererControl::bufferRequested,
- this, &QWinRTCameraControl::onBufferRequested);
- d->videoDeviceSelector = new QWinRTVideoDeviceSelectorControl(this);
- connect(d->videoDeviceSelector, QOverload<int>::of(&QWinRTVideoDeviceSelectorControl::selectedDeviceChanged),
- d->videoRenderer, &QWinRTCameraVideoRendererControl::resetSampleFormat);
- d->imageCaptureControl = new QWinRTCameraImageCaptureControl(this);
- d->imageEncoderControl = new QWinRTImageEncoderControl(this);
- d->cameraFlashControl = new QWinRTCameraFlashControl(this);
- d->cameraFocusControl = new QWinRTCameraFocusControl(this);
- d->cameraLocksControl = new QWinRTCameraLocksControl(this);
-
- d->initializationCompleteEvent = CreateEvent(nullptr, false, false, nullptr);
-
- if (qGuiApp) {
- connect(qGuiApp, &QGuiApplication::applicationStateChanged,
- this, &QWinRTCameraControl::onApplicationStateChanged);
- }
-}
-
-QWinRTCameraControl::~QWinRTCameraControl()
-{
- setState(QCamera::UnloadedState);
-}
-
-QCamera::State QWinRTCameraControl::state() const
-{
- Q_D(const QWinRTCameraControl);
- return d->state;
-}
-
-void QWinRTCameraControl::setState(QCamera::State state)
-{
- qCDebug(lcMMCamera) << __FUNCTION__ << state;
- Q_D(QWinRTCameraControl);
-
- if (d->state == state)
- return;
-
- HRESULT hr;
- switch (state) {
- case QCamera::ActiveState: {
- // Capture has not been created or initialized
- if (d->state == QCamera::UnloadedState) {
- if (!d->initialized) {
- if (!d->initializing) {
- hr = initialize();
- RETURN_VOID_AND_EMIT_ERROR("Failed to initialize media capture");
- }
- DWORD waitResult = WaitForSingleObjectEx(d->initializationCompleteEvent, 30000, FALSE);
- if (waitResult != WAIT_OBJECT_0) {
- RETURN_VOID_AND_EMIT_ERROR("Failed to initialize camera control.");
- return;
- }
- }
-
- d->state = QCamera::LoadedState;
- emit stateChanged(d->state);
-
- d->status = QCamera::LoadedStatus;
- emit statusChanged(d->status);
- }
- Q_ASSERT(d->state == QCamera::LoadedState);
-
- ComPtr<IAsyncAction> op;
- hr = QEventDispatcherWinRT::runOnXamlThread([d, &op]() {
- d->mediaSink = Make<MediaSink>(d->encodingProfile.Get(), d->videoRenderer);
- HRESULT hr = d->capturePreview->StartPreviewToCustomSinkAsync(d->encodingProfile.Get(), d->mediaSink.Get(), &op);
- return hr;
- });
- RETURN_VOID_AND_EMIT_ERROR("Failed to initiate capture.");
- if (d->status != QCamera::StartingStatus) {
- d->status = QCamera::StartingStatus;
- emit statusChanged(d->status);
- }
-
- hr = QEventDispatcherWinRT::runOnXamlThread([&op]() {
- return QWinRTFunctions::await(op);
- });
- if (FAILED(hr)) {
- emit error(QCamera::CameraError, qt_error_string(hr));
- setState(QCamera::UnloadedState); // Unload everything, as initialize() will need be called again
- return;
- }
-
- QCameraFocus::FocusModes focusMode = d->cameraFocusControl->focusMode();
- if (focusMode != 0 && setFocus(focusMode) && focusMode == QCameraFocus::ContinuousFocus)
- focus();
-
- d->state = QCamera::ActiveState;
- emit stateChanged(d->state);
- d->status = QCamera::ActiveStatus;
- emit statusChanged(d->status);
- QEventDispatcherWinRT::runOnXamlThread([d]() { d->mediaSink->RequestSample(); return S_OK;});
- break;
- }
- case QCamera::LoadedState: {
- // If moving from unloaded, initialize the camera
- if (d->state == QCamera::UnloadedState) {
- if (!d->initialized) {
- if (!d->initializing) {
- hr = initialize();
- RETURN_VOID_AND_EMIT_ERROR("Failed to initialize media capture");
- }
- DWORD waitResult = WaitForSingleObjectEx(d->initializationCompleteEvent, 30000, FALSE);
- if (waitResult != WAIT_OBJECT_0) {
- RETURN_VOID_AND_EMIT_ERROR("Failed to initialize camera control.");
- return;
- }
- }
-
- d->state = QCamera::LoadedState;
- emit stateChanged(d->state);
-
- d->status = QCamera::LoadedStatus;
- emit statusChanged(d->status);
- }
- // fall through
- }
- case QCamera::UnloadedState: {
- // Stop the camera if it is running (transition to LoadedState)
- if (d->status == QCamera::ActiveStatus) {
- HRESULT hr;
- if (d->focusOperation) {
- hr = QWinRTFunctions::await(d->focusOperation);
- Q_ASSERT_SUCCEEDED(hr);
- }
- if (d->framesMapped > 0) {
- qWarning("%d QVideoFrame(s) mapped when closing down camera. Camera will wait for unmap before closing down.",
- d->framesMapped);
- if (!d->delayClose)
- d->delayClose = new QEventLoop(this);
- d->delayClose->exec();
- }
-
- ComPtr<IAsyncAction> op;
- hr = QEventDispatcherWinRT::runOnXamlThread([d, &op]() {
- HRESULT hr = d->capturePreview->StopPreviewAsync(&op);
- return hr;
- });
- RETURN_VOID_AND_EMIT_ERROR("Failed to stop camera preview");
- if (d->status != QCamera::StoppingStatus) {
- d->status = QCamera::StoppingStatus;
- emit statusChanged(d->status);
- }
- Q_ASSERT_SUCCEEDED(hr);
- hr = QEventDispatcherWinRT::runOnXamlThread([&op]() {
- return QWinRTFunctions::await(op); // Synchronize unloading
- });
- if (FAILED(hr))
- emit error(QCamera::InvalidRequestError, qt_error_string(hr));
-
- if (d->mediaSink) {
- hr = QEventDispatcherWinRT::runOnXamlThread([d]() {
- d->mediaSink->Shutdown();
- d->mediaSink.Reset();
- return S_OK;
- });
- }
-
- d->state = QCamera::LoadedState;
- emit stateChanged(d->state);
-
- d->status = QCamera::LoadedStatus;
- emit statusChanged(d->status);
- }
- // Completely unload if needed
- if (state == QCamera::UnloadedState) {
- if (!d->capture) // Already unloaded
- break;
-
- if (d->status != QCamera::UnloadingStatus) {
- d->status = QCamera::UnloadingStatus;
- emit statusChanged(d->status);
- }
-
- hr = QEventDispatcherWinRT::runOnXamlThread([d]() {
- HRESULT hr;
- if (d->capture && d->captureFailedCookie.value) {
- hr = d->capture->remove_Failed(d->captureFailedCookie);
- Q_ASSERT_SUCCEEDED(hr);
- d->captureFailedCookie.value = 0;
- }
- if (d->capture && d->recordLimitationCookie.value) {
- d->capture->remove_RecordLimitationExceeded(d->recordLimitationCookie);
- Q_ASSERT_SUCCEEDED(hr);
- d->recordLimitationCookie.value = 0;
- }
- ComPtr<IClosable> capture;
- hr = d->capture.As(&capture);
- Q_ASSERT_SUCCEEDED(hr);
- hr = capture->Close();
- RETURN_HR_IF_FAILED("");
- d->capture.Reset();
- return hr;
- });
- RETURN_VOID_AND_EMIT_ERROR("Failed to close the capture manger");
- if (d->state != QCamera::UnloadedState) {
- d->state = QCamera::UnloadedState;
- emit stateChanged(d->state);
- }
- if (d->status != QCamera::UnloadedStatus) {
- d->status = QCamera::UnloadedStatus;
- emit statusChanged(d->status);
- }
- d->initialized = false;
- }
- break;
- }
- default:
- break;
- }
-}
-
-QCamera::Status QWinRTCameraControl::status() const
-{
- Q_D(const QWinRTCameraControl);
- return d->status;
-}
-
-QCamera::CaptureModes QWinRTCameraControl::captureMode() const
-{
- Q_D(const QWinRTCameraControl);
- return d->captureMode;
-}
-
-void QWinRTCameraControl::setCaptureMode(QCamera::CaptureModes mode)
-{
- qCDebug(lcMMCamera) << __FUNCTION__ << mode;
- Q_D(QWinRTCameraControl);
-
- if (d->captureMode == mode)
- return;
-
- if (!isCaptureModeSupported(mode)) {
- qWarning("Unsupported capture mode: %d", mode);
- return;
- }
-
- d->captureMode = mode;
- emit captureModeChanged(d->captureMode);
-}
-
-bool QWinRTCameraControl::isCaptureModeSupported(QCamera::CaptureModes mode) const
-{
- return mode >= QCamera::CaptureViewfinder && mode <= QCamera::CaptureStillImage;
-}
-
-bool QWinRTCameraControl::canChangeProperty(QCameraControl::PropertyChangeType changeType, QCamera::Status status) const
-{
- Q_UNUSED(changeType);
-
- return status == QCamera::UnloadedStatus; // For now, assume shutdown is required for all property changes
-}
-
-QVideoRendererControl *QWinRTCameraControl::videoRenderer() const
-{
- Q_D(const QWinRTCameraControl);
- return d->videoRenderer;
-}
-
-QVideoDeviceSelectorControl *QWinRTCameraControl::videoDeviceSelector() const
-{
- Q_D(const QWinRTCameraControl);
- return d->videoDeviceSelector;
-}
-
-QCameraImageCaptureControl *QWinRTCameraControl::imageCaptureControl() const
-{
- Q_D(const QWinRTCameraControl);
- return d->imageCaptureControl;
-}
-
-QImageEncoderControl *QWinRTCameraControl::imageEncoderControl() const
-{
- Q_D(const QWinRTCameraControl);
- return d->imageEncoderControl;
-}
-
-QCameraFlashControl *QWinRTCameraControl::cameraFlashControl() const
-{
- Q_D(const QWinRTCameraControl);
- return d->cameraFlashControl;
-}
-
-QCameraFocusControl *QWinRTCameraControl::cameraFocusControl() const
-{
- Q_D(const QWinRTCameraControl);
- return d->cameraFocusControl;
-}
-
-QCameraLocksControl *QWinRTCameraControl::cameraLocksControl() const
-{
- Q_D(const QWinRTCameraControl);
- return d->cameraLocksControl;
-}
-
-Microsoft::WRL::ComPtr<ABI::Windows::Media::Capture::IMediaCapture> QWinRTCameraControl::handle() const
-{
- Q_D(const QWinRTCameraControl);
- return d->capture;
-}
-
-void QWinRTCameraControl::onBufferRequested()
-{
- Q_D(QWinRTCameraControl);
-
- if (d->mediaSink)
- d->mediaSink->RequestSample();
-}
-
-void QWinRTCameraControl::onApplicationStateChanged(Qt::ApplicationState state)
-{
- qCDebug(lcMMCamera) << __FUNCTION__ << state;
-#ifdef _DEBUG
- return;
-#else // !_DEBUG
- Q_D(QWinRTCameraControl);
- static QCamera::State savedState = d->state;
- switch (state) {
- case Qt::ApplicationInactive:
- if (d->state != QCamera::UnloadedState) {
- savedState = d->state;
- setState(QCamera::UnloadedState);
- }
- break;
- case Qt::ApplicationActive:
- setState(QCamera::State(savedState));
- break;
- default:
- break;
- }
-#endif // _DEBUG
-}
-
-HRESULT QWinRTCameraControl::initialize()
-{
- qCDebug(lcMMCamera) << __FUNCTION__;
- Q_D(QWinRTCameraControl);
-
- if (d->status != QCamera::LoadingStatus) {
- d->status = QCamera::LoadingStatus;
- emit statusChanged(d->status);
- }
-
- HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([this, d]() {
- HRESULT hr;
- ComPtr<IInspectable> capture;
- hr = RoActivateInstance(Wrappers::HString::MakeReference(RuntimeClass_Windows_Media_Capture_MediaCapture).Get(),
- &capture);
- Q_ASSERT_SUCCEEDED(hr);
- hr = capture.As(&d->capture);
- Q_ASSERT_SUCCEEDED(hr);
- hr = d->capture.As(&d->capturePreview);
- Q_ASSERT_SUCCEEDED(hr);
- hr = d->capture->add_Failed(Callback<IMediaCaptureFailedEventHandler>(this, &QWinRTCameraControl::onCaptureFailed).Get(),
- &d->captureFailedCookie);
- Q_ASSERT_SUCCEEDED(hr);
- hr = d->capture->add_RecordLimitationExceeded(Callback<IRecordLimitationExceededEventHandler>(this, &QWinRTCameraControl::onRecordLimitationExceeded).Get(),
- &d->recordLimitationCookie);
- Q_ASSERT_SUCCEEDED(hr);
- hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Media_MediaProperties_MediaEncodingProfile).Get(),
- IID_PPV_ARGS(&d->encodingProfileFactory));
- Q_ASSERT_SUCCEEDED(hr);
-
- int deviceIndex = d->videoDeviceSelector->selectedDevice();
- if (deviceIndex < 0)
- deviceIndex = d->videoDeviceSelector->defaultDevice();
-
- const QString deviceName = d->videoDeviceSelector->deviceName(deviceIndex);
- if (deviceName.isEmpty()) {
- qWarning("No video device available or selected.");
- return E_FAIL;
- }
-
- d->videoRenderer->setScanLineDirection(QVideoSurfaceFormat::TopToBottom);
- ComPtr<IMediaCaptureInitializationSettings> settings;
- hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Media_Capture_MediaCaptureInitializationSettings).Get(),
- &settings);
- Q_ASSERT_SUCCEEDED(hr);
- HStringReference deviceId(reinterpret_cast<LPCWSTR>(deviceName.utf16()), uint(deviceName.length()));
- hr = settings->put_VideoDeviceId(deviceId.Get());
- Q_ASSERT_SUCCEEDED(hr);
-
- hr = settings->put_StreamingCaptureMode(StreamingCaptureMode_Video);
- Q_ASSERT_SUCCEEDED(hr);
-
- hr = settings->put_PhotoCaptureSource(PhotoCaptureSource_Auto);
- Q_ASSERT_SUCCEEDED(hr);
-
- ComPtr<IAsyncAction> op;
- hr = d->capture->InitializeWithSettingsAsync(settings.Get(), &op);
- RETURN_HR_IF_FAILED("Failed to begin initialization of media capture manager");
- hr = op.Get()->put_Completed(Callback<IAsyncActionCompletedHandler>(
- this, &QWinRTCameraControl::onInitializationCompleted).Get());
- RETURN_HR_IF_FAILED("Failed to register initialization callback");
- return S_OK;
- });
- return hr;
-}
-
-#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
-
-HRESULT QWinRTCameraControl::initializeFocus()
-{
- Q_D(QWinRTCameraControl);
- ComPtr<IFocusControl2> focusControl2;
- HRESULT hr = d->focusControl.As(&focusControl2);
- Q_ASSERT_SUCCEEDED(hr);
- ComPtr<IVectorView<enum FocusMode>> focusModes;
- hr = focusControl2->get_SupportedFocusModes(&focusModes);
- if (FAILED(hr)) {
- d->cameraFocusControl->setSupportedFocusMode(nullptr);
- d->cameraFocusControl->setSupportedFocusPointMode(QSet<QCameraFocus::FocusPointMode>());
- qErrnoWarning(hr, "Failed to get camera supported focus mode list");
- return hr;
- }
- quint32 size;
- hr = focusModes->get_Size(&size);
- Q_ASSERT_SUCCEEDED(hr);
- QCameraFocus::FocusModes supportedModeFlag = nullptr;
- for (quint32 i = 0; i < size; ++i) {
- FocusMode mode;
- hr = focusModes->GetAt(i, &mode);
- Q_ASSERT_SUCCEEDED(hr);
- switch (mode) {
- case FocusMode_Continuous:
- supportedModeFlag |= QCameraFocus::ContinuousFocus;
- break;
- case FocusMode_Single:
- supportedModeFlag |= QCameraFocus::AutoFocus;
- break;
- default:
- break;
- }
- }
-
- ComPtr<IVectorView<enum AutoFocusRange>> focusRange;
- hr = focusControl2->get_SupportedFocusRanges(&focusRange);
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to get camera supported focus range list");
- } else {
- hr = focusRange->get_Size(&size);
- Q_ASSERT_SUCCEEDED(hr);
- for (quint32 i = 0; i < size; ++i) {
- AutoFocusRange range;
- hr = focusRange->GetAt(i, &range);
- Q_ASSERT_SUCCEEDED(hr);
- switch (range) {
- case AutoFocusRange_Macro:
- supportedModeFlag |= QCameraFocus::MacroFocus;
- break;
- case AutoFocusRange_FullRange:
- supportedModeFlag |= QCameraFocus::InfinityFocus;
- break;
- default:
- break;
- }
- }
- }
- d->cameraFocusControl->setSupportedFocusMode(supportedModeFlag);
- if (!d->regionsOfInterestControl) {
- d->cameraFocusControl->setSupportedFocusPointMode(QSet<QCameraFocus::FocusPointMode>());
- return S_OK;
- }
- boolean isRegionsfocusSupported = false;
- hr = d->regionsOfInterestControl->get_AutoFocusSupported(&isRegionsfocusSupported);
- Q_ASSERT_SUCCEEDED(hr);
- UINT32 maxRegions;
- hr = d->regionsOfInterestControl->get_MaxRegions(&maxRegions);
- Q_ASSERT_SUCCEEDED(hr);
- if (!isRegionsfocusSupported || maxRegions == 0) {
- d->cameraFocusControl->setSupportedFocusPointMode(QSet<QCameraFocus::FocusPointMode>());
- return S_OK;
- }
- QSet<QCameraFocus::FocusPointMode> supportedFocusPointModes;
- supportedFocusPointModes << QCameraFocus::FocusPointCustom
- << QCameraFocus::FocusPointCenter
- << QCameraFocus::FocusPointAuto;
- d->cameraFocusControl->setSupportedFocusPointMode(supportedFocusPointModes);
- return S_OK;
-}
-
-bool QWinRTCameraControl::setFocus(QCameraFocus::FocusModes modes)
-{
- Q_D(QWinRTCameraControl);
- if (d->status == QCamera::UnloadedStatus)
- return false;
-
- bool result = false;
- HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([modes, &result, d, this]() {
- ComPtr<IFocusSettings> focusSettings;
- ComPtr<IInspectable> focusSettingsObject;
- HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Media_Devices_FocusSettings).Get(), &focusSettingsObject);
- Q_ASSERT_SUCCEEDED(hr);
- hr = focusSettingsObject.As(&focusSettings);
- Q_ASSERT_SUCCEEDED(hr);
- FocusMode mode;
- if (modes.testFlag(QCameraFocus::ContinuousFocus)) {
- mode = FocusMode_Continuous;
- } else if (modes.testFlag(QCameraFocus::AutoFocus)
- || modes.testFlag(QCameraFocus::MacroFocus)
- || modes.testFlag(QCameraFocus::InfinityFocus)) {
- // The Macro and infinity focus modes are only supported in auto focus mode on WinRT.
- // QML camera focus doesn't support combined focus flags settings. In the case of macro
- // and infinity Focus modes, the auto focus setting is applied.
- mode = FocusMode_Single;
- } else {
- emit error(QCamera::NotSupportedFeatureError, QStringLiteral("Unsupported camera focus modes."));
- result = false;
- return S_OK;
- }
- hr = focusSettings->put_Mode(mode);
- Q_ASSERT_SUCCEEDED(hr);
- AutoFocusRange range = AutoFocusRange_Normal;
- if (modes.testFlag(QCameraFocus::MacroFocus))
- range = AutoFocusRange_Macro;
- else if (modes.testFlag(QCameraFocus::InfinityFocus))
- range = AutoFocusRange_FullRange;
- hr = focusSettings->put_AutoFocusRange(range);
- Q_ASSERT_SUCCEEDED(hr);
- hr = focusSettings->put_WaitForFocus(true);
- Q_ASSERT_SUCCEEDED(hr);
- hr = focusSettings->put_DisableDriverFallback(false);
- Q_ASSERT_SUCCEEDED(hr);
-
- ComPtr<IFocusControl2> focusControl2;
- hr = d->focusControl.As(&focusControl2);
- Q_ASSERT_SUCCEEDED(hr);
- hr = focusControl2->Configure(focusSettings.Get());
- result = SUCCEEDED(hr);
- RETURN_OK_IF_FAILED("Failed to configure camera focus control");
- return S_OK;
- });
- Q_ASSERT_SUCCEEDED(hr);
- Q_UNUSED(hr); // Silence release build
- return result;
-}
-
-bool QWinRTCameraControl::setFocusPoint(const QPointF &focusPoint)
-{
- Q_D(QWinRTCameraControl);
- if (focusPoint.x() < double(FOCUS_RECT_POSITION_MIN)
- || focusPoint.x() > double(FOCUS_RECT_BOUNDARY)) {
- emit error(QCamera::CameraError, QStringLiteral("Focus horizontal location should be between 0.0 and 1.0."));
- return false;
- }
-
- if (focusPoint.y() < double(FOCUS_RECT_POSITION_MIN)
- || focusPoint.y() > double(FOCUS_RECT_BOUNDARY)) {
- emit error(QCamera::CameraError, QStringLiteral("Focus vertical location should be between 0.0 and 1.0."));
- return false;
- }
-
- ABI::Windows::Foundation::Rect rect;
- rect.X = qBound<float>(FOCUS_RECT_POSITION_MIN, float(focusPoint.x() - double(FOCUS_RECT_HALF_SIZE)), FOCUS_RECT_POSITION_MAX);
- rect.Y = qBound<float>(FOCUS_RECT_POSITION_MIN, float(focusPoint.y() - double(FOCUS_RECT_HALF_SIZE)), FOCUS_RECT_POSITION_MAX);
- rect.Width = (rect.X + FOCUS_RECT_SIZE) < FOCUS_RECT_BOUNDARY ? FOCUS_RECT_SIZE : FOCUS_RECT_BOUNDARY - rect.X;
- rect.Height = (rect.Y + FOCUS_RECT_SIZE) < FOCUS_RECT_BOUNDARY ? FOCUS_RECT_SIZE : FOCUS_RECT_BOUNDARY - rect.Y;
-
- ComPtr<IRegionOfInterest> regionOfInterest;
- ComPtr<IInspectable> regionOfInterestObject;
- HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Media_Devices_RegionOfInterest).Get(), &regionOfInterestObject);
- Q_ASSERT_SUCCEEDED(hr);
- hr = regionOfInterestObject.As(&regionOfInterest);
- Q_ASSERT_SUCCEEDED(hr);
- ComPtr<IRegionOfInterest2> regionOfInterest2;
- hr = regionOfInterestObject.As(&regionOfInterest2);
- Q_ASSERT_SUCCEEDED(hr);
- hr = regionOfInterest2->put_BoundsNormalized(true);
- Q_ASSERT_SUCCEEDED(hr);
- hr = regionOfInterest2->put_Weight(1);
- Q_ASSERT_SUCCEEDED(hr);
- hr = regionOfInterest2->put_Type(RegionOfInterestType_Unknown);
- Q_ASSERT_SUCCEEDED(hr);
- hr = regionOfInterest->put_AutoFocusEnabled(true);
- Q_ASSERT_SUCCEEDED(hr);
- hr = regionOfInterest->put_Bounds(rect);
- Q_ASSERT_SUCCEEDED(hr);
-
- ComPtr<WindowsRegionOfInterestIterable> regionOfInterestIterable = Make<WindowsRegionOfInterestIterable>(regionOfInterest);
- ComPtr<IAsyncAction> op;
- hr = d->regionsOfInterestControl->SetRegionsAsync(regionOfInterestIterable.Get(), &op);
- Q_ASSERT_SUCCEEDED(hr);
- return QWinRTFunctions::await(op) == S_OK;
-}
-
-bool QWinRTCameraControl::focus()
-{
- Q_D(QWinRTCameraControl);
- HRESULT hr;
- if (!d->focusControl)
- return false;
-
- QEventDispatcherWinRT::runOnXamlThread([&d, &hr]() {
- if (d->focusOperation) {
- ComPtr<IAsyncInfo> info;
- hr = d->focusOperation.As(&info);
- Q_ASSERT_SUCCEEDED(hr);
-
- AsyncStatus status = AsyncStatus::Completed;
- hr = info->get_Status(&status);
- Q_ASSERT_SUCCEEDED(hr);
- if (status == AsyncStatus::Started)
- return E_ASYNC_OPERATION_NOT_STARTED;
- }
-
- hr = d->focusControl->FocusAsync(&d->focusOperation);
- Q_ASSERT_SUCCEEDED(hr);
-
- const long errorCode = HRESULT_CODE(hr);
- if (errorCode == ERROR_OPERATION_IN_PROGRESS
- || errorCode == ERROR_WRITE_PROTECT) {
- return E_ASYNC_OPERATION_NOT_STARTED;
- }
- Q_ASSERT_SUCCEEDED(hr);
- return S_OK;
- });
-
- return hr == S_OK;
-}
-
-void QWinRTCameraControl::clearFocusPoint()
-{
- Q_D(QWinRTCameraControl);
- if (!d->focusControl)
- return;
- ComPtr<IAsyncAction> op;
- HRESULT hr = d->regionsOfInterestControl->ClearRegionsAsync(&op);
- Q_ASSERT_SUCCEEDED(hr);
- hr = QWinRTFunctions::await(op);
- Q_ASSERT_SUCCEEDED(hr);
-}
-
-bool QWinRTCameraControl::lockFocus()
-{
- Q_D(QWinRTCameraControl);
- if (!d->focusControl)
- return false;
-
- bool result = false;
- ComPtr<IAsyncAction> op;
- HRESULT hr;
- hr = QEventDispatcherWinRT::runOnXamlThread([d, &result, &op]() {
- ComPtr<IFocusControl2> focusControl2;
- HRESULT hr = d->focusControl.As(&focusControl2);
- Q_ASSERT_SUCCEEDED(hr);
- hr = focusControl2->LockAsync(&op);
- if (HRESULT_CODE(hr) == ERROR_WRITE_PROTECT)
- return S_OK;
- Q_ASSERT_SUCCEEDED(hr);
- result = true;
- return hr;
- });
- return result ? (QWinRTFunctions::await(op) == S_OK) : false;
-}
-
-bool QWinRTCameraControl::unlockFocus()
-{
- Q_D(QWinRTCameraControl);
- if (!d->focusControl)
- return false;
-
- bool result = false;
- ComPtr<IAsyncAction> op;
- HRESULT hr;
- hr = QEventDispatcherWinRT::runOnXamlThread([d, &result, &op]() {
- ComPtr<IFocusControl2> focusControl2;
- HRESULT hr = d->focusControl.As(&focusControl2);
- Q_ASSERT_SUCCEEDED(hr);
- hr = focusControl2->UnlockAsync(&op);
- if (HRESULT_CODE(hr) == ERROR_WRITE_PROTECT)
- return S_OK;
- Q_ASSERT_SUCCEEDED(hr);
- result = true;
- return hr;
- });
- return result ? (QWinRTFunctions::await(op) == S_OK) : false;
-}
-
-#else // !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
-
-HRESULT QWinRTCameraControl::initializeFocus()
-{
- Q_D(QWinRTCameraControl);
- d->cameraFocusControl->setSupportedFocusMode(0);
- d->cameraFocusControl->setSupportedFocusPointMode(QSet<QCameraFocus::FocusPointMode>());
- return S_OK;
-}
-
-bool QWinRTCameraControl::setFocus(QCameraFocus::FocusModes modes)
-{
- Q_UNUSED(modes)
- return false;
-}
-
-bool QWinRTCameraControl::setFocusPoint(const QPointF &focusPoint)
-{
- Q_UNUSED(focusPoint)
- return false;
-}
-
-bool QWinRTCameraControl::focus()
-{
- return false;
-}
-
-void QWinRTCameraControl::clearFocusPoint()
-{
-}
-
-bool QWinRTCameraControl::lockFocus()
-{
- return false;
-}
-
-bool QWinRTCameraControl::unlockFocus()
-{
- return false;
-}
-
-#endif // !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
-
-void QWinRTCameraControl::frameMapped()
-{
- Q_D(QWinRTCameraControl);
- ++d->framesMapped;
-}
-
-void QWinRTCameraControl::frameUnmapped()
-{
- Q_D(QWinRTCameraControl);
- --d->framesMapped;
- Q_ASSERT(d->framesMapped >= 0);
- if (!d->framesMapped && d->delayClose && d->delayClose->isRunning())
- d->delayClose->exit();
-}
-
-HRESULT QWinRTCameraControl::onCaptureFailed(IMediaCapture *, IMediaCaptureFailedEventArgs *args)
-{
- qCDebug(lcMMCamera) << __FUNCTION__ << args;
- HRESULT hr;
- UINT32 code;
- hr = args->get_Code(&code);
- RETURN_HR_IF_FAILED("Failed to get error code");
- HString message;
- args->get_Message(message.GetAddressOf());
- RETURN_HR_IF_FAILED("Failed to get error message");
- quint32 messageLength;
- const wchar_t *messageBuffer = message.GetRawBuffer(&messageLength);
- emit error(QCamera::CameraError, QString::fromWCharArray(messageBuffer, int(messageLength)));
- setState(QCamera::LoadedState);
- return S_OK;
-}
-
-HRESULT QWinRTCameraControl::onRecordLimitationExceeded(IMediaCapture *)
-{
- qCDebug(lcMMCamera) << __FUNCTION__;
- emit error(QCamera::CameraError, QStringLiteral("Recording limit exceeded."));
- setState(QCamera::LoadedState);
- return S_OK;
-}
-
-HRESULT QWinRTCameraControl::onInitializationCompleted(IAsyncAction *, AsyncStatus status)
-{
- qCDebug(lcMMCamera) << __FUNCTION__;
- Q_D(QWinRTCameraControl);
-
- if (status != Completed) {
- d->initializing = false;
- d->initialized = false;
- return S_OK;
- }
-
- ComPtr<IVideoDeviceController> videoDeviceController;
- HRESULT hr = d->capture->get_VideoDeviceController(&videoDeviceController);
- ComPtr<IAdvancedVideoCaptureDeviceController2> advancedVideoDeviceController;
- hr = videoDeviceController.As(&advancedVideoDeviceController);
- Q_ASSERT_SUCCEEDED(hr);
- hr = advancedVideoDeviceController->get_FocusControl(&d->focusControl);
- Q_ASSERT_SUCCEEDED(hr);
-
- d->cameraFlashControl->initialize(advancedVideoDeviceController);
-
- boolean isFocusSupported;
- hr = d->focusControl->get_Supported(&isFocusSupported);
- Q_ASSERT_SUCCEEDED(hr);
- if (isFocusSupported) {
- hr = advancedVideoDeviceController->get_RegionsOfInterestControl(&d->regionsOfInterestControl);
- if (FAILED(hr))
- qCDebug(lcMMCamera) << "Focus supported, but no control for regions of interest available";
- hr = initializeFocus();
- Q_ASSERT_SUCCEEDED(hr);
- }
-
- Q_ASSERT_SUCCEEDED(hr);
- ComPtr<IMediaDeviceController> deviceController;
- hr = videoDeviceController.As(&deviceController);
- Q_ASSERT_SUCCEEDED(hr);
-
- // Get preview stream properties.
- ComPtr<IVectorView<IMediaEncodingProperties *>> previewPropertiesList;
- QVector<QSize> previewResolutions;
- hr = getMediaStreamResolutions(deviceController.Get(),
- MediaStreamType_VideoPreview,
- &previewPropertiesList,
- &previewResolutions);
- RETURN_HR_IF_FAILED("Failed to find a suitable video format");
-
- MediaStreamType mediaStreamType =
- d->captureMode == QCamera::CaptureVideo ? MediaStreamType_VideoRecord : MediaStreamType_Photo;
-
- // Get capture stream properties.
- ComPtr<IVectorView<IMediaEncodingProperties *>> capturePropertiesList;
- QVector<QSize> captureResolutions;
- hr = getMediaStreamResolutions(deviceController.Get(),
- mediaStreamType,
- &capturePropertiesList,
- &captureResolutions);
- RETURN_HR_IF_FAILED("Failed to find a suitable video format");
-
- std::sort(captureResolutions.begin(), captureResolutions.end(), [](QSize size1, QSize size2) {
- return size1.width() * size1.height() < size2.width() * size2.height();
- });
-
- // Set capture resolutions.
- d->imageEncoderControl->setSupportedResolutionsList(captureResolutions.toList());
- const QSize captureResolution = d->imageEncoderControl->imageSettings().resolution();
- const quint32 captureResolutionIndex = quint32(captureResolutions.indexOf(captureResolution));
- ComPtr<IMediaEncodingProperties> captureProperties;
- hr = capturePropertiesList->GetAt(captureResolutionIndex, &captureProperties);
- Q_ASSERT_SUCCEEDED(hr);
- ComPtr<IAsyncAction> op;
- hr = deviceController->SetMediaStreamPropertiesAsync(mediaStreamType, captureProperties.Get(), &op);
- Q_ASSERT_SUCCEEDED(hr);
- hr = QWinRTFunctions::await(op);
- Q_ASSERT_SUCCEEDED(hr);
-
- // Set preview resolution.
- QSize maxSize;
- const float captureAspectRatio = float(captureResolution.width()) / captureResolution.height();
- for (const QSize &resolution : qAsConst(previewResolutions)) {
- const float aspectRatio = float(resolution.width()) / resolution.height();
- if ((qAbs(aspectRatio - captureAspectRatio) <= ASPECTRATIO_EPSILON)
- && (maxSize.width() * maxSize.height() < resolution.width() * resolution.height())) {
- maxSize = resolution;
- }
- }
-
- const QSize &viewfinderResolution = maxSize;
- const quint32 viewfinderResolutionIndex = quint32(previewResolutions.indexOf(viewfinderResolution));
- hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Media_MediaProperties_MediaEncodingProfile).Get(),
- &d->encodingProfile);
- Q_ASSERT_SUCCEEDED(hr);
- ComPtr<IMediaEncodingProperties> previewProperties;
- hr = previewPropertiesList->GetAt(viewfinderResolutionIndex, &previewProperties);
- Q_ASSERT_SUCCEEDED(hr);
- hr = deviceController->SetMediaStreamPropertiesAsync(MediaStreamType_VideoPreview, previewProperties.Get(), &op);
- Q_ASSERT_SUCCEEDED(hr);
- hr = QWinRTFunctions::await(op);
- Q_ASSERT_SUCCEEDED(hr);
- ComPtr<IVideoEncodingProperties> videoPreviewProperties;
- hr = previewProperties.As(&videoPreviewProperties);
- Q_ASSERT_SUCCEEDED(hr);
- hr = d->encodingProfile->put_Video(videoPreviewProperties.Get());
- Q_ASSERT_SUCCEEDED(hr);
-
- if (d->videoRenderer)
- d->videoRenderer->setSize(viewfinderResolution);
-
- if (!isFocusSupported) {
- d->cameraFocusControl->setSupportedFocusMode(0);
- d->cameraFocusControl->setSupportedFocusPointMode(QSet<QCameraFocus::FocusPointMode>());
- }
- d->cameraLocksControl->initialize();
-
- d->initializing = false;
- d->initialized = true;
- SetEvent(d->initializationCompleteEvent);
- return S_OK;
-}
-
-void QWinRTCameraControl::emitError(int errorCode, const QString &errorString)
-{
- qCDebug(lcMMCamera) << __FUNCTION__ << errorString << errorCode;
- emit error(errorCode, errorString);
-}
-
-QT_END_NAMESPACE