summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Knight <andrew.knight@digia.com>2014-08-29 16:59:09 +0300
committerAndrew Knight <andrew.knight@digia.com>2014-08-30 08:24:07 +0200
commit0c3438c9a12fbc607eada8f938cf0ad8fdea374d (patch)
treea7656d4bcaa8a9625955061ae2f3e7147867885a
parent80ba1d635dc37963b4c90d776c46774b0349c4f8 (diff)
winrt: Add camera service
This adds a basic camera service with viewfinder (video renderer based), still image capture, and device selection support. Runtime apps must set the "webcam" and "microphone" device capabilities in order to access the hardware. This can be done by adding the following to the .pro file: WINRT_MANIFEST.capabilites_device += webcam microphone [ChangeLog] Enabled basic camera support in the winrt backend. Change-Id: If4f963ef645d93c757ae23aec9a9c8aae122324f Reviewed-by: Yoann Lopes <yoann.lopes@digia.com>
-rw-r--r--src/plugins/winrt/qwinrtcameracontrol.cpp783
-rw-r--r--src/plugins/winrt/qwinrtcameracontrol.h111
-rw-r--r--src/plugins/winrt/qwinrtcameraimagecapturecontrol.cpp280
-rw-r--r--src/plugins/winrt/qwinrtcameraimagecapturecontrol.h86
-rw-r--r--src/plugins/winrt/qwinrtcamerainfocontrol.cpp60
-rw-r--r--src/plugins/winrt/qwinrtcamerainfocontrol.h61
-rw-r--r--src/plugins/winrt/qwinrtcameraservice.cpp104
-rw-r--r--src/plugins/winrt/qwinrtcameraservice.h66
-rw-r--r--src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp204
-rw-r--r--src/plugins/winrt/qwinrtcameravideorenderercontrol.h74
-rw-r--r--src/plugins/winrt/qwinrtserviceplugin.cpp39
-rw-r--r--src/plugins/winrt/qwinrtserviceplugin.h14
-rw-r--r--src/plugins/winrt/qwinrtvideodeviceselectorcontrol.cpp383
-rw-r--r--src/plugins/winrt/qwinrtvideodeviceselectorcontrol.h94
-rw-r--r--src/plugins/winrt/winrt.json2
-rw-r--r--src/plugins/winrt/winrt.pro18
16 files changed, 2375 insertions, 4 deletions
diff --git a/src/plugins/winrt/qwinrtcameracontrol.cpp b/src/plugins/winrt/qwinrtcameracontrol.cpp
new file mode 100644
index 000000000..619e97315
--- /dev/null
+++ b/src/plugins/winrt/qwinrtcameracontrol.cpp
@@ -0,0 +1,783 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 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 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwinrtcameracontrol.h"
+#include "qwinrtcameravideorenderercontrol.h"
+#include "qwinrtvideodeviceselectorcontrol.h"
+#include "qwinrtcameraimagecapturecontrol.h"
+
+#include <QtCore/qfunctions_winrt.h>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QPointer>
+
+#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>
+
+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_USE_NAMESPACE
+
+#define RETURN_VOID_AND_EMIT_ERROR(msg) \
+ if (FAILED(hr)) { \
+ emit error(QCamera::CameraError, qt_error_string(hr)); \
+ RETURN_VOID_IF_FAILED(msg); \
+ }
+
+class CriticalSectionLocker
+{
+public:
+ CriticalSectionLocker(CRITICAL_SECTION *section)
+ : m_section(section)
+ {
+ EnterCriticalSection(m_section);
+ }
+ ~CriticalSectionLocker()
+ {
+ LeaveCriticalSection(m_section);
+ }
+private:
+ CRITICAL_SECTION *m_section;
+};
+
+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);
+
+ InitializeCriticalSectionEx(&m_mutex, 0, 0);
+
+ HRESULT hr;
+ hr = MFCreateEventQueue(&m_eventQueue);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = MFAllocateSerialWorkQueue(MFASYNC_CALLBACK_QUEUE_STANDARD, &m_workQueueId);
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+
+ ~MediaStream()
+ {
+ CriticalSectionLocker locker(&m_mutex);
+ m_eventQueue->Shutdown();
+ DeleteCriticalSection(&m_mutex);
+ }
+
+ HRESULT RequestSample()
+ {
+ if (m_pendingSamples.load() < 3) {
+ m_pendingSamples.ref();
+ return QueueEvent(MEStreamSinkRequestSample, GUID_NULL, S_OK, Q_NULLPTR);
+ }
+ return S_OK;
+ }
+
+ HRESULT __stdcall GetEvent(DWORD flags, IMFMediaEvent **event) Q_DECL_OVERRIDE
+ {
+ EnterCriticalSection(&m_mutex);
+ // Create an extra reference to avoid deadlock
+ ComPtr<IMFMediaEventQueue> eventQueue = m_eventQueue;
+ LeaveCriticalSection(&m_mutex);
+
+ return eventQueue->GetEvent(flags, event);
+ }
+
+ HRESULT __stdcall BeginGetEvent(IMFAsyncCallback *callback, IUnknown *state) Q_DECL_OVERRIDE
+ {
+ CriticalSectionLocker locker(&m_mutex);
+ HRESULT hr = m_eventQueue->BeginGetEvent(callback, state);
+ return hr;
+ }
+
+ HRESULT __stdcall EndGetEvent(IMFAsyncResult *result, IMFMediaEvent **event) Q_DECL_OVERRIDE
+ {
+ CriticalSectionLocker locker(&m_mutex);
+ return m_eventQueue->EndGetEvent(result, event);
+ }
+
+ HRESULT __stdcall QueueEvent(MediaEventType eventType, const GUID &extendedType, HRESULT status, const PROPVARIANT *value) Q_DECL_OVERRIDE
+ {
+ CriticalSectionLocker locker(&m_mutex);
+ return m_eventQueue->QueueEventParamVar(eventType, extendedType, status, value);
+ }
+
+ HRESULT __stdcall GetMediaSink(IMFMediaSink **mediaSink) Q_DECL_OVERRIDE
+ {
+ *mediaSink = m_sink;
+ return S_OK;
+ }
+
+ HRESULT __stdcall GetIdentifier(DWORD *identifier) Q_DECL_OVERRIDE
+ {
+ *identifier = 0;
+ return S_OK;
+ }
+
+ HRESULT __stdcall GetMediaTypeHandler(IMFMediaTypeHandler **handler) Q_DECL_OVERRIDE
+ {
+ return QueryInterface(IID_PPV_ARGS(handler));
+ }
+
+ HRESULT __stdcall ProcessSample(IMFSample *sample) Q_DECL_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) Q_DECL_OVERRIDE
+ {
+ Q_UNUSED(type);
+ Q_UNUSED(value);
+ QueueEvent(MEStreamSinkMarker, GUID_NULL, S_OK, context);
+ return S_OK;
+ }
+
+ HRESULT __stdcall Flush() Q_DECL_OVERRIDE
+ {
+ m_videoRenderer->discardBuffers();
+ m_pendingSamples.store(0);
+ return S_OK;
+ }
+
+ HRESULT __stdcall IsMediaTypeSupported(IMFMediaType *type, IMFMediaType **) Q_DECL_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) Q_DECL_OVERRIDE
+ {
+ *typeCount = 1;
+ return S_OK;
+ }
+
+ HRESULT __stdcall GetMediaTypeByIndex(DWORD index, IMFMediaType **type) Q_DECL_OVERRIDE
+ {
+ if (index == 0)
+ return m_type.CopyTo(type);
+ return E_BOUNDS;
+ }
+
+ HRESULT __stdcall SetCurrentMediaType(IMFMediaType *type) Q_DECL_OVERRIDE
+ {
+ if (FAILED(IsMediaTypeSupported(type, Q_NULLPTR)))
+ return MF_E_INVALIDREQUEST;
+
+ m_type = type;
+ return S_OK;
+ }
+
+ HRESULT __stdcall GetCurrentMediaType(IMFMediaType **type) Q_DECL_OVERRIDE
+ {
+ return m_type.CopyTo(type);
+ }
+
+ HRESULT __stdcall GetMajorType(GUID *majorType) Q_DECL_OVERRIDE
+ {
+ return m_type->GetMajorType(majorType);
+ }
+
+private:
+ CRITICAL_SECTION 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()
+ {
+ }
+
+ HRESULT RequestSample()
+ {
+ return m_stream->RequestSample();
+ }
+
+ HRESULT __stdcall SetProperties(Collections::IPropertySet *configuration) Q_DECL_OVERRIDE
+ {
+ Q_UNUSED(configuration);
+ return E_NOTIMPL;
+ }
+
+ HRESULT __stdcall GetCharacteristics(DWORD *characteristics) Q_DECL_OVERRIDE
+ {
+ *characteristics = MEDIASINK_FIXED_STREAMS | MEDIASINK_RATELESS;
+ return S_OK;
+ }
+
+ HRESULT __stdcall AddStreamSink(DWORD streamSinkIdentifier, IMFMediaType *mediaType, IMFStreamSink **streamSink) Q_DECL_OVERRIDE
+ {
+ Q_UNUSED(streamSinkIdentifier);
+ Q_UNUSED(mediaType);
+ Q_UNUSED(streamSink);
+ return E_NOTIMPL;
+ }
+
+ HRESULT __stdcall RemoveStreamSink(DWORD streamSinkIdentifier) Q_DECL_OVERRIDE
+ {
+ Q_UNUSED(streamSinkIdentifier);
+ return E_NOTIMPL;
+ }
+
+ HRESULT __stdcall GetStreamSinkCount(DWORD *streamSinkCount) Q_DECL_OVERRIDE
+ {
+ *streamSinkCount = 1;
+ return S_OK;
+ }
+
+ HRESULT __stdcall GetStreamSinkByIndex(DWORD index, IMFStreamSink **streamSink) Q_DECL_OVERRIDE
+ {
+ if (index == 0)
+ return m_stream.CopyTo(streamSink);
+ return MF_E_INVALIDINDEX;
+ }
+
+ HRESULT __stdcall GetStreamSinkById(DWORD streamSinkIdentifier, IMFStreamSink **streamSink) Q_DECL_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) Q_DECL_OVERRIDE
+ {
+ HRESULT hr = S_OK;
+ m_presentationClock = presentationClock;
+ if (m_presentationClock)
+ hr = m_presentationClock->AddClockStateSink(this);
+ return hr;
+ }
+
+ HRESULT __stdcall GetPresentationClock(IMFPresentationClock **presentationClock) Q_DECL_OVERRIDE
+ {
+ return m_presentationClock.CopyTo(presentationClock);
+ }
+
+ HRESULT __stdcall Shutdown() Q_DECL_OVERRIDE
+ {
+ m_stream->Flush();
+ m_videoRenderer->setActive(false);
+ return m_presentationClock->Stop();
+ }
+
+ HRESULT __stdcall OnClockStart(MFTIME systemTime, LONGLONG clockStartOffset) Q_DECL_OVERRIDE
+ {
+ Q_UNUSED(systemTime);
+ Q_UNUSED(clockStartOffset);
+
+ m_videoRenderer->setActive(true);
+
+ return S_OK;
+ }
+
+ HRESULT __stdcall OnClockStop(MFTIME systemTime) Q_DECL_OVERRIDE
+ {
+ Q_UNUSED(systemTime);
+
+ m_videoRenderer->setActive(false);
+
+ return m_stream->QueueEvent(MEStreamSinkStopped, GUID_NULL, S_OK, Q_NULLPTR);
+ }
+
+ HRESULT __stdcall OnClockPause(MFTIME systemTime) Q_DECL_OVERRIDE
+ {
+ Q_UNUSED(systemTime);
+
+ m_videoRenderer->setActive(false);
+
+ return m_stream->QueueEvent(MEStreamSinkPaused, GUID_NULL, S_OK, Q_NULLPTR);
+ }
+
+ HRESULT __stdcall OnClockRestart(MFTIME systemTime) Q_DECL_OVERRIDE
+ {
+ Q_UNUSED(systemTime);
+
+ m_videoRenderer->setActive(true);
+
+ return m_stream->QueueEvent(MEStreamSinkStarted, GUID_NULL, S_OK, Q_NULLPTR);
+ }
+
+ HRESULT __stdcall OnClockSetRate(MFTIME systemTime, float rate) Q_DECL_OVERRIDE
+ {
+ Q_UNUSED(systemTime);
+ Q_UNUSED(rate);
+ return E_NOTIMPL;
+ }
+
+private:
+ 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;
+
+ QSize size;
+ QPointer<QWinRTCameraVideoRendererControl> videoRenderer;
+ QPointer<QWinRTVideoDeviceSelectorControl> videoDeviceSelector;
+ QPointer<QWinRTCameraImageCaptureControl> imageCaptureControl;
+};
+
+QWinRTCameraControl::QWinRTCameraControl(QObject *parent)
+ : QCameraControl(parent), d_ptr(new QWinRTCameraControlPrivate)
+{
+ Q_D(QWinRTCameraControl);
+
+ d->state = QCamera::UnloadedState;
+ d->status = QCamera::UnloadedStatus;
+ d->captureMode = QCamera::CaptureStillImage;
+ d->captureFailedCookie.value = 0;
+ d->recordLimitationCookie.value = 0;
+ d->videoRenderer = new QWinRTCameraVideoRendererControl(d->size, this);
+ connect(d->videoRenderer, &QWinRTCameraVideoRendererControl::bufferRequested,
+ this, &QWinRTCameraControl::onBufferRequested);
+ d->videoDeviceSelector = new QWinRTVideoDeviceSelectorControl(this);
+ d->imageCaptureControl = new QWinRTCameraImageCaptureControl(this);
+}
+
+QWinRTCameraControl::~QWinRTCameraControl()
+{
+ setState(QCamera::UnloadedState);
+}
+
+QCamera::State QWinRTCameraControl::state() const
+{
+ Q_D(const QWinRTCameraControl);
+ return d->state;
+}
+
+void QWinRTCameraControl::setState(QCamera::State 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) {
+ hr = initialize();
+ RETURN_VOID_AND_EMIT_ERROR("Failed to initialize media capture");
+ }
+ Q_ASSERT(d->state == QCamera::LoadedState);
+
+ d->mediaSink = Make<MediaSink>(d->encodingProfile.Get(), d->videoRenderer);
+ ComPtr<IAsyncAction> op;
+ hr = d->capturePreview->StartPreviewToCustomSinkAsync(d->encodingProfile.Get(), d->mediaSink.Get(), &op);
+ RETURN_VOID_AND_EMIT_ERROR("Failed to initiate capture");
+ if (d->status != QCamera::StartingStatus) {
+ d->status = QCamera::StartingStatus;
+ emit statusChanged(d->status);
+ }
+
+ hr = 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;
+ }
+
+ d->state = QCamera::ActiveState;
+ emit stateChanged(d->state);
+ d->status = QCamera::ActiveStatus;
+ emit statusChanged(d->status);
+ break;
+ }
+ case QCamera::LoadedState: {
+ // If moving from unloaded, initialize the camera
+ if (d->state == QCamera::UnloadedState) {
+ hr = initialize();
+ RETURN_VOID_AND_EMIT_ERROR("Failed to initialize media capture");
+ }
+ // fall through
+ }
+ case QCamera::UnloadedState: {
+ // Stop the camera if it is running (transition to LoadedState)
+ if (d->status == QCamera::ActiveStatus) {
+ ComPtr<IAsyncAction> op;
+ hr = d->capturePreview->StopPreviewAsync(&op);
+ 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 = QWinRTFunctions::await(op); // Synchronize unloading
+ if (FAILED(hr))
+ emit error(QCamera::InvalidRequestError, qt_error_string(hr));
+
+ d->mediaSink->Shutdown();
+ d->mediaSink.Reset();
+
+ 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);
+ }
+
+ 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_VOID_AND_EMIT_ERROR("Failed to close the capture manger");
+ d->capture.Reset();
+ 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);
+ }
+ }
+ 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)
+{
+ 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;
+}
+
+IMediaCapture *QWinRTCameraControl::handle() const
+{
+ Q_D(const QWinRTCameraControl);
+ return d->capture.Get();
+}
+
+QSize QWinRTCameraControl::imageSize() const
+{
+ Q_D(const QWinRTCameraControl);
+ return d->size;
+}
+
+void QWinRTCameraControl::onBufferRequested()
+{
+ Q_D(QWinRTCameraControl);
+
+ if (d->mediaSink)
+ d->mediaSink->RequestSample();
+}
+
+HRESULT QWinRTCameraControl::initialize()
+{
+ Q_D(QWinRTCameraControl);
+
+ if (d->status != QCamera::LoadingStatus) {
+ d->status = QCamera::LoadingStatus;
+ emit statusChanged(d->status);
+ }
+
+ 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;
+ }
+
+ 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()), 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 = QWinRTFunctions::await(op, QWinRTFunctions::ProcessThreadEvents);
+ if (hr == E_ACCESSDENIED) {
+ qWarning("Access denied when initializing the media capture manager. "
+ "Check your manifest settings for microphone and webcam access.");
+ }
+ RETURN_HR_IF_FAILED("Failed to initialize media capture manager");
+
+ ComPtr<IVideoDeviceController> videoDeviceController;
+ hr = d->capture->get_VideoDeviceController(&videoDeviceController);
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<IMediaDeviceController> deviceController;
+ hr = videoDeviceController.As(&deviceController);
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<IVectorView<IMediaEncodingProperties *>> encodingPropertiesList;
+ hr = deviceController->GetAvailableMediaStreamProperties(MediaStreamType_Photo, &encodingPropertiesList);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ d->size = QSize();
+ ComPtr<IVideoEncodingProperties> videoEncodingProperties;
+ quint32 encodingPropertiesListSize;
+ hr = encodingPropertiesList->get_Size(&encodingPropertiesListSize);
+ Q_ASSERT_SUCCEEDED(hr);
+ for (quint32 i = 0; i < encodingPropertiesListSize; ++i) {
+ ComPtr<IMediaEncodingProperties> properties;
+ hr = encodingPropertiesList->GetAt(i, &properties);
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<IVideoEncodingProperties> videoProperties;
+ hr = properties.As(&videoEncodingProperties);
+ Q_ASSERT_SUCCEEDED(hr);
+ UINT32 width, height;
+ hr = videoEncodingProperties->get_Width(&width);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = videoEncodingProperties->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 (!videoEncodingProperties || d->size.isEmpty()) {
+ hr = MF_E_INVALID_FORMAT;
+ RETURN_HR_IF_FAILED("Failed to find a suitable video format");
+ }
+
+ hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Media_MediaProperties_MediaEncodingProfile).Get(),
+ &d->encodingProfile);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->encodingProfile->put_Video(videoEncodingProperties.Get());
+ Q_ASSERT_SUCCEEDED(hr);
+ if (d->videoRenderer)
+ d->videoRenderer->setSize(d->size);
+
+ if (SUCCEEDED(hr) && d->state != QCamera::LoadedState) {
+ d->state = QCamera::LoadedState;
+ emit stateChanged(d->state);
+ }
+ if (SUCCEEDED(hr) && d->status != QCamera::LoadedStatus) {
+ d->status = QCamera::LoadedStatus;
+ emit statusChanged(d->status);
+ }
+ return hr;
+}
+
+HRESULT QWinRTCameraControl::onCaptureFailed(IMediaCapture *, IMediaCaptureFailedEventArgs *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, messageLength));
+ setState(QCamera::LoadedState);
+ return S_OK;
+}
+
+HRESULT QWinRTCameraControl::onRecordLimitationExceeded(IMediaCapture *)
+{
+ emit error(QCamera::CameraError, QStringLiteral("Recording limit exceeded."));
+ setState(QCamera::LoadedState);
+ return S_OK;
+}
diff --git a/src/plugins/winrt/qwinrtcameracontrol.h b/src/plugins/winrt/qwinrtcameracontrol.h
new file mode 100644
index 000000000..e75f7e476
--- /dev/null
+++ b/src/plugins/winrt/qwinrtcameracontrol.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 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 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTCAMERACONTROL_H
+#define QWINRTCAMERACONTROL_H
+
+#include <QtMultimedia/QCameraControl>
+#include <QtCore/qt_windows.h>
+
+namespace ABI {
+ namespace Windows {
+ namespace Media {
+ namespace Capture {
+ struct IMediaCapture;
+ struct IMediaCaptureFailedEventArgs;
+ }
+ }
+ namespace Foundation {
+ struct IAsyncAction;
+ enum class AsyncStatus;
+ }
+ }
+}
+
+QT_BEGIN_NAMESPACE
+
+class QVideoRendererControl;
+class QVideoDeviceSelectorControl;
+class QCameraImageCaptureControl;
+
+class QWinRTCameraControlPrivate;
+class QWinRTCameraControl : public QCameraControl
+{
+ Q_OBJECT
+public:
+ explicit QWinRTCameraControl(QObject *parent = 0);
+ ~QWinRTCameraControl();
+
+ QCamera::State state() const Q_DECL_OVERRIDE;
+ void setState(QCamera::State state) Q_DECL_OVERRIDE;
+
+ QCamera::Status status() const Q_DECL_OVERRIDE;
+
+ QCamera::CaptureModes captureMode() const Q_DECL_OVERRIDE;
+ void setCaptureMode(QCamera::CaptureModes mode) Q_DECL_OVERRIDE;
+ bool isCaptureModeSupported(QCamera::CaptureModes mode) const Q_DECL_OVERRIDE;
+
+ bool canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const Q_DECL_OVERRIDE;
+
+ QVideoRendererControl *videoRenderer() const;
+ QVideoDeviceSelectorControl *videoDeviceSelector() const;
+ QCameraImageCaptureControl *imageCaptureControl() const;
+
+ ABI::Windows::Media::Capture::IMediaCapture *handle() const;
+ QSize imageSize() const;
+
+private slots:
+ void onBufferRequested();
+
+private:
+ HRESULT enumerateDevices();
+ HRESULT initialize();
+ HRESULT onCaptureFailed(ABI::Windows::Media::Capture::IMediaCapture *,
+ ABI::Windows::Media::Capture::IMediaCaptureFailedEventArgs *);
+ HRESULT onRecordLimitationExceeded(ABI::Windows::Media::Capture::IMediaCapture *);
+
+ QScopedPointer<QWinRTCameraControlPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QWinRTCameraControl)
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINRTCAMERACONTROL_H
diff --git a/src/plugins/winrt/qwinrtcameraimagecapturecontrol.cpp b/src/plugins/winrt/qwinrtcameraimagecapturecontrol.cpp
new file mode 100644
index 000000000..f5151c619
--- /dev/null
+++ b/src/plugins/winrt/qwinrtcameraimagecapturecontrol.cpp
@@ -0,0 +1,280 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 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 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwinrtcameraimagecapturecontrol.h"
+#include "qwinrtcameracontrol.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 <QtMultimedia/private/qmediastoragelocation_p.h>
+
+#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_USE_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;
+};
+
+class QWinRTCameraImageCaptureControlPrivate
+{
+public:
+ QPointer<QWinRTCameraControl> cameraControl;
+ QHash<IAsyncAction *, CaptureRequest> requests;
+ quint16 currentCaptureId;
+ QMediaStorageLocation location;
+
+ void onCameraStateChanged()
+ {
+
+ }
+};
+
+QWinRTCameraImageCaptureControl::QWinRTCameraImageCaptureControl(QWinRTCameraControl *parent)
+ : QCameraImageCaptureControl(parent), d_ptr(new QWinRTCameraImageCaptureControlPrivate)
+{
+ Q_D(QWinRTCameraImageCaptureControl);
+
+ d->cameraControl = parent;
+ connect(d->cameraControl, &QCameraControl::stateChanged,
+ this, &QWinRTCameraImageCaptureControl::readyForCaptureChanged);
+ d->currentCaptureId = 0;
+}
+
+bool QWinRTCameraImageCaptureControl::isReadyForCapture() const
+{
+ Q_D(const QWinRTCameraImageCaptureControl);
+ return d->cameraControl->state() == QCamera::ActiveState;
+}
+
+QCameraImageCapture::DriveMode QWinRTCameraImageCaptureControl::driveMode() const
+{
+ return QCameraImageCapture::SingleImageCapture;
+}
+
+void QWinRTCameraImageCaptureControl::setDriveMode(QCameraImageCapture::DriveMode mode)
+{
+ Q_UNUSED(mode);
+}
+
+int QWinRTCameraImageCaptureControl::capture(const QString &fileName)
+{
+ Q_D(QWinRTCameraImageCaptureControl);
+
+ ++d->currentCaptureId;
+ 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())
+ };
+
+ 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 = d->cameraControl->imageSize();
+ hr = request.imageFormat->put_Width(imageSize.width());
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = request.imageFormat->put_Height(imageSize.height());
+ Q_ASSERT_SUCCEEDED(hr);
+
+ hr = capture->CapturePhotoToStreamAsync(request.imageFormat.Get(), request.stream.Get(), &request.op);
+ Q_ASSERT_SUCCEEDED(hr);
+ d->requests.insert(request.op.Get(), request);
+
+ hr = request.op->put_Completed(Callback<IAsyncActionCompletedHandler>(
+ this, &QWinRTCameraImageCaptureControl::onCaptureCompleted).Get());
+ Q_ASSERT_SUCCEEDED(hr);
+
+ return request.id;
+}
+
+void QWinRTCameraImageCaptureControl::cancelCapture()
+{
+ 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);
+ }
+}
+
+HRESULT QWinRTCameraImageCaptureControl::onCaptureCompleted(IAsyncAction *asyncInfo, AsyncStatus status)
+{
+ Q_D(QWinRTCameraImageCaptureControl);
+
+ if (status == Canceled || !d->requests.contains(asyncInfo))
+ return S_OK;
+
+ CaptureRequest request = d->requests.take(asyncInfo);
+
+ 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, pixelWidth, pixelHeight, QImage::Format_RGBA8888,
+ reinterpret_cast<QImageCleanupFunction>(&CoTaskMemFree), pixelData);
+ emit imageCaptured(request.id, image);
+ if (image.save(request.fileName))
+ emit imageSaved(request.id, request.fileName);
+ else
+ emit error(request.id, QCameraImageCapture::ResourceError, tr("Image saving failed"));
+
+ return S_OK;
+}
diff --git a/src/plugins/winrt/qwinrtcameraimagecapturecontrol.h b/src/plugins/winrt/qwinrtcameraimagecapturecontrol.h
new file mode 100644
index 000000000..5150e4d3a
--- /dev/null
+++ b/src/plugins/winrt/qwinrtcameraimagecapturecontrol.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 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 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTCAMERAIMAGECAPTURECONTROL_H
+#define QWINRTCAMERAIMAGECAPTURECONTROL_H
+
+#include <QtMultimedia/QCameraImageCaptureControl>
+#include <QtCore/qt_windows.h>
+
+namespace ABI {
+ namespace Windows {
+ namespace Foundation {
+ struct IAsyncAction;
+ enum class AsyncStatus;
+ }
+ }
+}
+
+QT_BEGIN_NAMESPACE
+
+class QWinRTCameraControl;
+
+class QWinRTCameraImageCaptureControlPrivate;
+class QWinRTCameraImageCaptureControl : public QCameraImageCaptureControl
+{
+ Q_OBJECT
+public:
+ explicit QWinRTCameraImageCaptureControl(QWinRTCameraControl *parent);
+
+ bool isReadyForCapture() const Q_DECL_OVERRIDE;
+
+ QCameraImageCapture::DriveMode driveMode() const Q_DECL_OVERRIDE;
+ void setDriveMode(QCameraImageCapture::DriveMode mode) Q_DECL_OVERRIDE;
+
+ int capture(const QString &fileName) Q_DECL_OVERRIDE;
+ void cancelCapture() Q_DECL_OVERRIDE;
+
+private:
+ HRESULT onCaptureCompleted(ABI::Windows::Foundation::IAsyncAction *,
+ ABI::Windows::Foundation::AsyncStatus);
+
+ QScopedPointer<QWinRTCameraImageCaptureControlPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QWinRTCameraImageCaptureControl)
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINRTCAMERAIMAGECAPTURECONTROL_H
diff --git a/src/plugins/winrt/qwinrtcamerainfocontrol.cpp b/src/plugins/winrt/qwinrtcamerainfocontrol.cpp
new file mode 100644
index 000000000..c16b83be8
--- /dev/null
+++ b/src/plugins/winrt/qwinrtcamerainfocontrol.cpp
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 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 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwinrtcamerainfocontrol.h"
+#include "qwinrtvideodeviceselectorcontrol.h"
+
+QT_USE_NAMESPACE
+
+QWinRTCameraInfoControl::QWinRTCameraInfoControl(QObject *parent)
+ : QCameraInfoControl(parent)
+{
+}
+
+QCamera::Position QWinRTCameraInfoControl::cameraPosition(const QString &deviceName) const
+{
+ return QWinRTVideoDeviceSelectorControl::cameraPosition(deviceName);
+}
+
+int QWinRTCameraInfoControl::cameraOrientation(const QString &deviceName) const
+{
+ return QWinRTVideoDeviceSelectorControl::cameraOrientation(deviceName);
+}
diff --git a/src/plugins/winrt/qwinrtcamerainfocontrol.h b/src/plugins/winrt/qwinrtcamerainfocontrol.h
new file mode 100644
index 000000000..bf430f038
--- /dev/null
+++ b/src/plugins/winrt/qwinrtcamerainfocontrol.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 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 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTCAMERAINFOCONTROL_H
+#define QWINRTCAMERAINFOCONTROL_H
+
+#include <QtMultimedia/QCameraInfoControl>
+
+QT_BEGIN_NAMESPACE
+
+class QWinRTCameraInfoControl : public QCameraInfoControl
+{
+ Q_OBJECT
+public:
+ explicit QWinRTCameraInfoControl(QObject *parent = 0);
+
+ QCamera::Position cameraPosition(const QString &deviceName) const Q_DECL_OVERRIDE;
+ int cameraOrientation(const QString &deviceName) const Q_DECL_OVERRIDE;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINRTCAMERAINFOCONTROL_H
diff --git a/src/plugins/winrt/qwinrtcameraservice.cpp b/src/plugins/winrt/qwinrtcameraservice.cpp
new file mode 100644
index 000000000..239a1e883
--- /dev/null
+++ b/src/plugins/winrt/qwinrtcameraservice.cpp
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 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 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwinrtcameraservice.h"
+#include "qwinrtcameracontrol.h"
+#include "qwinrtcamerainfocontrol.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/qfunctions_winrt.h>
+#include <QtCore/QPointer>
+#include <QtMultimedia/QCameraImageCaptureControl>
+#include <QtMultimedia/QVideoRendererControl>
+#include <QtMultimedia/QVideoDeviceSelectorControl>
+
+QT_USE_NAMESPACE
+
+class QWinRTCameraServicePrivate
+{
+public:
+ QPointer<QWinRTCameraControl> cameraControl;
+ QPointer<QWinRTCameraInfoControl> cameraInfoControl;
+};
+
+QWinRTCameraService::QWinRTCameraService(QObject *parent)
+ : QMediaService(parent), d_ptr(new QWinRTCameraServicePrivate)
+{
+}
+
+QMediaControl *QWinRTCameraService::requestControl(const char *name)
+{
+ Q_D(QWinRTCameraService);
+
+ if (qstrcmp(name, QCameraControl_iid) == 0) {
+ if (!d->cameraControl)
+ d->cameraControl = new QWinRTCameraControl(this);
+ return d->cameraControl;
+ }
+
+ if (qstrcmp(name, QVideoRendererControl_iid) == 0) {
+ if (d->cameraControl)
+ return d->cameraControl->videoRenderer();
+ }
+
+ if (qstrcmp(name, QVideoDeviceSelectorControl_iid) == 0) {
+ if (d->cameraControl)
+ return d->cameraControl->videoDeviceSelector();
+ }
+
+ if (qstrcmp(name, QCameraInfoControl_iid) == 0) {
+ if (!d->cameraInfoControl)
+ d->cameraInfoControl = new QWinRTCameraInfoControl(this);
+ return d->cameraInfoControl;
+ }
+
+ if (qstrcmp(name, QCameraImageCaptureControl_iid) == 0) {
+ if (d->cameraControl)
+ return d->cameraControl->imageCaptureControl();
+ }
+
+ return Q_NULLPTR;
+}
+
+void QWinRTCameraService::releaseControl(QMediaControl *control)
+{
+ Q_UNUSED(control);
+}
diff --git a/src/plugins/winrt/qwinrtcameraservice.h b/src/plugins/winrt/qwinrtcameraservice.h
new file mode 100644
index 000000000..19e93a818
--- /dev/null
+++ b/src/plugins/winrt/qwinrtcameraservice.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 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 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTCAMERASERVICE_H
+#define QWINRTCAMERASERVICE_H
+
+#include <QtMultimedia/QMediaService>
+
+QT_BEGIN_NAMESPACE
+
+class QWinRTCameraServicePrivate;
+class QWinRTCameraService : public QMediaService
+{
+ Q_OBJECT
+public:
+ explicit QWinRTCameraService(QObject *parent = 0);
+
+ QMediaControl *requestControl(const char *name) Q_DECL_OVERRIDE;
+ void releaseControl(QMediaControl *control) Q_DECL_OVERRIDE;
+
+private:
+ QScopedPointer<QWinRTCameraServicePrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QWinRTCameraService)
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINRTCAMERASERVICE_H
diff --git a/src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp b/src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp
new file mode 100644
index 000000000..e7e75da27
--- /dev/null
+++ b/src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp
@@ -0,0 +1,204 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 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 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwinrtcameravideorenderercontrol.h"
+
+#include <QtCore/qfunctions_winrt.h>
+#include <QtCore/QSize>
+#include <QtCore/QVector>
+
+#include <d3d11.h>
+#include <mfapi.h>
+#include <wrl.h>
+using namespace Microsoft::WRL;
+
+QT_USE_NAMESPACE
+
+class D3DVideoBlitter
+{
+public:
+ D3DVideoBlitter(ID3D11Device *device, ID3D11Texture2D *target)
+ : m_d3dDevice(device), m_target(target)
+ {
+ HRESULT hr;
+ ComPtr<IDXGIResource> targetResource;
+ hr = target->QueryInterface(IID_PPV_ARGS(&targetResource));
+ Q_ASSERT_SUCCEEDED(hr);
+ HANDLE sharedHandle;
+ hr = targetResource->GetSharedHandle(&sharedHandle);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = m_d3dDevice->OpenSharedResource(sharedHandle, IID_PPV_ARGS(&m_targetTexture));
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = m_d3dDevice.As(&m_videoDevice);
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+
+ ID3D11Device *device() const
+ {
+ return m_d3dDevice.Get();
+ }
+
+ ID3D11Texture2D *target() const
+ {
+ return m_target;
+ }
+
+ void blit(ID3D11Texture2D *texture)
+ {
+ HRESULT hr;
+ D3D11_TEXTURE2D_DESC desc;
+ texture->GetDesc(&desc);
+ if (!m_videoEnumerator) {
+ D3D11_VIDEO_PROCESSOR_CONTENT_DESC videoProcessorDesc = {
+ D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE,
+ { 0 }, desc.Width, desc.Height,
+ { 0 }, desc.Width, desc.Height,
+ D3D11_VIDEO_USAGE_PLAYBACK_NORMAL
+ };
+ hr = m_videoDevice->CreateVideoProcessorEnumerator(&videoProcessorDesc, &m_videoEnumerator);
+ RETURN_VOID_IF_FAILED("Failed to create video enumerator");
+ }
+
+ if (!m_videoProcessor) {
+ hr = m_videoDevice->CreateVideoProcessor(m_videoEnumerator.Get(), 0, &m_videoProcessor);
+ RETURN_VOID_IF_FAILED("Failed to create video processor");
+ }
+
+ if (!m_outputView) {
+ D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC outputDesc = { D3D11_VPOV_DIMENSION_TEXTURE2D };
+ hr = m_videoDevice->CreateVideoProcessorOutputView(
+ m_targetTexture.Get(), m_videoEnumerator.Get(), &outputDesc, &m_outputView);
+ RETURN_VOID_IF_FAILED("Failed to create video output view");
+ }
+
+ D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC inputViewDesc = {
+ 0, D3D11_VPIV_DIMENSION_TEXTURE2D, { 0, 0 }
+ };
+ ComPtr<ID3D11VideoProcessorInputView> inputView;
+ hr = m_videoDevice->CreateVideoProcessorInputView(
+ texture, m_videoEnumerator.Get(), &inputViewDesc, &inputView);
+ RETURN_VOID_IF_FAILED("Failed to create video input view");
+
+ ComPtr<ID3D11DeviceContext> context;
+ ComPtr<ID3D11VideoContext> videoContext;
+ m_d3dDevice->GetImmediateContext(&context);
+ hr = context.As(&videoContext);
+ RETURN_VOID_IF_FAILED("Failed to get video context");
+
+ D3D11_VIDEO_PROCESSOR_STREAM stream = { TRUE };
+ stream.pInputSurface = inputView.Get();
+ hr = videoContext->VideoProcessorBlt(
+ m_videoProcessor.Get(), m_outputView.Get(), 0, 1, &stream);
+ RETURN_VOID_IF_FAILED("Failed to get blit video frame");
+ }
+
+private:
+ ComPtr<ID3D11Device> m_d3dDevice;
+ ComPtr<ID3D11Texture2D> m_targetTexture;
+ ID3D11Texture2D *m_target;
+ ComPtr<ID3D11VideoDevice> m_videoDevice;
+ ComPtr<ID3D11VideoProcessorEnumerator> m_videoEnumerator;
+ ComPtr<ID3D11VideoProcessor> m_videoProcessor;
+ ComPtr<ID3D11VideoProcessorOutputView> m_outputView;
+};
+
+class QWinRTCameraVideoRendererControlPrivate
+{
+public:
+ QScopedPointer<D3DVideoBlitter> blitter;
+ QVector<ComPtr<IMF2DBuffer>> buffers;
+};
+
+QWinRTCameraVideoRendererControl::QWinRTCameraVideoRendererControl(const QSize &size, QObject *parent)
+ : QWinRTAbstractVideoRendererControl(size, parent), d_ptr(new QWinRTCameraVideoRendererControlPrivate)
+{
+}
+
+QWinRTCameraVideoRendererControl::~QWinRTCameraVideoRendererControl()
+{
+ shutdown();
+}
+
+bool QWinRTCameraVideoRendererControl::render(ID3D11Texture2D *target)
+{
+ Q_D(QWinRTCameraVideoRendererControl);
+
+ if (d->buffers.isEmpty()) {
+ emit bufferRequested();
+ return false;
+ }
+
+ HRESULT hr;
+ ComPtr<IMF2DBuffer> buffer = d->buffers.takeFirst();
+
+ ComPtr<ID3D11Texture2D> sourceTexture;
+ ComPtr<IMFDXGIBuffer> dxgiBuffer;
+ hr = buffer.As(&dxgiBuffer);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = dxgiBuffer->GetResource(IID_PPV_ARGS(&sourceTexture));
+ if (FAILED(hr)) {
+ qErrnoWarning(hr, "The video frame does not support texture output; aborting rendering.");
+ return false;
+ }
+
+ ComPtr<ID3D11Device> device;
+ sourceTexture->GetDevice(&device);
+ if (!d->blitter || d->blitter->device() != device.Get() || d->blitter->target() != target)
+ d->blitter.reset(new D3DVideoBlitter(device.Get(), target));
+
+ d->blitter->blit(sourceTexture.Get());
+
+ emit bufferRequested();
+ return true;
+}
+
+void QWinRTCameraVideoRendererControl::queueBuffer(IMF2DBuffer *buffer)
+{
+ Q_D(QWinRTCameraVideoRendererControl);
+ Q_ASSERT(buffer);
+ d->buffers.append(buffer);
+}
+
+void QWinRTCameraVideoRendererControl::discardBuffers()
+{
+ Q_D(QWinRTCameraVideoRendererControl);
+ d->buffers.clear();
+}
diff --git a/src/plugins/winrt/qwinrtcameravideorenderercontrol.h b/src/plugins/winrt/qwinrtcameravideorenderercontrol.h
new file mode 100644
index 000000000..ed8b3388d
--- /dev/null
+++ b/src/plugins/winrt/qwinrtcameravideorenderercontrol.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 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 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTCAMERAVIDEORENDERERCONTROL_H
+#define QWINRTCAMERAVIDEORENDERERCONTROL_H
+
+#include "qwinrtabstractvideorenderercontrol.h"
+
+struct IMF2DBuffer;
+
+QT_BEGIN_NAMESPACE
+
+class QVideoSurfaceFormat;
+class QWinRTCameraVideoRendererControlPrivate;
+class QWinRTCameraVideoRendererControl : public QWinRTAbstractVideoRendererControl
+{
+ Q_OBJECT
+public:
+ explicit QWinRTCameraVideoRendererControl(const QSize &size, QObject *parent);
+ ~QWinRTCameraVideoRendererControl();
+
+ bool render(ID3D11Texture2D *texture) Q_DECL_OVERRIDE;
+ void queueBuffer(IMF2DBuffer *buffer);
+ void discardBuffers();
+
+signals:
+ void bufferRequested();
+
+private:
+ QScopedPointer<QWinRTCameraVideoRendererControlPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QWinRTCameraVideoRendererControl)
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINRTCAMERAVIDEORENDERERCONTROL_H
diff --git a/src/plugins/winrt/qwinrtserviceplugin.cpp b/src/plugins/winrt/qwinrtserviceplugin.cpp
index 5d49b44a4..036d63e39 100644
--- a/src/plugins/winrt/qwinrtserviceplugin.cpp
+++ b/src/plugins/winrt/qwinrtserviceplugin.cpp
@@ -44,6 +44,8 @@
#include "qwinrtserviceplugin.h"
#include "qwinrtmediaplayerservice.h"
+#include "qwinrtcameraservice.h"
+#include "qwinrtvideodeviceselectorcontrol.h"
QT_USE_NAMESPACE
@@ -52,6 +54,9 @@ QMediaService *QWinRTServicePlugin::create(QString const &key)
if (key == QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER))
return new QWinRTMediaPlayerService(this);
+ if (key == QLatin1String(Q_MEDIASERVICE_CAMERA))
+ return new QWinRTCameraService(this);
+
return Q_NULLPTR;
}
@@ -68,3 +73,37 @@ QMediaServiceProviderHint::Features QWinRTServicePlugin::supportedFeatures(
return QMediaServiceProviderHint::Features();
}
+
+QCamera::Position QWinRTServicePlugin::cameraPosition(const QByteArray &device) const
+{
+ return QWinRTVideoDeviceSelectorControl::cameraPosition(device);
+}
+
+int QWinRTServicePlugin::cameraOrientation(const QByteArray &device) const
+{
+ return QWinRTVideoDeviceSelectorControl::cameraOrientation(device);
+}
+
+QList<QByteArray> QWinRTServicePlugin::devices(const QByteArray &service) const
+{
+ if (service == Q_MEDIASERVICE_CAMERA)
+ return QWinRTVideoDeviceSelectorControl::deviceNames();
+
+ return QList<QByteArray>();
+}
+
+QString QWinRTServicePlugin::deviceDescription(const QByteArray &service, const QByteArray &device)
+{
+ if (service == Q_MEDIASERVICE_CAMERA)
+ return QWinRTVideoDeviceSelectorControl::deviceDescription(device);
+
+ return QString();
+}
+
+QByteArray QWinRTServicePlugin::defaultDevice(const QByteArray &service) const
+{
+ if (service == Q_MEDIASERVICE_CAMERA)
+ return QWinRTVideoDeviceSelectorControl::defaultDeviceName();
+
+ return QByteArray();
+}
diff --git a/src/plugins/winrt/qwinrtserviceplugin.h b/src/plugins/winrt/qwinrtserviceplugin.h
index aaac79c7b..9fabadb4f 100644
--- a/src/plugins/winrt/qwinrtserviceplugin.h
+++ b/src/plugins/winrt/qwinrtserviceplugin.h
@@ -48,15 +48,29 @@ QT_USE_NAMESPACE
class QWinRTServicePlugin : public QMediaServiceProviderPlugin
, public QMediaServiceFeaturesInterface
+ , public QMediaServiceCameraInfoInterface
+ , public QMediaServiceSupportedDevicesInterface
+ , public QMediaServiceDefaultDeviceInterface
{
Q_OBJECT
Q_INTERFACES(QMediaServiceFeaturesInterface)
+ Q_INTERFACES(QMediaServiceCameraInfoInterface)
+ Q_INTERFACES(QMediaServiceSupportedDevicesInterface)
+ Q_INTERFACES(QMediaServiceDefaultDeviceInterface)
Q_PLUGIN_METADATA(IID "org.qt-project.qt.mediaserviceproviderfactory/5.0" FILE "winrt.json")
public:
QMediaService *create(QString const &key);
void release(QMediaService *service);
QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const;
+
+ QCamera::Position cameraPosition(const QByteArray &device) const Q_DECL_OVERRIDE;
+ int cameraOrientation(const QByteArray &device) const Q_DECL_OVERRIDE;
+
+ QList<QByteArray> devices(const QByteArray &service) const Q_DECL_OVERRIDE;
+ QString deviceDescription(const QByteArray &service, const QByteArray &device) Q_DECL_OVERRIDE;
+
+ QByteArray defaultDevice(const QByteArray &service) const Q_DECL_OVERRIDE;
};
#endif // QWINRTSERVICEPLUGIN_H
diff --git a/src/plugins/winrt/qwinrtvideodeviceselectorcontrol.cpp b/src/plugins/winrt/qwinrtvideodeviceselectorcontrol.cpp
new file mode 100644
index 000000000..8058c3dad
--- /dev/null
+++ b/src/plugins/winrt/qwinrtvideodeviceselectorcontrol.cpp
@@ -0,0 +1,383 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 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 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwinrtvideodeviceselectorcontrol.h"
+
+#include <QtCore/qfunctions_winrt.h>
+#include <QtCore/QVector>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QEventLoop>
+#include <QtCore/QGlobalStatic>
+
+#include <wrl.h>
+#include <windows.devices.enumeration.h>
+
+using namespace ABI::Windows::Devices::Enumeration;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Foundation::Collections;
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+
+typedef ITypedEventHandler<DeviceWatcher *, DeviceInformation *> DeviceInformationHandler;
+typedef ITypedEventHandler<DeviceWatcher *, DeviceInformationUpdate *> DeviceInformationUpdateHandler;
+typedef ITypedEventHandler<DeviceWatcher *, IInspectable *> DeviceEnumerationCompletedHandler;
+
+QT_USE_NAMESPACE
+
+static QString deviceName(IDeviceInformation *device)
+{
+ HRESULT hr;
+ HString id;
+ hr = device->get_Id(id.GetAddressOf());
+ Q_ASSERT_SUCCEEDED(hr);
+ quint32 length;
+ const wchar_t *buffer = id.GetRawBuffer(&length);
+ return QString::fromWCharArray(buffer, length);
+}
+
+static QString deviceDescription(IDeviceInformation *device)
+{
+ HRESULT hr;
+ HString name;
+ hr = device->get_Name(name.GetAddressOf());
+ Q_ASSERT_SUCCEEDED(hr);
+ quint32 length;
+ const wchar_t *buffer = name.GetRawBuffer(&length);
+ return QString::fromWCharArray(buffer, length);
+}
+
+struct QWinRTVideoDeviceSelectorControlGlobal
+{
+ QWinRTVideoDeviceSelectorControlGlobal()
+ : defaultDeviceIndex(-1)
+ {
+ HRESULT hr;
+ ComPtr<IDeviceInformationStatics> deviceWatcherFactory;
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Devices_Enumeration_DeviceInformation).Get(),
+ IID_PPV_ARGS(&deviceWatcherFactory));
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = deviceWatcherFactory->CreateWatcherDeviceClass(DeviceClass_VideoCapture, &deviceWatcher);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ hr = deviceWatcher->add_Added(
+ Callback<DeviceInformationHandler>(this, &QWinRTVideoDeviceSelectorControlGlobal::onDeviceAdded).Get(),
+ &deviceAddedToken);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ hr = deviceWatcher->add_Removed(
+ Callback<DeviceInformationUpdateHandler>(this, &QWinRTVideoDeviceSelectorControlGlobal::onDeviceRemoved).Get(),
+ &deviceRemovedToken);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ hr = deviceWatcher->add_Updated(
+ Callback<DeviceInformationUpdateHandler>(this, &QWinRTVideoDeviceSelectorControlGlobal::onDeviceUpdated).Get(),
+ &deviceUpdatedToken);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ // Synchronously populate the devices on construction
+ ComPtr<IAsyncOperation<DeviceInformationCollection *>> op;
+ hr = deviceWatcherFactory->FindAllAsyncDeviceClass(DeviceClass_VideoCapture, &op);
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<IVectorView<DeviceInformation *>> deviceList;
+ hr = QWinRTFunctions::await(op, deviceList.GetAddressOf());
+ Q_ASSERT_SUCCEEDED(hr);
+ quint32 deviceCount;
+ hr = deviceList->get_Size(&deviceCount);
+ Q_ASSERT_SUCCEEDED(hr);
+ for (quint32 i = 0; i < deviceCount; ++i) {
+ IDeviceInformation *device;
+ hr = deviceList->GetAt(i, &device);
+ Q_ASSERT_SUCCEEDED(hr);
+ onDeviceAdded(Q_NULLPTR, device);
+ }
+
+ // If there is no default device provided by the API, choose the first one
+ if (!devices.isEmpty() && defaultDeviceIndex < 0)
+ defaultDeviceIndex = 0;
+ }
+
+ ~QWinRTVideoDeviceSelectorControlGlobal()
+ {
+ HRESULT hr;
+ hr = deviceWatcher->remove_Added(deviceAddedToken);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = deviceWatcher->remove_Removed(deviceRemovedToken);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = deviceWatcher->remove_Updated(deviceUpdatedToken);
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+
+private:
+ HRESULT onDeviceAdded(IDeviceWatcher *, IDeviceInformation *device)
+ {
+ const QString name = deviceName(device);
+ if (deviceIndex.contains(name))
+ return S_OK;
+
+ devices.append(device);
+ const int index = devices.size() - 1;
+ deviceIndex.insert(name, index);
+
+ HRESULT hr;
+ boolean isDefault;
+ hr = device->get_IsDefault(&isDefault);
+ Q_ASSERT_SUCCEEDED(hr);
+ if (isDefault)
+ defaultDeviceIndex = index;
+
+ foreach (QWinRTVideoDeviceSelectorControl *watcher, watchers)
+ emit watcher->devicesChanged();
+
+ return S_OK;
+ }
+
+ HRESULT onDeviceRemoved(IDeviceWatcher *, IDeviceInformationUpdate *device)
+ {
+ HRESULT hr;
+ HString id;
+ hr = device->get_Id(id.GetAddressOf());
+ Q_ASSERT_SUCCEEDED(hr);
+
+ HString name;
+ hr = device->get_Id(name.GetAddressOf());
+ Q_ASSERT_SUCCEEDED(hr);
+ quint32 nameLength;
+ const wchar_t *nameString = name.GetRawBuffer(&nameLength);
+ const int index = deviceIndex.take(QString::fromWCharArray(nameString, nameLength));
+ if (index >= 0)
+ devices.remove(index);
+
+ foreach (QWinRTVideoDeviceSelectorControl *watcher, watchers)
+ emit watcher->devicesChanged();
+
+ return S_OK;
+ }
+
+ HRESULT onDeviceUpdated(IDeviceWatcher *, IDeviceInformationUpdate *)
+ {
+ // A name or description may have changed, so emit devicesChanged
+ foreach (QWinRTVideoDeviceSelectorControl *watcher, watchers)
+ emit watcher->devicesChanged();
+
+ return S_OK;
+ }
+
+public:
+ void addWatcher(QWinRTVideoDeviceSelectorControl *control)
+ {
+ watchers.append(control);
+
+ HRESULT hr;
+ DeviceWatcherStatus status;
+ hr = deviceWatcher->get_Status(&status);
+ Q_ASSERT_SUCCEEDED(hr);
+ if (status != DeviceWatcherStatus_Started) {
+ // We can't immediately Start() if we have just called Stop()
+ while (status == DeviceWatcherStatus_Stopping) {
+ QThread::yieldCurrentThread();
+ hr = deviceWatcher->get_Status(&status);
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+ hr = deviceWatcher->Start();
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+ }
+
+ void removeWatcher(QWinRTVideoDeviceSelectorControl *control)
+ {
+ watchers.removeAll(control);
+
+ if (!watchers.isEmpty())
+ return;
+
+ HRESULT hr;
+ DeviceWatcherStatus status;
+ hr = deviceWatcher->get_Status(&status);
+ Q_ASSERT_SUCCEEDED(hr);
+ if (status == DeviceWatcherStatus_Stopped || status == DeviceWatcherStatus_Stopping)
+ return;
+
+ hr = deviceWatcher->Stop();
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+
+ QVector<ComPtr<IDeviceInformation>> devices;
+ QHash<QString, int> deviceIndex;
+ int defaultDeviceIndex;
+
+private:
+ ComPtr<IDeviceWatcher> deviceWatcher;
+ QList<QWinRTVideoDeviceSelectorControl *> watchers;
+ EventRegistrationToken deviceAddedToken;
+ EventRegistrationToken deviceRemovedToken;
+ EventRegistrationToken deviceUpdatedToken;
+};
+Q_GLOBAL_STATIC(QWinRTVideoDeviceSelectorControlGlobal, g)
+
+class QWinRTVideoDeviceSelectorControlPrivate
+{
+public:
+ int selectedDevice;
+};
+
+QWinRTVideoDeviceSelectorControl::QWinRTVideoDeviceSelectorControl(QObject *parent)
+ : QVideoDeviceSelectorControl(parent), d_ptr(new QWinRTVideoDeviceSelectorControlPrivate)
+{
+ Q_D(QWinRTVideoDeviceSelectorControl);
+ d->selectedDevice = -1;
+ g->addWatcher(this);
+}
+
+QWinRTVideoDeviceSelectorControl::~QWinRTVideoDeviceSelectorControl()
+{
+ if (g.isDestroyed())
+ return;
+
+ g->removeWatcher(this);
+}
+
+int QWinRTVideoDeviceSelectorControl::deviceCount() const
+{
+ return g->devices.size();
+}
+
+QString QWinRTVideoDeviceSelectorControl::deviceName(int index) const
+{
+ if (index < 0 || index >= g->devices.size())
+ return QString();
+
+ return ::deviceName(g->devices.at(index).Get());
+}
+
+QString QWinRTVideoDeviceSelectorControl::deviceDescription(int index) const
+{
+ if (index < 0 || index >= g->devices.size())
+ return QString();
+
+ return ::deviceDescription(g->devices.at(index).Get());
+}
+
+int QWinRTVideoDeviceSelectorControl::defaultDevice() const
+{
+ return g->defaultDeviceIndex;
+}
+
+int QWinRTVideoDeviceSelectorControl::selectedDevice() const
+{
+ Q_D(const QWinRTVideoDeviceSelectorControl);
+ return d->selectedDevice;
+}
+
+QCamera::Position QWinRTVideoDeviceSelectorControl::cameraPosition(const QString &deviceName)
+{
+ int deviceIndex = g->deviceIndex.value(deviceName);
+ IDeviceInformation *deviceInfo = g->devices.value(deviceIndex).Get();
+ if (!deviceInfo)
+ return QCamera::UnspecifiedPosition;
+
+ ComPtr<IEnclosureLocation> enclosureLocation;
+ HRESULT hr;
+ hr = deviceInfo->get_EnclosureLocation(&enclosureLocation);
+ RETURN_IF_FAILED("Failed to get camera enclosure location", return QCamera::UnspecifiedPosition);
+ if (!enclosureLocation)
+ return QCamera::UnspecifiedPosition;
+
+ Panel panel;
+ hr = enclosureLocation->get_Panel(&panel);
+ RETURN_IF_FAILED("Failed to get camera panel location", return QCamera::UnspecifiedPosition);
+
+ switch (panel) {
+ case Panel_Front:
+ return QCamera::FrontFace;
+ case Panel_Back:
+ return QCamera::BackFace;
+ default:
+ break;
+ }
+ return QCamera::UnspecifiedPosition;
+}
+
+int QWinRTVideoDeviceSelectorControl::cameraOrientation(const QString &deviceName)
+{
+ Q_UNUSED(deviceName);
+ return 0;
+}
+
+QList<QByteArray> QWinRTVideoDeviceSelectorControl::deviceNames()
+{
+ QList<QByteArray> devices;
+ foreach (const QString &device, g->deviceIndex.keys())
+ devices.append(device.toUtf8());
+
+ return devices;
+}
+
+QByteArray QWinRTVideoDeviceSelectorControl::deviceDescription(const QByteArray &deviceName)
+{
+ int deviceIndex = g->deviceIndex.value(QString::fromUtf8(deviceName), -1);
+ if (deviceIndex < 0)
+ return QByteArray();
+
+ return ::deviceDescription(g->devices.value(deviceIndex).Get()).toUtf8();
+}
+
+QByteArray QWinRTVideoDeviceSelectorControl::defaultDeviceName()
+{
+ if (g->defaultDeviceIndex < 0)
+ return QByteArray();
+
+ return ::deviceName(g->devices.value(g->defaultDeviceIndex).Get()).toUtf8();
+}
+
+void QWinRTVideoDeviceSelectorControl::setSelectedDevice(int index)
+{
+ Q_D(QWinRTVideoDeviceSelectorControl);
+
+ int selectedDevice = index;
+ if (index < 0 || index >= g->devices.size())
+ selectedDevice = -1;
+
+ if (d->selectedDevice != selectedDevice) {
+ d->selectedDevice = selectedDevice;
+ emit selectedDeviceChanged(d->selectedDevice);
+ emit selectedDeviceChanged(deviceName(d->selectedDevice));
+ }
+}
diff --git a/src/plugins/winrt/qwinrtvideodeviceselectorcontrol.h b/src/plugins/winrt/qwinrtvideodeviceselectorcontrol.h
new file mode 100644
index 000000000..2143b3ea8
--- /dev/null
+++ b/src/plugins/winrt/qwinrtvideodeviceselectorcontrol.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 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 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTVIDEODEVICESELECTORCONTROL_H
+#define QWINRTVIDEODEVICESELECTORCONTROL_H
+
+#include <QtMultimedia/QVideoDeviceSelectorControl>
+#include <QtMultimedia/QCameraInfoControl>
+#include <QtCore/qt_windows.h>
+
+struct IInspectable;
+namespace ABI {
+ namespace Windows {
+ namespace Devices {
+ namespace Enumeration {
+ struct IDeviceInformation;
+ }
+ }
+ }
+}
+
+QT_BEGIN_NAMESPACE
+
+class QWinRTVideoDeviceSelectorControlPrivate;
+class QWinRTVideoDeviceSelectorControl : public QVideoDeviceSelectorControl
+{
+ Q_OBJECT
+public:
+ explicit QWinRTVideoDeviceSelectorControl(QObject *parent = 0);
+ ~QWinRTVideoDeviceSelectorControl();
+
+ int deviceCount() const Q_DECL_OVERRIDE;
+
+ QString deviceName(int index) const Q_DECL_OVERRIDE;
+ QString deviceDescription(int index) const Q_DECL_OVERRIDE;
+
+ int defaultDevice() const Q_DECL_OVERRIDE;
+ int selectedDevice() const Q_DECL_OVERRIDE;
+
+ static QCamera::Position cameraPosition(const QString &deviceName);
+ static int cameraOrientation(const QString &deviceName);
+ static QList<QByteArray> deviceNames();
+ static QByteArray deviceDescription(const QByteArray &deviceName);
+ static QByteArray defaultDeviceName();
+
+public slots:
+ void setSelectedDevice(int index) Q_DECL_OVERRIDE;
+
+private:
+ QScopedPointer<QWinRTVideoDeviceSelectorControlPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QWinRTVideoDeviceSelectorControl)
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINRTVIDEODEVICESELECTORCONTROL_H
diff --git a/src/plugins/winrt/winrt.json b/src/plugins/winrt/winrt.json
index b85cfeb12..9af79cc37 100644
--- a/src/plugins/winrt/winrt.json
+++ b/src/plugins/winrt/winrt.json
@@ -1,4 +1,4 @@
{
"Keys": ["winrt"],
- "Services": ["org.qt-project.qt.mediaplayer"]
+ "Services": ["org.qt-project.qt.mediaplayer", "org.qt-project.qt.camera"]
}
diff --git a/src/plugins/winrt/winrt.pro b/src/plugins/winrt/winrt.pro
index 0ea90d22e..04db71e75 100644
--- a/src/plugins/winrt/winrt.pro
+++ b/src/plugins/winrt/winrt.pro
@@ -5,21 +5,33 @@ PLUGIN_TYPE=mediaservice
PLUGIN_CLASS_NAME = WinRTServicePlugin
load(qt_plugin)
-LIBS += -lmfplat -lmfuuid -loleaut32 -ld3d11
+LIBS += -lmfplat -lmfuuid -loleaut32 -ld3d11 -lruntimeobject
HEADERS += \
qwinrtabstractvideorenderercontrol.h \
+ qwinrtcameracontrol.h \
+ qwinrtcamerainfocontrol.h \
+ qwinrtcameraimagecapturecontrol.h \
+ qwinrtcameraservice.h \
+ qwinrtcameravideorenderercontrol.h \
qwinrtmediaplayercontrol.h \
qwinrtmediaplayerservice.h \
qwinrtplayerrenderercontrol.h \
- qwinrtserviceplugin.h
+ qwinrtserviceplugin.h \
+ qwinrtvideodeviceselectorcontrol.h
SOURCES += \
qwinrtabstractvideorenderercontrol.cpp \
+ qwinrtcameracontrol.cpp \
+ qwinrtcamerainfocontrol.cpp \
+ qwinrtcameraimagecapturecontrol.cpp \
+ qwinrtcameraservice.cpp \
+ qwinrtcameravideorenderercontrol.cpp \
qwinrtmediaplayercontrol.cpp \
qwinrtmediaplayerservice.cpp \
qwinrtplayerrenderercontrol.cpp \
- qwinrtserviceplugin.cpp
+ qwinrtserviceplugin.cpp \
+ qwinrtvideodeviceselectorcontrol.cpp
OTHER_FILES += \
winrt.json