From 61033aa420b4d34107e3cc67e8751506bc4ab745 Mon Sep 17 00:00:00 2001 From: Peng Wu Date: Wed, 22 Apr 2015 12:42:38 +0300 Subject: winrt: fix camera sample queue thread safety Replace sample buffer QVector with C array to avoid reallocations. The resource needs to be protected, so use atomic indexes to prevent writing into the same array element that is being read. Task-number: QTBUG-45667 Change-Id: Ifd30dd128765ea4794fe8614f25ef596bba891ee Reviewed-by: Andrew Knight Reviewed-by: Maurice Kalinowski --- .../winrt/qwinrtcameravideorenderercontrol.cpp | 23 +++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp b/src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp index 74afabaf3..bcae8a201 100644 --- a/src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp +++ b/src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp @@ -132,11 +132,14 @@ private: ComPtr m_outputView; }; +#define CAMERA_SAMPLE_QUEUE_SIZE 5 class QWinRTCameraVideoRendererControlPrivate { public: QScopedPointer blitter; - QVector> buffers; + ComPtr buffers[CAMERA_SAMPLE_QUEUE_SIZE]; + QAtomicInteger writeIndex; + QAtomicInteger readIndex; }; QWinRTCameraVideoRendererControl::QWinRTCameraVideoRendererControl(const QSize &size, QObject *parent) @@ -153,13 +156,17 @@ bool QWinRTCameraVideoRendererControl::render(ID3D11Texture2D *target) { Q_D(QWinRTCameraVideoRendererControl); - if (d->buffers.isEmpty()) { + const quint16 readIndex = d->readIndex; + if (readIndex == d->writeIndex) { emit bufferRequested(); return false; } HRESULT hr; - ComPtr buffer = d->buffers.takeFirst(); + ComPtr buffer = d->buffers[readIndex]; + Q_ASSERT(buffer); + d->buffers[readIndex].Reset(); + d->readIndex = (readIndex + 1) % CAMERA_SAMPLE_QUEUE_SIZE; ComPtr sourceTexture; ComPtr dxgiBuffer; @@ -186,11 +193,17 @@ void QWinRTCameraVideoRendererControl::queueBuffer(IMF2DBuffer *buffer) { Q_D(QWinRTCameraVideoRendererControl); Q_ASSERT(buffer); - d->buffers.append(buffer); + const quint16 writeIndex = (d->writeIndex + 1) % CAMERA_SAMPLE_QUEUE_SIZE; + if (d->readIndex == writeIndex) // Drop new sample if queue is full + return; + d->buffers[d->writeIndex] = buffer; + d->writeIndex = writeIndex; } void QWinRTCameraVideoRendererControl::discardBuffers() { Q_D(QWinRTCameraVideoRendererControl); - d->buffers.clear(); + d->writeIndex = d->readIndex = 0; + for (ComPtr &buffer : d->buffers) + buffer.Reset(); } -- cgit v1.2.3