summaryrefslogtreecommitdiffstats
path: root/src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp
diff options
context:
space:
mode:
authorPeng Wu <peng.wu@intopalo.com>2015-07-29 13:00:03 +0300
committerAndrew Knight <andrew.knight@intopalo.com>2015-08-10 12:12:52 +0000
commit129b06ba77e451c08778badcd54cbaf193d195bc (patch)
tree052b20dca9571bb5291445378d0a4ff29c8874a2 /src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp
parent5cec451c10e73785c95fb236cbae7205a9a661d0 (diff)
winrt: Add camera video probe controls
[ChangLog][multimedia][winrt] The WinRT backend now supports QVideoProbes on camera objects. Task-number: QTBUG-46228 Change-Id: I7850c5ec6f61e5824064d4be8afc8a0b55d05806 Reviewed-by: Andrew Knight <andrew.knight@intopalo.com>
Diffstat (limited to 'src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp')
-rw-r--r--src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp152
1 files changed, 142 insertions, 10 deletions
diff --git a/src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp b/src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp
index 4878c55c9..6c5575a17 100644
--- a/src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp
+++ b/src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp
@@ -39,6 +39,7 @@
#include <QtCore/qfunctions_winrt.h>
#include <QtCore/QSize>
#include <QtCore/QVector>
+#include <QVideoFrame>
#include <d3d11.h>
#include <mfapi.h>
@@ -47,6 +48,60 @@ using namespace Microsoft::WRL;
QT_BEGIN_NAMESPACE
+class QWinRTCameraVideoBuffer : public QAbstractVideoBuffer
+{
+public:
+ QWinRTCameraVideoBuffer(IMF2DBuffer *buffer, int size)
+ : QAbstractVideoBuffer(NoHandle)
+ , currentMode(NotMapped)
+ , buffer(buffer)
+ , size(size)
+ {
+ }
+
+ ~QWinRTCameraVideoBuffer()
+ {
+ unmap();
+ }
+
+ MapMode mapMode() const Q_DECL_OVERRIDE
+ {
+ return currentMode;
+ }
+
+ uchar *map(MapMode mode, int *numBytes, int *bytesPerLine) Q_DECL_OVERRIDE
+ {
+ if (currentMode != NotMapped || mode == NotMapped)
+ return nullptr;
+
+ BYTE *bytes;
+ LONG stride;
+ HRESULT hr = buffer->Lock2D(&bytes, &stride);
+ RETURN_IF_FAILED("Failed to lock camera frame buffer", nullptr);
+
+ if (bytesPerLine)
+ *bytesPerLine = stride;
+ if (numBytes)
+ *numBytes = size;
+ currentMode = mode;
+ return bytes;
+ }
+
+ void unmap() Q_DECL_OVERRIDE
+ {
+ if (currentMode == NotMapped)
+ return;
+ HRESULT hr = buffer->Unlock2D();
+ RETURN_VOID_IF_FAILED("Failed to unlock camera frame buffer");
+ currentMode = NotMapped;
+ }
+
+private:
+ ComPtr<IMF2DBuffer> buffer;
+ MapMode currentMode;
+ int size;
+};
+
class D3DVideoBlitter
{
public:
@@ -143,11 +198,52 @@ public:
ComPtr<IMF2DBuffer> buffers[CAMERA_SAMPLE_QUEUE_SIZE];
QAtomicInteger<quint16> writeIndex;
QAtomicInteger<quint16> readIndex;
+ QVideoFrame::PixelFormat cameraSampleformat;
+ int cameraSampleSize;
+ uint videoProbesCounter;
+ bool getCameraSampleInfo(const ComPtr<IMF2DBuffer> &buffer);
+ ComPtr<IMF2DBuffer> dequeueBuffer();
};
+bool QWinRTCameraVideoRendererControlPrivate::getCameraSampleInfo(const ComPtr<IMF2DBuffer> &buffer)
+{
+ ComPtr<ID3D11Texture2D> sourceTexture;
+ ComPtr<IMFDXGIBuffer> dxgiBuffer;
+ HRESULT 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");
+ cameraSampleformat = QVideoFrame::Format_Invalid;
+ return false;
+ }
+ D3D11_TEXTURE2D_DESC desc;
+ sourceTexture->GetDesc(&desc);
+ switch (desc.Format) {
+ case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+ cameraSampleformat = QVideoFrame::Format_ARGB32;
+ break;
+ case DXGI_FORMAT_NV12:
+ cameraSampleformat = QVideoFrame::Format_NV12;
+ break;
+ default:
+ cameraSampleformat = QVideoFrame::Format_Invalid;
+ qErrnoWarning("Unsupported camera probe format.");
+ return false;
+ }
+ DWORD pcbLength;
+ hr = buffer->GetContiguousLength(&pcbLength);
+ Q_ASSERT_SUCCEEDED(hr);
+ cameraSampleSize = pcbLength;
+ return true;
+}
+
QWinRTCameraVideoRendererControl::QWinRTCameraVideoRendererControl(const QSize &size, QObject *parent)
: QWinRTAbstractVideoRendererControl(size, parent), d_ptr(new QWinRTCameraVideoRendererControlPrivate)
{
+ Q_D(QWinRTCameraVideoRendererControl);
+ d->cameraSampleformat = QVideoFrame::Format_User;
+ d->videoProbesCounter = 0;
}
QWinRTCameraVideoRendererControl::~QWinRTCameraVideoRendererControl()
@@ -158,22 +254,15 @@ QWinRTCameraVideoRendererControl::~QWinRTCameraVideoRendererControl()
bool QWinRTCameraVideoRendererControl::render(ID3D11Texture2D *target)
{
Q_D(QWinRTCameraVideoRendererControl);
-
- const quint16 readIndex = d->readIndex;
- if (readIndex == d->writeIndex) {
+ ComPtr<IMF2DBuffer> buffer = d->dequeueBuffer();
+ if (!buffer) {
emit bufferRequested();
return false;
}
- HRESULT hr;
- 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;
- hr = buffer.As(&dxgiBuffer);
+ HRESULT hr = buffer.As(&dxgiBuffer);
Q_ASSERT_SUCCEEDED(hr);
hr = dxgiBuffer->GetResource(IID_PPV_ARGS(&sourceTexture));
if (FAILED(hr)) {
@@ -196,11 +285,41 @@ void QWinRTCameraVideoRendererControl::queueBuffer(IMF2DBuffer *buffer)
{
Q_D(QWinRTCameraVideoRendererControl);
Q_ASSERT(buffer);
+
+ if (d->videoProbesCounter > 0) {
+ if (d->cameraSampleformat == QVideoFrame::Format_User)
+ d->getCameraSampleInfo(buffer);
+
+ if (d->cameraSampleformat != QVideoFrame::Format_Invalid) {
+ QWinRTCameraVideoBuffer *videoBuffer = new QWinRTCameraVideoBuffer(buffer, d->cameraSampleSize);
+ QVideoFrame frame(videoBuffer, size(), d->cameraSampleformat);
+ emit videoFrameProbed(frame);
+ }
+ }
+
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;
+
+ if (!surface()) {
+ d->dequeueBuffer();
+ emit bufferRequested();
+ }
+}
+
+ComPtr<IMF2DBuffer> QWinRTCameraVideoRendererControlPrivate::dequeueBuffer()
+{
+ const quint16 currentReadIndex = readIndex;
+ if (currentReadIndex == writeIndex)
+ return nullptr;
+
+ ComPtr<IMF2DBuffer> buffer = buffers[currentReadIndex];
+ Q_ASSERT(buffer);
+ buffers[currentReadIndex].Reset();
+ readIndex = (currentReadIndex + 1) % CAMERA_SAMPLE_QUEUE_SIZE;
+ return buffer;
}
void QWinRTCameraVideoRendererControl::discardBuffers()
@@ -211,4 +330,17 @@ void QWinRTCameraVideoRendererControl::discardBuffers()
buffer.Reset();
}
+void QWinRTCameraVideoRendererControl::incrementProbe()
+{
+ Q_D(QWinRTCameraVideoRendererControl);
+ ++d->videoProbesCounter;
+}
+
+void QWinRTCameraVideoRendererControl::decrementProbe()
+{
+ Q_D(QWinRTCameraVideoRendererControl);
+ Q_ASSERT(d->videoProbesCounter > 0);
+ --d->videoProbesCounter;
+}
+
QT_END_NAMESPACE