diff options
author | Peng Wu <peng.wu@intopalo.com> | 2015-04-22 12:42:38 +0300 |
---|---|---|
committer | PengWu <peng.wu@intopalo.com> | 2015-04-23 07:10:28 +0000 |
commit | 61033aa420b4d34107e3cc67e8751506bc4ab745 (patch) | |
tree | 8ad4312cf41d31a1d20468644b579a67dc87bd8d | |
parent | d44f5734bf945b9b3d57f2bc9c73243343c21518 (diff) |
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 <qt@panimo.net>
Reviewed-by: Maurice Kalinowski <maurice.kalinowski@theqtcompany.com>
-rw-r--r-- | src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp | 23 |
1 files 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<ID3D11VideoProcessorOutputView> m_outputView; }; +#define CAMERA_SAMPLE_QUEUE_SIZE 5 class QWinRTCameraVideoRendererControlPrivate { public: QScopedPointer<D3DVideoBlitter> blitter; - QVector<ComPtr<IMF2DBuffer>> buffers; + ComPtr<IMF2DBuffer> buffers[CAMERA_SAMPLE_QUEUE_SIZE]; + QAtomicInteger<quint16> writeIndex; + QAtomicInteger<quint16> 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<IMF2DBuffer> buffer = d->buffers.takeFirst(); + ComPtr<IMF2DBuffer> buffer = d->buffers[readIndex]; + Q_ASSERT(buffer); + d->buffers[readIndex].Reset(); + d->readIndex = (readIndex + 1) % CAMERA_SAMPLE_QUEUE_SIZE; ComPtr<ID3D11Texture2D> sourceTexture; ComPtr<IMFDXGIBuffer> 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<IMF2DBuffer> &buffer : d->buffers) + buffer.Reset(); } |