summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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