summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2016-09-21 09:28:06 +0200
committerLiang Qi <liang.qi@qt.io>2016-09-21 09:28:06 +0200
commite1ae1235f259393e72e4a2e0d77278e9054405fb (patch)
tree04f57d7b2a9429844306c55e9604f10562ba9783 /src/plugins
parent2e556aef9375377439b9b6da8d455fe891abfd7c (diff)
parent01c9322bfe918b886468eb520d77b21b6d8c0c11 (diff)
Merge remote-tracking branch 'origin/5.8' into dev
Conflicts: src/imports/multimedia/multimedia.cpp Change-Id: I38899391ec8d2fcec6f2d46514286759f7a27629
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm16
-rw-r--r--src/plugins/avfoundation/mediaplayer/avfvideowidget.mm6
-rw-r--r--src/plugins/directshow/camera/dscamerasession.cpp2
-rw-r--r--src/plugins/directshow/player/directshowiosource.cpp77
-rw-r--r--src/plugins/directshow/player/directshowiosource.h2
-rw-r--r--src/plugins/opensles/qopenslesaudiooutput.cpp31
-rw-r--r--src/plugins/videonode/videonode.pro1
-rw-r--r--src/plugins/wasapi/qwasapiaudiodeviceinfo.cpp2
-rw-r--r--src/plugins/wasapi/qwasapiaudioinput.cpp121
-rw-r--r--src/plugins/wasapi/qwasapiaudioinput.h3
-rw-r--r--src/plugins/wasapi/qwasapiaudiooutput.cpp86
-rw-r--r--src/plugins/wasapi/qwasapiaudiooutput.h3
-rw-r--r--src/plugins/wasapi/qwasapiutils.cpp11
-rw-r--r--src/plugins/winrt/qwinrtcameracontrol.cpp11
-rw-r--r--src/plugins/winrt/qwinrtcameracontrol.h2
-rw-r--r--src/plugins/winrt/qwinrtcameraflashcontrol.cpp191
-rw-r--r--src/plugins/winrt/qwinrtcameraflashcontrol.h76
-rw-r--r--src/plugins/winrt/qwinrtcamerafocuscontrol.cpp164
-rw-r--r--src/plugins/winrt/qwinrtcamerafocuscontrol.h3
-rw-r--r--src/plugins/winrt/qwinrtcameraservice.cpp4
-rw-r--r--src/plugins/winrt/winrt.pro2
21 files changed, 604 insertions, 210 deletions
diff --git a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm
index 87bb08e5c..473a18884 100644
--- a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm
+++ b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm
@@ -41,6 +41,8 @@
#include "avfmediaplayerservice.h"
#include "avfvideooutput.h"
+#include <qpointer.h>
+
#import <AVFoundation/AVFoundation.h>
QT_USE_NAMESPACE
@@ -111,15 +113,23 @@ static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMe
//Create an asset for inspection of a resource referenced by a given URL.
//Load the values for the asset keys "tracks", "playable".
- AVURLAsset *asset = [AVURLAsset URLAssetWithURL:m_URL options:nil];
- NSArray *requestedKeys = [NSArray arrayWithObjects:AVF_TRACKS_KEY, AVF_PLAYABLE_KEY, nil];
+ // use __block to avoid maintaining strong references on variables captured by the
+ // following block callback
+ __block AVURLAsset *asset = [[AVURLAsset URLAssetWithURL:m_URL options:nil] retain];
+ __block NSArray *requestedKeys = [[NSArray arrayWithObjects:AVF_TRACKS_KEY, AVF_PLAYABLE_KEY, nil] retain];
+
+ __block AVFMediaPlayerSessionObserver *blockSelf = self;
+ QPointer<AVFMediaPlayerSession> session(m_session);
// Tells the asset to load the values of any of the specified keys that are not already loaded.
[asset loadValuesAsynchronouslyForKeys:requestedKeys completionHandler:
^{
dispatch_async( dispatch_get_main_queue(),
^{
- [self prepareToPlayAsset:asset withKeys:requestedKeys];
+ if (session)
+ [blockSelf prepareToPlayAsset:asset withKeys:requestedKeys];
+ [asset release];
+ [requestedKeys release];
});
}];
}
diff --git a/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm b/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm
index 3b270f9b6..7eb5a71cf 100644
--- a/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm
+++ b/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm
@@ -45,6 +45,12 @@
#include <QtGui/QPaintEvent>
#include <QtGui/QPainter>
+#if defined(Q_OS_MACOS)
+#import <AppKit/AppKit.h>
+#else
+#import <UIKit/UIKit.h>
+#endif
+
QT_USE_NAMESPACE
AVFVideoWidget::AVFVideoWidget(QWidget *parent)
diff --git a/src/plugins/directshow/camera/dscamerasession.cpp b/src/plugins/directshow/camera/dscamerasession.cpp
index 509057ba1..5587b479c 100644
--- a/src/plugins/directshow/camera/dscamerasession.cpp
+++ b/src/plugins/directshow/camera/dscamerasession.cpp
@@ -174,6 +174,8 @@ QVideoFrame::PixelFormat pixelFormatFromMediaSubtype(GUID uid)
return QVideoFrame::Format_YUYV;
else if (uid == MEDIASUBTYPE_NV12)
return QVideoFrame::Format_NV12;
+ else if (uid == MEDIASUBTYPE_MJPG)
+ return QVideoFrame::Format_Jpeg;
else if (uid == MEDIASUBTYPE_IMC1)
return QVideoFrame::Format_IMC1;
else if (uid == MEDIASUBTYPE_IMC2)
diff --git a/src/plugins/directshow/player/directshowiosource.cpp b/src/plugins/directshow/player/directshowiosource.cpp
index 4dc8bec3d..3c44dd1ed 100644
--- a/src/plugins/directshow/player/directshowiosource.cpp
+++ b/src/plugins/directshow/player/directshowiosource.cpp
@@ -47,6 +47,22 @@
#include <QtCore/qcoreapplication.h>
#include <QtCore/qurl.h>
+static const GUID directshow_subtypes[] =
+{
+ MEDIASUBTYPE_NULL,
+ MEDIASUBTYPE_Avi,
+ MEDIASUBTYPE_Asf,
+ MEDIASUBTYPE_MPEG1Video,
+ MEDIASUBTYPE_QTMovie,
+ MEDIASUBTYPE_WAVE,
+ MEDIASUBTYPE_AIFF,
+ MEDIASUBTYPE_AU,
+ MEDIASUBTYPE_DssVideo,
+ MEDIASUBTYPE_MPEG1Audio,
+ MEDIASUBTYPE_MPEG1System,
+ MEDIASUBTYPE_MPEG1VideoCD
+};
+
DirectShowIOSource::DirectShowIOSource(DirectShowEventLoop *loop)
: m_ref(1)
, m_state(State_Stopped)
@@ -65,13 +81,26 @@ DirectShowIOSource::DirectShowIOSource(DirectShowEventLoop *loop)
//
// The filter works in pull mode, the downstream filter is responsible for requesting
// samples from this one.
-
- m_outputType.majortype = MEDIATYPE_Stream;
- m_outputType.subtype = MEDIASUBTYPE_NULL; // Wildcard
- m_outputType.bFixedSizeSamples = TRUE;
- m_outputType.lSampleSize = 1;
-
- m_supportedMediaTypes.append(m_outputType);
+ //
+ AM_MEDIA_TYPE type =
+ {
+ MEDIATYPE_Stream, // majortype
+ MEDIASUBTYPE_NULL, // subtype
+ TRUE, // bFixedSizeSamples
+ FALSE, // bTemporalCompression
+ 1, // lSampleSize
+ GUID_NULL, // formattype
+ 0, // pUnk
+ 0, // cbFormat
+ 0, // pbFormat
+ };
+
+ static const int count = sizeof(directshow_subtypes) / sizeof(GUID);
+
+ for (int i = 0; i < count; ++i) {
+ type.subtype = directshow_subtypes[i];
+ m_supportedMediaTypes.append(type);
+ }
}
DirectShowIOSource::~DirectShowIOSource()
@@ -328,14 +357,40 @@ HRESULT DirectShowIOSource::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
return VFW_E_ALREADY_CONNECTED;
// If we get a type from the graph manager, check that we support that
- if (pmt && (pmt->majortype != MEDIATYPE_Stream || pmt->subtype != MEDIASUBTYPE_NULL))
+ if (pmt && pmt->majortype != MEDIATYPE_Stream)
return VFW_E_TYPE_NOT_ACCEPTED;
// This filter only works in pull mode, the downstream filter must query for the
// AsyncReader interface during ReceiveConnection().
// If it doesn't, we can't connect to it.
m_queriedForAsyncReader = false;
- HRESULT hr = pReceivePin->ReceiveConnection(this, pmt ? pmt : &m_outputType);
+ HRESULT hr = 0;
+ // Negotiation of media type
+ // - Complete'ish type (Stream with subtype specified).
+ if (pmt && pmt->subtype != MEDIASUBTYPE_NULL /* aka. GUID_NULL */) {
+ hr = pReceivePin->ReceiveConnection(this, pmt);
+ // Update the media type for the current connection.
+ if (SUCCEEDED(hr))
+ m_connectionMediaType = *pmt;
+ } else if (pmt && pmt->subtype == MEDIATYPE_NULL) { // - Partial type (Stream, but no subtype specified).
+ m_connectionMediaType = *pmt;
+ // Check if the receiving pin accepts any of the streaming subtypes.
+ for (const DirectShowMediaType &t : qAsConst(m_supportedMediaTypes)) {
+ m_connectionMediaType.subtype = t.subtype;
+ hr = pReceivePin->ReceiveConnection(this, &m_connectionMediaType);
+ if (SUCCEEDED(hr))
+ break;
+ }
+ } else { // - No media type specified.
+ // Check if the receiving pin accepts any of the streaming types.
+ for (const DirectShowMediaType &t : qAsConst(m_supportedMediaTypes)) {
+ hr = pReceivePin->ReceiveConnection(this, &t);
+ if (SUCCEEDED(hr)) {
+ m_connectionMediaType = t;
+ break;
+ }
+ }
+ }
if (SUCCEEDED(hr) && m_queriedForAsyncReader) {
m_peerPin = pReceivePin;
@@ -348,6 +403,8 @@ HRESULT DirectShowIOSource::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
}
if (!m_queriedForAsyncReader)
hr = VFW_E_NO_TRANSPORT;
+
+ m_connectionMediaType.clear();
}
return hr;
@@ -420,7 +477,7 @@ HRESULT DirectShowIOSource::ConnectionMediaType(AM_MEDIA_TYPE *pmt)
return VFW_E_NOT_CONNECTED;
} else {
- DirectShowMediaType::copy(pmt, m_outputType);
+ DirectShowMediaType::copy(pmt, m_connectionMediaType);
return S_OK;
}
diff --git a/src/plugins/directshow/player/directshowiosource.h b/src/plugins/directshow/player/directshowiosource.h
index efcde7a27..702bfed61 100644
--- a/src/plugins/directshow/player/directshowiosource.h
+++ b/src/plugins/directshow/player/directshowiosource.h
@@ -123,7 +123,7 @@ private:
IReferenceClock *m_clock;
IMemAllocator *m_allocator;
IPin *m_peerPin;
- DirectShowMediaType m_outputType;
+ DirectShowMediaType m_connectionMediaType;
QList<DirectShowMediaType> m_supportedMediaTypes;
QString m_filterName;
const QString m_pinId;
diff --git a/src/plugins/opensles/qopenslesaudiooutput.cpp b/src/plugins/opensles/qopenslesaudiooutput.cpp
index 26f2380b2..70d77a380 100644
--- a/src/plugins/opensles/qopenslesaudiooutput.cpp
+++ b/src/plugins/opensles/qopenslesaudiooutput.cpp
@@ -114,11 +114,18 @@ QAudio::State QOpenSLESAudioOutput::state() const
void QOpenSLESAudioOutput::start(QIODevice *device)
{
Q_ASSERT(device);
+
+ if (m_state != QAudio::StoppedState)
+ stop();
+
if (!preparePlayer())
return;
m_pullMode = true;
m_audioSource = device;
+ m_nextBuffer = 0;
+ m_processedBytes = 0;
+ m_availableBuffers = BUFFER_COUNT;
setState(QAudio::ActiveState);
setError(QAudio::NoError);
@@ -136,6 +143,9 @@ void QOpenSLESAudioOutput::start(QIODevice *device)
m_processedBytes += readSize;
}
+ if (m_processedBytes < 1)
+ onEOSEvent();
+
// Change the state to playing.
// We need to do this after filling the buffers or processedBytes might get corrupted.
startPlayer();
@@ -143,10 +153,15 @@ void QOpenSLESAudioOutput::start(QIODevice *device)
QIODevice *QOpenSLESAudioOutput::start()
{
+ if (m_state != QAudio::StoppedState)
+ stop();
+
if (!preparePlayer())
return Q_NULLPTR;
m_pullMode = false;
+ m_processedBytes = 0;
+ m_availableBuffers = BUFFER_COUNT;
m_audioSource = new SLIODevicePrivate(this);
m_audioSource->open(QIODevice::WriteOnly | QIODevice::Unbuffered);
@@ -372,7 +387,10 @@ void QOpenSLESAudioOutput::bufferAvailable(quint32 count, quint32 playIndex)
if (!m_pullMode) { // We're in push mode.
// Signal that there is a new open slot in the buffer and return
- m_availableBuffers.fetchAndAddRelease(1);
+ const int val = m_availableBuffers.fetchAndAddRelease(1) + 1;
+ if (val == BUFFER_COUNT)
+ QMetaObject::invokeMethod(this, "onEOSEvent", Qt::QueuedConnection);
+
return;
}
@@ -380,8 +398,11 @@ void QOpenSLESAudioOutput::bufferAvailable(quint32 count, quint32 playIndex)
const int index = m_nextBuffer * m_bufferSize;
const qint64 readSize = m_audioSource->read(m_buffers + index, m_bufferSize);
- if (1 > readSize)
+ if (readSize < 1) {
+ QMetaObject::invokeMethod(this, "onEOSEvent", Qt::QueuedConnection);
return;
+ }
+
if (SL_RESULT_SUCCESS != (*m_bufferQueueItf)->Enqueue(m_bufferQueueItf,
m_buffers + index,
@@ -606,6 +627,12 @@ void QOpenSLESAudioOutput::stopPlayer()
{
setState(QAudio::StoppedState);
+ if (m_audioSource && !m_pullMode) {
+ m_audioSource->close();
+ delete m_audioSource;
+ m_audioSource = Q_NULLPTR;
+ }
+
// We need to change the state manually...
if (m_playItf)
(*m_playItf)->SetPlayState(m_playItf, SL_PLAYSTATE_STOPPED);
diff --git a/src/plugins/videonode/videonode.pro b/src/plugins/videonode/videonode.pro
index b7b18cdcf..5fbcaecd4 100644
--- a/src/plugins/videonode/videonode.pro
+++ b/src/plugins/videonode/videonode.pro
@@ -1,4 +1,5 @@
TEMPLATE = subdirs
+QT_FOR_CONFIG += gui-private
config_gpu_vivante {
SUBDIRS += imx6
diff --git a/src/plugins/wasapi/qwasapiaudiodeviceinfo.cpp b/src/plugins/wasapi/qwasapiaudiodeviceinfo.cpp
index 0fa618fe4..e1a46841d 100644
--- a/src/plugins/wasapi/qwasapiaudiodeviceinfo.cpp
+++ b/src/plugins/wasapi/qwasapiaudiodeviceinfo.cpp
@@ -54,7 +54,7 @@ QWasapiAudioDeviceInfo::QWasapiAudioDeviceInfo(QByteArray dev, QAudio::Mode mode
QAudioFormat referenceFormat = m_interface->m_mixFormat;
- const int rates[] = {8000, 11025, 160000, 22050, 32000, 44100, 48000, 88200, 96000, 192000};
+ const int rates[] = {8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200, 96000, 192000};
for (int rate : rates) {
QAudioFormat f = referenceFormat;
f.setSampleRate(rate);
diff --git a/src/plugins/wasapi/qwasapiaudioinput.cpp b/src/plugins/wasapi/qwasapiaudioinput.cpp
index 3bcf50367..22a77df38 100644
--- a/src/plugins/wasapi/qwasapiaudioinput.cpp
+++ b/src/plugins/wasapi/qwasapiaudioinput.cpp
@@ -120,7 +120,7 @@ qint64 WasapiInputDevicePrivate::readData(char* data, qint64 len)
qFatal("Could not release buffer");
if (m_input->m_interval && m_input->m_openTime.elapsed() - m_input->m_openTimeOffset > m_input->m_interval) {
- QMetaObject::invokeMethod(m_input, "notify", Qt::QueuedConnection);
+ emit m_input->notify();
m_input->m_openTimeOffset = m_input->m_openTime.elapsed();
}
@@ -128,8 +128,7 @@ qint64 WasapiInputDevicePrivate::readData(char* data, qint64 len)
if (m_input->m_currentState != QAudio::ActiveState) {
m_input->m_currentState = QAudio::ActiveState;
- QMetaObject::invokeMethod(m_input, "stateChanged", Qt::QueuedConnection,
- Q_ARG(QAudio::State, QAudio::ActiveState));
+ emit m_input->stateChanged(m_input->m_currentState);
}
return readBytes;
}
@@ -192,13 +191,9 @@ qreal QWasapiAudioInput::volume() const
void QWasapiAudioInput::process()
{
qCDebug(lcMmAudioInput) << __FUNCTION__;
- const quint32 channelCount = m_currentFormat.channelCount();
- const quint32 sampleBytes = m_currentFormat.sampleSize() / 8;
- BYTE* buffer;
- HRESULT hr;
DWORD waitRet;
- bool processing = true;
+ m_processing = true;
do {
waitRet = WaitForSingleObjectEx(m_event, 2000, FALSE);
if (waitRet != WAIT_OBJECT_0) {
@@ -210,67 +205,75 @@ void QWasapiAudioInput::process()
if (m_currentState != QAudio::ActiveState && m_currentState != QAudio::IdleState)
break;
+ QMetaObject::invokeMethod(this, "processBuffer", Qt::QueuedConnection);
+ } while (m_processing);
+}
- if (!m_pullMode) {
- QMetaObject::invokeMethod(m_eventDevice, "readyRead", Qt::QueuedConnection);
- ResetEvent(m_event);
- continue;
- }
+void QWasapiAudioInput::processBuffer()
+{
+ if (!m_pullMode) {
+ emit m_eventDevice->readyRead();
+ ResetEvent(m_event);
+ return;
+ }
- quint32 packetFrames;
- hr = m_capture->GetNextPacketSize(&packetFrames);
+ QMutexLocker locker(&m_mutex);
+ const quint32 channelCount = m_currentFormat.channelCount();
+ const quint32 sampleBytes = m_currentFormat.sampleSize() / 8;
+ BYTE* buffer;
+ HRESULT hr;
- while (packetFrames != 0 && m_currentState == QAudio::ActiveState) {
- DWORD flags;
- quint64 devicePosition;
- hr = m_capture->GetBuffer(&buffer, &packetFrames, &flags, &devicePosition, NULL);
- if (hr != S_OK) {
- m_currentError = QAudio::FatalError;
- QMetaObject::invokeMethod(this, "errorChanged", Qt::QueuedConnection,
- Q_ARG(QAudio::Error, QAudio::UnderrunError));
- // Also Error Buffers need to be released
- hr = m_capture->ReleaseBuffer(packetFrames);
- qCDebug(lcMmAudioInput) << __FUNCTION__ << "Could not acquire input buffer.";
- return;
- }
- const quint32 writeBytes = packetFrames * channelCount * sampleBytes;
- if (Q_UNLIKELY(flags & AUDCLNT_BUFFERFLAGS_SILENT)) {
- // In case this flag is set, user is supposed to ignore the content
- // of the buffer and manually write silence
- qCDebug(lcMmAudioInput) << __FUNCTION__ << "AUDCLNT_BUFFERFLAGS_SILENT: "
- << "Ignoring buffer and writing silence.";
- buffer = new BYTE[writeBytes];
- memset(buffer, 0, writeBytes);
- }
+ quint32 packetFrames;
+ hr = m_capture->GetNextPacketSize(&packetFrames);
+
+ while (packetFrames != 0 && m_currentState == QAudio::ActiveState) {
+ DWORD flags;
+ quint64 devicePosition;
+ hr = m_capture->GetBuffer(&buffer, &packetFrames, &flags, &devicePosition, NULL);
+ if (hr != S_OK) {
+ m_currentError = QAudio::FatalError;
+ emit errorChanged(m_currentError);
+ // Also Error Buffers need to be released
+ hr = m_capture->ReleaseBuffer(packetFrames);
+ qCDebug(lcMmAudioInput) << __FUNCTION__ << "Could not acquire input buffer.";
+ return;
+ }
+ const quint32 writeBytes = packetFrames * channelCount * sampleBytes;
+ if (Q_UNLIKELY(flags & AUDCLNT_BUFFERFLAGS_SILENT)) {
+ // In case this flag is set, user is supposed to ignore the content
+ // of the buffer and manually write silence
+ qCDebug(lcMmAudioInput) << __FUNCTION__ << "AUDCLNT_BUFFERFLAGS_SILENT: "
+ << "Ignoring buffer and writing silence.";
+ buffer = new BYTE[writeBytes];
+ memset(buffer, 0, writeBytes);
+ }
- qint64 written = m_eventDevice->write(reinterpret_cast<const char *>(buffer), writeBytes);
+ const qint64 written = m_eventDevice->write(reinterpret_cast<const char *>(buffer), writeBytes);
- if (Q_UNLIKELY(flags & AUDCLNT_BUFFERFLAGS_SILENT))
- delete [] buffer;
+ if (Q_UNLIKELY(flags & AUDCLNT_BUFFERFLAGS_SILENT))
+ delete [] buffer;
- if (written < static_cast<qint64>(writeBytes)) {
- if (m_currentError != QAudio::UnderrunError) {
- m_currentError = QAudio::UnderrunError;
- QMetaObject::invokeMethod(this, "errorChanged", Qt::QueuedConnection,
- Q_ARG(QAudio::Error, QAudio::UnderrunError));
- }
+ if (written < static_cast<qint64>(writeBytes)) {
+ if (m_currentError != QAudio::UnderrunError) {
+ m_currentError = QAudio::UnderrunError;
+ emit errorChanged(m_currentError);
}
- hr = m_capture->ReleaseBuffer(packetFrames);
- if (hr != S_OK)
- qFatal("Could not release buffer");
+ }
+ hr = m_capture->ReleaseBuffer(packetFrames);
+ if (hr != S_OK)
+ qFatal("Could not release buffer");
- m_bytesProcessed += writeBytes;
+ m_bytesProcessed += writeBytes;
- hr = m_capture->GetNextPacketSize(&packetFrames);
- }
- ResetEvent(m_event);
+ hr = m_capture->GetNextPacketSize(&packetFrames);
+ }
+ ResetEvent(m_event);
- if (m_interval && m_openTime.elapsed() - m_openTimeOffset > m_interval) {
- QMetaObject::invokeMethod(this, "notify", Qt::QueuedConnection);
- m_openTimeOffset = m_openTime.elapsed();
- }
- processing = m_currentState == QAudio::ActiveState || m_currentState == QAudio::IdleState;
- } while (processing);
+ if (m_interval && m_openTime.elapsed() - m_openTimeOffset > m_interval) {
+ emit notify();
+ m_openTimeOffset = m_openTime.elapsed();
+ }
+ m_processing = m_currentState == QAudio::ActiveState || m_currentState == QAudio::IdleState;
}
bool QWasapiAudioInput::initStart(bool pull)
diff --git a/src/plugins/wasapi/qwasapiaudioinput.h b/src/plugins/wasapi/qwasapiaudioinput.h
index cb2f46436..3fd7315c1 100644
--- a/src/plugins/wasapi/qwasapiaudioinput.h
+++ b/src/plugins/wasapi/qwasapiaudioinput.h
@@ -88,6 +88,8 @@ public:
qreal volume() const Q_DECL_OVERRIDE;
void process();
+public slots:
+ void processBuffer();
private:
bool initStart(bool pull);
friend class WasapiInputDevicePrivate;
@@ -112,6 +114,7 @@ private:
quint32 m_bufferBytes;
HANDLE m_event;
QWasapiProcessThread *m_eventThread;
+ QAtomicInt m_processing;
QIODevice *m_eventDevice;
};
diff --git a/src/plugins/wasapi/qwasapiaudiooutput.cpp b/src/plugins/wasapi/qwasapiaudiooutput.cpp
index 53f4f2710..1b0f64451 100644
--- a/src/plugins/wasapi/qwasapiaudiooutput.cpp
+++ b/src/plugins/wasapi/qwasapiaudiooutput.cpp
@@ -206,13 +206,9 @@ qreal QWasapiAudioOutput::volume() const
void QWasapiAudioOutput::process()
{
qCDebug(lcMmAudioOutput) << __FUNCTION__;
- const quint32 channelCount = m_currentFormat.channelCount();
- const quint32 sampleBytes = m_currentFormat.sampleSize() / 8;
- BYTE* buffer;
- HRESULT hr;
DWORD waitRet;
- bool processing = true;
+ m_processing = true;
do {
waitRet = WaitForSingleObjectEx(m_event, 2000, FALSE);
if (waitRet != WAIT_OBJECT_0) {
@@ -224,51 +220,59 @@ void QWasapiAudioOutput::process()
if (m_currentState != QAudio::ActiveState && m_currentState != QAudio::IdleState)
break;
+ QMetaObject::invokeMethod(this, "processBuffer", Qt::QueuedConnection);
+ } while (m_processing);
+}
- quint32 paddingFrames;
- hr = m_interface->m_client->GetCurrentPadding(&paddingFrames);
+void QWasapiAudioOutput::processBuffer()
+{
+ QMutexLocker locker(&m_mutex);
- quint32 availableFrames = m_bufferFrames - paddingFrames;
- hr = m_renderer->GetBuffer(availableFrames, &buffer);
- if (hr != S_OK) {
- m_currentError = QAudio::UnderrunError;
- QMetaObject::invokeMethod(this, "errorChanged", Qt::QueuedConnection,
- Q_ARG(QAudio::Error, QAudio::UnderrunError));
- // Also Error Buffers need to be released
- hr = m_renderer->ReleaseBuffer(availableFrames, 0);
- ResetEvent(m_event);
- continue; // We will continue trying
- }
+ const quint32 channelCount = m_currentFormat.channelCount();
+ const quint32 sampleBytes = m_currentFormat.sampleSize() / 8;
+ BYTE* buffer;
+ HRESULT hr;
- const quint32 readBytes = availableFrames * channelCount * sampleBytes;
- qint64 read = m_eventDevice->read((char*)buffer, readBytes);
- if (read < static_cast<qint64>(readBytes)) {
- // Fill the rest of the buffer with zero to avoid audio glitches
- if (m_currentError != QAudio::UnderrunError) {
- m_currentError = QAudio::UnderrunError;
- QMetaObject::invokeMethod(this, "errorChanged", Qt::QueuedConnection,
- Q_ARG(QAudio::Error, QAudio::UnderrunError));
- }
- if (m_currentState != QAudio::IdleState) {
- m_currentState = QAudio::IdleState;
- QMetaObject::invokeMethod(this, "stateChanged", Qt::QueuedConnection,
- Q_ARG(QAudio::State, QAudio::IdleState));
- }
- }
+ quint32 paddingFrames;
+ hr = m_interface->m_client->GetCurrentPadding(&paddingFrames);
+ const quint32 availableFrames = m_bufferFrames - paddingFrames;
+ hr = m_renderer->GetBuffer(availableFrames, &buffer);
+ if (hr != S_OK) {
+ m_currentError = QAudio::UnderrunError;
+ emit errorChanged(m_currentError);
+ // Also Error Buffers need to be released
hr = m_renderer->ReleaseBuffer(availableFrames, 0);
- if (hr != S_OK)
- qFatal("Could not release buffer");
ResetEvent(m_event);
+ return;
+ }
- if (m_interval && m_openTime.elapsed() - m_openTimeOffset > m_interval) {
- QMetaObject::invokeMethod(this, "notify", Qt::QueuedConnection);
- m_openTimeOffset = m_openTime.elapsed();
+ const quint32 readBytes = availableFrames * channelCount * sampleBytes;
+ const qint64 read = m_eventDevice->read((char*)buffer, readBytes);
+ if (read < static_cast<qint64>(readBytes)) {
+ // Fill the rest of the buffer with zero to avoid audio glitches
+ if (m_currentError != QAudio::UnderrunError) {
+ m_currentError = QAudio::UnderrunError;
+ emit errorChanged(m_currentError);
}
+ if (m_currentState != QAudio::IdleState) {
+ m_currentState = QAudio::IdleState;
+ emit stateChanged(m_currentState);
+ }
+ }
+
+ hr = m_renderer->ReleaseBuffer(availableFrames, 0);
+ if (hr != S_OK)
+ qFatal("Could not release buffer");
+ ResetEvent(m_event);
+
+ if (m_interval && m_openTime.elapsed() - m_openTimeOffset > m_interval) {
+ emit notify();
+ m_openTimeOffset = m_openTime.elapsed();
+ }
- m_bytesProcessed += read;
- processing = m_currentState == QAudio::ActiveState || m_currentState == QAudio::IdleState;
- } while (processing);
+ m_bytesProcessed += read;
+ m_processing = m_currentState == QAudio::ActiveState || m_currentState == QAudio::IdleState;
}
bool QWasapiAudioOutput::initStart(bool pull)
diff --git a/src/plugins/wasapi/qwasapiaudiooutput.h b/src/plugins/wasapi/qwasapiaudiooutput.h
index 247a07160..118731af9 100644
--- a/src/plugins/wasapi/qwasapiaudiooutput.h
+++ b/src/plugins/wasapi/qwasapiaudiooutput.h
@@ -89,6 +89,8 @@ public:
qreal volume() const Q_DECL_OVERRIDE;
void process();
+public slots:
+ void processBuffer();
private:
bool initStart(bool pull);
friend class WasapiOutputDevicePrivate;
@@ -113,6 +115,7 @@ private:
quint32 m_bufferBytes;
HANDLE m_event;
QWasapiProcessThread *m_eventThread;
+ QAtomicInt m_processing;
QIODevice *m_eventDevice;
};
diff --git a/src/plugins/wasapi/qwasapiutils.cpp b/src/plugins/wasapi/qwasapiutils.cpp
index 6340a3b01..727c94c23 100644
--- a/src/plugins/wasapi/qwasapiutils.cpp
+++ b/src/plugins/wasapi/qwasapiutils.cpp
@@ -182,6 +182,13 @@ QByteArray QWasapiUtils::defaultDevice(QAudio::Mode mode)
{
qCDebug(lcMmUtils) << __FUNCTION__ << mode;
+ QList<QByteArray> &deviceNames = mode == QAudio::AudioInput ? gMapping->inputDeviceNames : gMapping->outputDeviceNames;
+ QList<QString> &deviceIds = mode == QAudio::AudioInput ? gMapping->inputDeviceIds : gMapping->outputDeviceIds;
+ if (deviceNames.isEmpty() || deviceIds.isEmpty()) // Initialize
+ availableDevices(mode);
+ if (deviceNames.isEmpty() || deviceIds.isEmpty()) // No audio devices at all
+ return QByteArray();
+
ComPtr<IMediaDeviceStatics> mediaDeviceStatics;
HRESULT hr;
@@ -198,7 +205,9 @@ QByteArray QWasapiUtils::defaultDevice(QAudio::Mode mode)
const wchar_t *dadWStr = defaultAudioDevice.GetRawBuffer(&dADSize);
const QString defaultAudioDeviceId = QString::fromWCharArray(dadWStr, dADSize);
- return defaultAudioDeviceId.toLocal8Bit();
+ Q_ASSERT(deviceIds.indexOf(defaultAudioDeviceId) != -1);
+
+ return deviceNames.at(deviceIds.indexOf(defaultAudioDeviceId));
}
QList<QByteArray> QWasapiUtils::availableDevices(QAudio::Mode mode)
diff --git a/src/plugins/winrt/qwinrtcameracontrol.cpp b/src/plugins/winrt/qwinrtcameracontrol.cpp
index c32a5f2e2..f81a2e94d 100644
--- a/src/plugins/winrt/qwinrtcameracontrol.cpp
+++ b/src/plugins/winrt/qwinrtcameracontrol.cpp
@@ -42,6 +42,7 @@
#include "qwinrtvideodeviceselectorcontrol.h"
#include "qwinrtcameraimagecapturecontrol.h"
#include "qwinrtimageencodercontrol.h"
+#include "qwinrtcameraflashcontrol.h"
#include "qwinrtcamerafocuscontrol.h"
#include "qwinrtcameralockscontrol.h"
@@ -554,6 +555,7 @@ public:
QPointer<QWinRTVideoDeviceSelectorControl> videoDeviceSelector;
QPointer<QWinRTCameraImageCaptureControl> imageCaptureControl;
QPointer<QWinRTImageEncoderControl> imageEncoderControl;
+ QPointer<QWinRTCameraFlashControl> cameraFlashControl;
QPointer<QWinRTCameraFocusControl> cameraFocusControl;
QPointer<QWinRTCameraLocksControl> cameraLocksControl;
QAtomicInt framesMapped;
@@ -578,6 +580,7 @@ QWinRTCameraControl::QWinRTCameraControl(QObject *parent)
d->videoDeviceSelector = new QWinRTVideoDeviceSelectorControl(this);
d->imageCaptureControl = new QWinRTCameraImageCaptureControl(this);
d->imageEncoderControl = new QWinRTImageEncoderControl(this);
+ d->cameraFlashControl = new QWinRTCameraFlashControl(this);
d->cameraFocusControl = new QWinRTCameraFocusControl(this);
d->cameraLocksControl = new QWinRTCameraLocksControl(this);
@@ -815,6 +818,12 @@ QImageEncoderControl *QWinRTCameraControl::imageEncoderControl() const
return d->imageEncoderControl;
}
+QCameraFlashControl *QWinRTCameraControl::cameraFlashControl() const
+{
+ Q_D(const QWinRTCameraControl);
+ return d->cameraFlashControl;
+}
+
QCameraFocusControl *QWinRTCameraControl::cameraFocusControl() const
{
Q_D(const QWinRTCameraControl);
@@ -940,6 +949,8 @@ HRESULT QWinRTCameraControl::initialize()
hr = advancedVideoDeviceController->get_FocusControl(&d->focusControl);
Q_ASSERT_SUCCEEDED(hr);
+ d->cameraFlashControl->initialize(advancedVideoDeviceController);
+
boolean isFocusSupported;
hr = d->focusControl->get_Supported(&isFocusSupported);
Q_ASSERT_SUCCEEDED(hr);
diff --git a/src/plugins/winrt/qwinrtcameracontrol.h b/src/plugins/winrt/qwinrtcameracontrol.h
index 85dd4d44b..f978a8b2c 100644
--- a/src/plugins/winrt/qwinrtcameracontrol.h
+++ b/src/plugins/winrt/qwinrtcameracontrol.h
@@ -69,6 +69,7 @@ class QVideoRendererControl;
class QVideoDeviceSelectorControl;
class QCameraImageCaptureControl;
class QImageEncoderControl;
+class QCameraFlashControl;
class QCameraFocusControl;
class QCameraLocksControl;
@@ -95,6 +96,7 @@ public:
QVideoDeviceSelectorControl *videoDeviceSelector() const;
QCameraImageCaptureControl *imageCaptureControl() const;
QImageEncoderControl *imageEncoderControl() const;
+ QCameraFlashControl *cameraFlashControl() const;
QCameraFocusControl *cameraFocusControl() const;
QCameraLocksControl *cameraLocksControl() const;
diff --git a/src/plugins/winrt/qwinrtcameraflashcontrol.cpp b/src/plugins/winrt/qwinrtcameraflashcontrol.cpp
new file mode 100644
index 000000000..1ea877672
--- /dev/null
+++ b/src/plugins/winrt/qwinrtcameraflashcontrol.cpp
@@ -0,0 +1,191 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies).
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwinrtcameraflashcontrol.h"
+#include "qwinrtcameracontrol.h"
+#include <QtCore/QTimer>
+#include <QtCore/qfunctions_winrt.h>
+#include <QtCore/private/qeventdispatcher_winrt_p.h>
+
+#include <windows.media.devices.h>
+#include <wrl.h>
+#include <functional>
+
+using namespace Microsoft::WRL;
+using namespace ABI::Windows::Media::Devices;
+
+QT_BEGIN_NAMESPACE
+
+class QWinRTCameraFlashControlPrivate
+{
+public:
+ ComPtr<IFlashControl> flashControl;
+
+ QList<QCameraExposure::FlashModes> supportedModes;
+ QCameraExposure::FlashModes currentModes;
+ bool initialized;
+};
+
+QWinRTCameraFlashControl::QWinRTCameraFlashControl(QWinRTCameraControl *parent)
+ : QCameraFlashControl(parent), d_ptr(new QWinRTCameraFlashControlPrivate)
+{
+ qCDebug(lcMMCamera) << __FUNCTION__ << parent;
+ Q_D(QWinRTCameraFlashControl);
+
+ d->initialized = false;
+ d->currentModes = QCameraExposure::FlashOff;
+}
+
+void QWinRTCameraFlashControl::initialize(Microsoft::WRL::ComPtr<IAdvancedVideoCaptureDeviceController2> &controller)
+{
+ qCDebug(lcMMCamera) << __FUNCTION__;
+ Q_D(QWinRTCameraFlashControl);
+
+ d->initialized = false;
+
+ d->supportedModes.clear();
+ HRESULT hr;
+ hr = QEventDispatcherWinRT::runOnXamlThread([d, controller]() {
+ HRESULT hr;
+ hr = controller->get_FlashControl(&d->flashControl);
+ RETURN_HR_IF_FAILED("Could not access flash control.");
+
+ boolean oldAuto;
+ boolean oldEnabled;
+ // IFlashControl::get_Supported() is only valid for additional
+ // controls (RedEye, etc.) so we have to manually try to set
+ // and reset flash
+ if (SUCCEEDED(d->flashControl->get_Auto(&oldAuto))) {
+ hr = d->flashControl->put_Auto(!oldAuto);
+ if (SUCCEEDED(hr)) {
+ d->flashControl->put_Auto(oldAuto);
+ d->supportedModes.append(QCameraExposure::FlashAuto);
+ }
+ }
+
+ if (SUCCEEDED(d->flashControl->get_Enabled(&oldEnabled))) {
+ hr = d->flashControl->put_Enabled(!oldEnabled);
+ if (SUCCEEDED(hr)) {
+ d->flashControl->put_Enabled(oldEnabled);
+ d->supportedModes.append(QCameraExposure::FlashOff);
+ d->supportedModes.append(QCameraExposure::FlashOn);
+ }
+ }
+
+ boolean val;
+ hr = d->flashControl->get_Supported(&val);
+ if (SUCCEEDED(hr) && val) {
+ hr = d->flashControl->get_RedEyeReductionSupported(&val);
+ if (SUCCEEDED(hr) && val)
+ d->supportedModes.append(QCameraExposure::FlashRedEyeReduction);
+
+ // ### There is no Qt API to actually set the power values.
+ // However query if the camera could theoretically do it
+ hr = d->flashControl->get_PowerSupported(&val);
+ if (SUCCEEDED(hr) && val)
+ d->supportedModes.append(QCameraExposure::FlashManual);
+ }
+
+ return S_OK;
+ });
+ Q_ASSERT_SUCCEEDED(hr);
+ d->initialized = true;
+ setFlashMode(d->currentModes);
+}
+
+QCameraExposure::FlashModes QWinRTCameraFlashControl::flashMode() const
+{
+ Q_D(const QWinRTCameraFlashControl);
+ return d->currentModes;
+}
+
+void QWinRTCameraFlashControl::setFlashMode(QCameraExposure::FlashModes mode)
+{
+ qCDebug(lcMMCamera) << __FUNCTION__ << mode;
+ Q_D(QWinRTCameraFlashControl);
+
+ if (!d->initialized) {
+ d->currentModes = mode;
+ return;
+ }
+
+ if (!isFlashModeSupported(mode))
+ return;
+
+ QEventDispatcherWinRT::runOnXamlThread([d, mode]() {
+ HRESULT hr;
+ if (mode.testFlag(QCameraExposure::FlashAuto)) {
+ hr = d->flashControl->put_Enabled(true);
+ RETURN_OK_IF_FAILED("Could not set flash mode on.");
+ hr = d->flashControl->put_Auto(true);
+ RETURN_OK_IF_FAILED("Could not set flash mode auto.");
+ d->currentModes = QCameraExposure::FlashAuto;
+ } else if (mode.testFlag(QCameraExposure::FlashOn)) {
+ hr = d->flashControl->put_Enabled(true);
+ RETURN_OK_IF_FAILED("Could not set flash mode on.");
+ hr = d->flashControl->put_Auto(false);
+ RETURN_OK_IF_FAILED("Could not disable flash auto mode.");
+ d->currentModes = QCameraExposure::FlashOn;
+ } else if (mode.testFlag(QCameraExposure::FlashRedEyeReduction)) {
+ hr = d->flashControl->put_Enabled(true);
+ RETURN_OK_IF_FAILED("Could not set flash mode on.");
+ hr = d->flashControl->put_RedEyeReduction(true);
+ RETURN_OK_IF_FAILED("Could not set flash mode red eye reduction.");
+ d->currentModes = QCameraExposure::FlashRedEyeReduction;
+ } else {
+ hr = d->flashControl->put_Enabled(false);
+ RETURN_OK_IF_FAILED("Could not set flash mode off.");
+ d->currentModes = QCameraExposure::FlashOff;
+ }
+ return S_OK;
+ });
+}
+
+bool QWinRTCameraFlashControl::isFlashModeSupported(QCameraExposure::FlashModes mode) const
+{
+ Q_D(const QWinRTCameraFlashControl);
+ qCDebug(lcMMCamera) << __FUNCTION__ << mode;
+ return d->initialized ? d->supportedModes.contains(mode) : false;
+}
+
+bool QWinRTCameraFlashControl::isFlashReady() const
+{
+ qCDebug(lcMMCamera) << __FUNCTION__;
+ // No native API to query state
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/winrt/qwinrtcameraflashcontrol.h b/src/plugins/winrt/qwinrtcameraflashcontrol.h
new file mode 100644
index 000000000..335329037
--- /dev/null
+++ b/src/plugins/winrt/qwinrtcameraflashcontrol.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies).
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTCAMERAFLASHCONTROL_H
+#define QWINRTCAMERAFLASHCONTROL_H
+#include <qcameraflashcontrol.h>
+
+#include <wrl.h>
+
+namespace ABI {
+ namespace Windows {
+ namespace Media {
+ namespace Devices {
+ struct IAdvancedVideoCaptureDeviceController2;
+ }
+ }
+ }
+}
+
+QT_BEGIN_NAMESPACE
+
+class QWinRTCameraControl;
+class QWinRTCameraFlashControlPrivate;
+class QWinRTCameraFlashControl : public QCameraFlashControl
+{
+ Q_OBJECT
+public:
+ explicit QWinRTCameraFlashControl(QWinRTCameraControl *parent);
+
+ void initialize(Microsoft::WRL::ComPtr<ABI::Windows::Media::Devices::IAdvancedVideoCaptureDeviceController2> &controller);
+
+ QCameraExposure::FlashModes flashMode() const Q_DECL_OVERRIDE;
+ void setFlashMode(QCameraExposure::FlashModes mode) Q_DECL_OVERRIDE;
+ bool isFlashModeSupported(QCameraExposure::FlashModes mode) const Q_DECL_OVERRIDE;
+
+ bool isFlashReady() const Q_DECL_OVERRIDE;
+
+private:
+ QScopedPointer<QWinRTCameraFlashControlPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QWinRTCameraFlashControl)
+};
+
+#endif // QWINRTCAMERAFLASHCONTROL_H
diff --git a/src/plugins/winrt/qwinrtcamerafocuscontrol.cpp b/src/plugins/winrt/qwinrtcamerafocuscontrol.cpp
index ef637ac37..aeefc9241 100644
--- a/src/plugins/winrt/qwinrtcamerafocuscontrol.cpp
+++ b/src/plugins/winrt/qwinrtcamerafocuscontrol.cpp
@@ -79,7 +79,41 @@ QCameraFocus::FocusModes QWinRTCameraFocusControl::focusMode() const
void QWinRTCameraFocusControl::setFocusMode(QCameraFocus::FocusModes modes)
{
- QMetaObject::invokeMethod(this, "applyFocusMode", Qt::QueuedConnection, Q_ARG(QCameraFocus::FocusModes, modes));
+ Q_D(QWinRTCameraFocusControl);
+ if (d->focusModes == modes)
+ return;
+ QWinRTCameraControl *cameraControl = static_cast<QWinRTCameraControl *>(parent());
+ Q_ASSERT(cameraControl);
+ if (!modes) {
+ cameraControl->emitError(QCamera::InvalidRequestError, QStringLiteral("Can't set empty camera focus modes."));
+ return;
+ }
+ if (!d->focusModeInitialized) {
+ d->focusModes = modes;
+ emit focusModeChanged(modes);
+ return;
+ }
+ if (!isFocusModeSupported(modes)) {
+ cameraControl->emitError(QCamera::NotSupportedFeatureError, QStringLiteral("Unsupported camera focus modes."));
+ return;
+ }
+ if (modes.testFlag(QCameraFocus::ContinuousFocus)) {
+ if (QCameraFocus::FocusPointCustom == d->focusPointMode) {
+ cameraControl->emitError(QCamera::NotSupportedFeatureError,
+ QStringLiteral("Unsupported camera focus modes: ContinuousFocus with FocusPointCustom."));
+ return;
+ } else if (!d->imageCaptureIdle) {
+ cameraControl->emitError(QCamera::NotSupportedFeatureError,
+ QStringLiteral("Can't set ContinuousFocus camera focus mode while capturing image."));
+ return;
+ }
+ }
+ if (!cameraControl->setFocus(modes))
+ return;
+ if (modes.testFlag(QCameraFocus::ContinuousFocus) || d->focusModes.testFlag(QCameraFocus::ContinuousFocus))
+ cameraControl->focus();
+ d->focusModes = modes;
+ emit focusModeChanged(modes);
}
bool QWinRTCameraFocusControl::isFocusModeSupported(QCameraFocus::FocusModes modes) const
@@ -96,7 +130,32 @@ QCameraFocus::FocusPointMode QWinRTCameraFocusControl::focusPointMode() const
void QWinRTCameraFocusControl::setFocusPointMode(QCameraFocus::FocusPointMode mode)
{
- QMetaObject::invokeMethod(this, "applyFocusPointMode", Qt::QueuedConnection, Q_ARG(QCameraFocus::FocusPointMode, mode));
+ Q_D(QWinRTCameraFocusControl);
+ if (d->focusPointMode == mode)
+ return;
+
+ if (!d->focusModeInitialized) {
+ d->focusPointMode = mode;
+ emit focusPointModeChanged(mode);
+ return;
+ }
+ QWinRTCameraControl *cameraControl = static_cast<QWinRTCameraControl *>(parent());
+ Q_ASSERT(cameraControl);
+ if (!d->supportedFocusPointModes.contains(mode)) {
+ cameraControl->emitError(QCamera::NotSupportedFeatureError, QStringLiteral("Unsupported camera point focus mode."));
+ return;
+ }
+ if (QCameraFocus::FocusPointCenter == mode || QCameraFocus::FocusPointAuto == mode)
+ d->focusPoint = QPointF(0.5, 0.5);
+ // Don't apply focus point focus settings if camera is in continuous focus mode
+ if (!d->focusModes.testFlag(QCameraFocus::ContinuousFocus)) {
+ changeFocusCustomPoint(d->focusPoint);
+ } else if (QCameraFocus::FocusPointCustom == mode) {
+ cameraControl->emitError(QCamera::NotSupportedFeatureError, QStringLiteral("Unsupported camera focus modes: ContinuousFocus with FocusPointCustom."));
+ return;
+ }
+ d->focusPointMode = mode;
+ emit focusPointModeChanged(mode);
}
bool QWinRTCameraFocusControl::isFocusPointModeSupported(QCameraFocus::FocusPointMode mode) const
@@ -113,7 +172,20 @@ QPointF QWinRTCameraFocusControl::customFocusPoint() const
void QWinRTCameraFocusControl::setCustomFocusPoint(const QPointF &point)
{
- QMetaObject::invokeMethod(this, "applyFocusCustomPoint", Qt::QueuedConnection, Q_ARG(const QPointF, point));
+ Q_D(QWinRTCameraFocusControl);
+ if (d->focusPointMode != QCameraFocus::FocusPointCustom) {
+ QWinRTCameraControl *cameraControl = static_cast<QWinRTCameraControl *>(parent());
+ Q_ASSERT(cameraControl);
+ cameraControl->emitError(QCamera::InvalidRequestError, QStringLiteral("Custom focus point can be set only in FocusPointCustom focus mode."));
+ return;
+ }
+ if (d->focusPoint == point)
+ return;
+ if (changeFocusCustomPoint(point)) {
+ d->focusPoint = point;
+ emit customFocusPointChanged(point);
+ }
+
}
QCameraFocusZoneList QWinRTCameraFocusControl::focusZones() const
@@ -176,92 +248,6 @@ void QWinRTCameraFocusControl::imageCaptureQueueChanged(bool isEmpty)
d->imageCaptureIdle = isEmpty;
}
-void QWinRTCameraFocusControl::applyFocusCustomPoint(const QPointF &point)
-{
- Q_D(QWinRTCameraFocusControl);
- if (d->focusPointMode != QCameraFocus::FocusPointCustom) {
- QWinRTCameraControl *cameraControl = static_cast<QWinRTCameraControl *>(parent());
- Q_ASSERT(cameraControl);
- cameraControl->emitError(QCamera::InvalidRequestError, QStringLiteral("Custom focus point can be set only in FocusPointCustom focus mode."));
- return;
- }
- if (d->focusPoint == point)
- return;
- if (changeFocusCustomPoint(point)) {
- d->focusPoint = point;
- emit customFocusPointChanged(point);
- }
-}
-
-void QWinRTCameraFocusControl::applyFocusMode(QCameraFocus::FocusModes modes)
-{
- Q_D(QWinRTCameraFocusControl);
- if (d->focusModes == modes)
- return;
- QWinRTCameraControl *cameraControl = static_cast<QWinRTCameraControl *>(parent());
- Q_ASSERT(cameraControl);
- if (!modes) {
- cameraControl->emitError(QCamera::InvalidRequestError, QStringLiteral("Can't set empty camera focus modes."));
- return;
- }
- if (!d->focusModeInitialized) {
- d->focusModes = modes;
- emit focusModeChanged(modes);
- return;
- }
- if (!isFocusModeSupported(modes)) {
- cameraControl->emitError(QCamera::NotSupportedFeatureError, QStringLiteral("Unsupported camera focus modes."));
- return;
- }
- if (modes.testFlag(QCameraFocus::ContinuousFocus)) {
- if (QCameraFocus::FocusPointCustom == d->focusPointMode) {
- cameraControl->emitError(QCamera::NotSupportedFeatureError,
- QStringLiteral("Unsupported camera focus modes: ContinuousFocus with FocusPointCustom."));
- return;
- } else if (!d->imageCaptureIdle) {
- cameraControl->emitError(QCamera::NotSupportedFeatureError,
- QStringLiteral("Can't set ContinuousFocus camera focus mode while capturing image."));
- return;
- }
- }
- if (!cameraControl->setFocus(modes))
- return;
- if (modes.testFlag(QCameraFocus::ContinuousFocus) || d->focusModes.testFlag(QCameraFocus::ContinuousFocus))
- cameraControl->focus();
- d->focusModes = modes;
- emit focusModeChanged(modes);
-}
-
-void QWinRTCameraFocusControl::applyFocusPointMode(QCameraFocus::FocusPointMode mode)
-{
- Q_D(QWinRTCameraFocusControl);
- if (d->focusPointMode == mode)
- return;
-
- if (!d->focusModeInitialized) {
- d->focusPointMode = mode;
- emit focusPointModeChanged(mode);
- return;
- }
- QWinRTCameraControl *cameraControl = static_cast<QWinRTCameraControl *>(parent());
- Q_ASSERT(cameraControl);
- if (!d->supportedFocusPointModes.contains(mode)) {
- cameraControl->emitError(QCamera::NotSupportedFeatureError, QStringLiteral("Unsupported camera point focus mode."));
- return;
- }
- if (QCameraFocus::FocusPointCenter == mode || QCameraFocus::FocusPointAuto == mode)
- d->focusPoint = QPointF(0.5, 0.5);
- // Don't apply focus point focus settings if camera is in continuous focus mode
- if (!d->focusModes.testFlag(QCameraFocus::ContinuousFocus)) {
- changeFocusCustomPoint(d->focusPoint);
- } else if (QCameraFocus::FocusPointCustom == mode) {
- cameraControl->emitError(QCamera::NotSupportedFeatureError, QStringLiteral("Unsupported camera focus modes: ContinuousFocus with FocusPointCustom."));
- return;
- }
- d->focusPointMode = mode;
- emit focusPointModeChanged(mode);
-}
-
bool QWinRTCameraFocusControl::changeFocusCustomPoint(const QPointF &point)
{
Q_D(QWinRTCameraFocusControl);
diff --git a/src/plugins/winrt/qwinrtcamerafocuscontrol.h b/src/plugins/winrt/qwinrtcamerafocuscontrol.h
index 6ec2ea67a..0a8c0afcf 100644
--- a/src/plugins/winrt/qwinrtcamerafocuscontrol.h
+++ b/src/plugins/winrt/qwinrtcamerafocuscontrol.h
@@ -68,9 +68,6 @@ private slots:
void imageCaptureQueueChanged(bool isEmpty);
private:
- Q_INVOKABLE void applyFocusCustomPoint(const QPointF &point);
- Q_INVOKABLE void applyFocusMode(QCameraFocus::FocusModes modes);
- Q_INVOKABLE void applyFocusPointMode(QCameraFocus::FocusPointMode mode);
bool changeFocusCustomPoint(const QPointF &point);
QScopedPointer<QWinRTCameraFocusControlPrivate> d_ptr;
diff --git a/src/plugins/winrt/qwinrtcameraservice.cpp b/src/plugins/winrt/qwinrtcameraservice.cpp
index f76edae51..d0327a708 100644
--- a/src/plugins/winrt/qwinrtcameraservice.cpp
+++ b/src/plugins/winrt/qwinrtcameraservice.cpp
@@ -50,6 +50,7 @@
#include <QtMultimedia/QVideoRendererControl>
#include <QtMultimedia/QVideoDeviceSelectorControl>
#include <QtMultimedia/QImageEncoderControl>
+#include <QtMultimedia/QCameraFlashControl>
#include <QtMultimedia/QCameraFocusControl>
#include <QtMultimedia/QCameraLocksControl>
#include <QtMultimedia/QMediaVideoProbeControl>
@@ -98,6 +99,9 @@ QMediaControl *QWinRTCameraService::requestControl(const char *name)
if (qstrcmp(name, QImageEncoderControl_iid) == 0)
return d->cameraControl->imageEncoderControl();
+ if (qstrcmp(name, QCameraFlashControl_iid) == 0)
+ return d->cameraControl->cameraFlashControl();
+
if (qstrcmp(name, QCameraFocusControl_iid) == 0)
return d->cameraControl->cameraFocusControl();
diff --git a/src/plugins/winrt/winrt.pro b/src/plugins/winrt/winrt.pro
index 87e44cce2..940064f46 100644
--- a/src/plugins/winrt/winrt.pro
+++ b/src/plugins/winrt/winrt.pro
@@ -6,6 +6,7 @@ LIBS += -lmfplat -lmfuuid -loleaut32 -ld3d11 -lruntimeobject
HEADERS += \
qwinrtabstractvideorenderercontrol.h \
qwinrtcameracontrol.h \
+ qwinrtcameraflashcontrol.h \
qwinrtcamerafocuscontrol.h \
qwinrtcameraimagecapturecontrol.h \
qwinrtcamerainfocontrol.h \
@@ -23,6 +24,7 @@ HEADERS += \
SOURCES += \
qwinrtabstractvideorenderercontrol.cpp \
qwinrtcameracontrol.cpp \
+ qwinrtcameraflashcontrol.cpp \
qwinrtcamerafocuscontrol.cpp \
qwinrtcameraimagecapturecontrol.cpp \
qwinrtcamerainfocontrol.cpp \