summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSamuel Nevala <samuel.nevala@intopalo.com>2015-10-14 10:48:00 +0300
committerSamuel Nevala <samuel.nevala@intopalo.com>2015-10-15 06:19:14 +0000
commit787dcd9e4d40d9d59b90544e4c4bdea13ef532b8 (patch)
tree0650f73eaa9794265c43e69c38ce899e91b8cfcc /src
parentd50a09965ae53e02caabdbcf4994ed9bc0ea3293 (diff)
winrt: Prevent camera device from being suspended.
On certain Lumia devices video buffer gets page locked when camera is stopped. Subsequent call to video frame map/unmap leads to camera device suspension. As a fix delay camera unload until all mapped video frames are unmapped and return early from video frame map when camera is not active. Task-Id: QTBUG-48672 Change-Id: If547b9d430727bbe0e12cd8c07a30aeff81d13e3 Reviewed-by: Andrew Knight <andrew.knight@intopalo.com>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/winrt/qwinrtcameracontrol.cpp26
-rw-r--r--src/plugins/winrt/qwinrtcameracontrol.h2
-rw-r--r--src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp21
3 files changed, 45 insertions, 4 deletions
diff --git a/src/plugins/winrt/qwinrtcameracontrol.cpp b/src/plugins/winrt/qwinrtcameracontrol.cpp
index 3489048d8..0db4cdb0d 100644
--- a/src/plugins/winrt/qwinrtcameracontrol.cpp
+++ b/src/plugins/winrt/qwinrtcameracontrol.cpp
@@ -524,6 +524,8 @@ public:
QPointer<QWinRTImageEncoderControl> imageEncoderControl;
QPointer<QWinRTCameraFocusControl> cameraFocusControl;
QPointer<QWinRTCameraLocksControl> cameraLocksControl;
+ QAtomicInt framesMapped;
+ QEventLoop *delayClose;
};
QWinRTCameraControl::QWinRTCameraControl(QObject *parent)
@@ -531,6 +533,7 @@ QWinRTCameraControl::QWinRTCameraControl(QObject *parent)
{
Q_D(QWinRTCameraControl);
+ d->delayClose = nullptr;
d->state = QCamera::UnloadedState;
d->status = QCamera::UnloadedStatus;
d->captureMode = QCamera::CaptureStillImage;
@@ -612,6 +615,14 @@ void QWinRTCameraControl::setState(QCamera::State state)
case QCamera::UnloadedState: {
// Stop the camera if it is running (transition to LoadedState)
if (d->status == QCamera::ActiveStatus) {
+ if (d->framesMapped > 0) {
+ qWarning("%d QVideoFrame(s) mapped when closing down camera. Camera will wait for unmap before closing down.",
+ d->framesMapped);
+ if (!d->delayClose)
+ d->delayClose = new QEventLoop(this);
+ d->delayClose->exec();
+ }
+
ComPtr<IAsyncAction> op;
hr = d->capturePreview->StopPreviewAsync(&op);
RETURN_VOID_AND_EMIT_ERROR("Failed to stop camera preview");
@@ -1208,6 +1219,21 @@ bool QWinRTCameraControl::unlockFocus()
#endif // !Q_OS_WINPHONE
+void QWinRTCameraControl::frameMapped()
+{
+ Q_D(QWinRTCameraControl);
+ ++d->framesMapped;
+}
+
+void QWinRTCameraControl::frameUnmapped()
+{
+ Q_D(QWinRTCameraControl);
+ --d->framesMapped;
+ Q_ASSERT(d->framesMapped >= 0);
+ if (!d->framesMapped && d->delayClose && d->delayClose->isRunning())
+ d->delayClose->exit();
+}
+
HRESULT QWinRTCameraControl::onCaptureFailed(IMediaCapture *, IMediaCaptureFailedEventArgs *args)
{
HRESULT hr;
diff --git a/src/plugins/winrt/qwinrtcameracontrol.h b/src/plugins/winrt/qwinrtcameracontrol.h
index ac1c922a4..758ecb556 100644
--- a/src/plugins/winrt/qwinrtcameracontrol.h
+++ b/src/plugins/winrt/qwinrtcameracontrol.h
@@ -99,6 +99,8 @@ public:
void emitError(int errorCode, const QString &errorString);
bool lockFocus();
bool unlockFocus();
+ void frameMapped();
+ void frameUnmapped();
private slots:
void onBufferRequested();
diff --git a/src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp b/src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp
index 7afef7669..7313ae7a2 100644
--- a/src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp
+++ b/src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp
@@ -38,6 +38,7 @@
#include <QtCore/qfunctions_winrt.h>
#include <QtCore/QSize>
+#include <QtCore/QPointer>
#include <QtCore/QVector>
#include <QVideoFrame>
@@ -45,6 +46,8 @@
#include <mfapi.h>
#include <wrl.h>
+#include "qwinrtcameracontrol.h"
+
#ifdef Q_OS_WINPHONE
#include <Windows.Security.ExchangeActiveSyncProvisioning.h>
using namespace ABI::Windows::Security::ExchangeActiveSyncProvisioning;
@@ -68,12 +71,14 @@ static bool blacklisted(const wchar_t (&blackListName)[n], const HString &device
class QWinRTCameraVideoBuffer : public QAbstractVideoBuffer
{
public:
- QWinRTCameraVideoBuffer(IMF2DBuffer *buffer, int size)
+ QWinRTCameraVideoBuffer(IMF2DBuffer *buffer, int size, QWinRTCameraControl *control)
: QAbstractVideoBuffer(NoHandle)
, currentMode(NotMapped)
, buffer(buffer)
, size(size)
+ , control(control)
{
+ Q_ASSERT(control);
}
~QWinRTCameraVideoBuffer()
@@ -88,13 +93,14 @@ public:
uchar *map(MapMode mode, int *numBytes, int *bytesPerLine) Q_DECL_OVERRIDE
{
- if (currentMode != NotMapped || mode == NotMapped)
+ if (currentMode != NotMapped || mode == NotMapped || control && control->state() != QCamera::ActiveState)
return nullptr;
BYTE *bytes;
LONG stride;
HRESULT hr = buffer->Lock2D(&bytes, &stride);
RETURN_IF_FAILED("Failed to lock camera frame buffer", nullptr);
+ control->frameMapped();
if (bytesPerLine)
*bytesPerLine = stride;
@@ -111,12 +117,15 @@ public:
HRESULT hr = buffer->Unlock2D();
RETURN_VOID_IF_FAILED("Failed to unlock camera frame buffer");
currentMode = NotMapped;
+ if (control)
+ control->frameUnmapped();
}
private:
ComPtr<IMF2DBuffer> buffer;
MapMode currentMode;
int size;
+ QPointer<QWinRTCameraControl> control;
};
class D3DVideoBlitter
@@ -331,7 +340,9 @@ bool QWinRTCameraVideoRendererControl::dequeueFrame(QVideoFrame *frame)
return false;
}
- QWinRTCameraVideoBuffer *videoBuffer = new QWinRTCameraVideoBuffer(buffer.Get(), d->cameraSampleSize);
+ QWinRTCameraVideoBuffer *videoBuffer = new QWinRTCameraVideoBuffer(buffer.Get(),
+ d->cameraSampleSize,
+ static_cast<QWinRTCameraControl *>(parent()));
*frame = QVideoFrame(videoBuffer, size(), d->cameraSampleformat);
emit bufferRequested();
@@ -350,7 +361,9 @@ void QWinRTCameraVideoRendererControl::queueBuffer(IMF2DBuffer *buffer)
}
if (d->videoProbesCounter > 0 && d->cameraSampleformat != QVideoFrame::Format_Invalid) {
- QWinRTCameraVideoBuffer *videoBuffer = new QWinRTCameraVideoBuffer(buffer, d->cameraSampleSize);
+ QWinRTCameraVideoBuffer *videoBuffer = new QWinRTCameraVideoBuffer(buffer,
+ d->cameraSampleSize,
+ static_cast<QWinRTCameraControl *>(parent()));
QVideoFrame frame(videoBuffer, size(), d->cameraSampleformat);
emit videoFrameProbed(frame);
}