From be0a231be4ed28474271fb29f44e1eb3270f35b7 Mon Sep 17 00:00:00 2001 From: Peng Wu Date: Wed, 15 Apr 2015 17:55:49 +0300 Subject: winrt: fix camera preview on Lumia 630 Certain devices give black frames when blitting to the target texture for image preview. However, a workaround has been found that simply mapping the buffer forces the frames to be rendered properly. As this degrades performance on devices with hardware buffers, a blacklist is introduced to specify which devices require this workaround. Task-number: QTBUG-44838 Change-Id: I137a1dc4e5126e7cf9ee00cb2d7e7722bf917efa Reviewed-by: Andrew Knight --- src/plugins/winrt/qwinrtcameracontrol.cpp | 42 ++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/plugins/winrt/qwinrtcameracontrol.cpp b/src/plugins/winrt/qwinrtcameracontrol.cpp index 5b19d3a77..e8f433d45 100644 --- a/src/plugins/winrt/qwinrtcameracontrol.cpp +++ b/src/plugins/winrt/qwinrtcameracontrol.cpp @@ -48,6 +48,11 @@ #include #include +#ifdef Q_OS_WINPHONE +#include +using namespace ABI::Windows::Security::ExchangeActiveSyncProvisioning; +#endif + using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; using namespace ABI::Windows::Devices::Enumeration; @@ -85,9 +90,21 @@ private: class MediaStream : public RuntimeClass, IMFStreamSink, IMFMediaEventGenerator, IMFMediaTypeHandler> { + enum Flags { NoFlag = 0, BufferLockRequired = 1 }; + + template + static Flags bufferLockRequired(const wchar_t (&blackListName)[n], const HString &deviceModel) + { + quint32 deviceNameLength; + const wchar_t *deviceName = deviceModel.GetRawBuffer(&deviceNameLength); + if (n - 1 <= deviceNameLength && !wmemcmp(blackListName, deviceName, n - 1)) + return BufferLockRequired; + return NoFlag; + } + public: MediaStream(IMFMediaType *type, IMFMediaSink *mediaSink, QWinRTCameraVideoRendererControl *videoRenderer) - : m_type(type), m_sink(mediaSink), m_videoRenderer(videoRenderer) + : m_type(type), m_sink(mediaSink), m_videoRenderer(videoRenderer), m_flags(NoFlag) { Q_ASSERT(m_videoRenderer); @@ -98,6 +115,18 @@ public: Q_ASSERT_SUCCEEDED(hr); hr = MFAllocateSerialWorkQueue(MFASYNC_CALLBACK_QUEUE_STANDARD, &m_workQueueId); Q_ASSERT_SUCCEEDED(hr); + +#ifdef Q_OS_WINPHONE + // Workaround for certain devices which fail to blit software buffers without first mapping them + ComPtr deviceInfo; + hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Security_ExchangeActiveSyncProvisioning_EasClientDeviceInformation).Get(), + &deviceInfo); + Q_ASSERT_SUCCEEDED(hr); + HString deviceModel; + hr = deviceInfo->get_SystemSku(deviceModel.GetAddressOf()); + Q_ASSERT_SUCCEEDED(hr); + m_flags |= bufferLockRequired(L"NOKIA RM-976", deviceModel); +#endif } ~MediaStream() @@ -171,6 +200,16 @@ public: hr = buffer.As(&buffer2d); RETURN_HR_IF_FAILED("Failed to cast camera sample buffer to 2D buffer"); +#ifdef Q_OS_WINPHONE + if (m_flags & BufferLockRequired) { + BYTE *bytes; + LONG stride; + hr = buffer2d->Lock2D(&bytes, &stride); + RETURN_HR_IF_FAILED("Failed to lock camera frame buffer"); + hr = buffer2d->Unlock2D(); + RETURN_HR_IF_FAILED("Failed to unlock camera frame buffer"); + } +#endif m_pendingSamples.deref(); m_videoRenderer->queueBuffer(buffer2d.Get()); @@ -244,6 +283,7 @@ private: QWinRTCameraVideoRendererControl *m_videoRenderer; QAtomicInt m_pendingSamples; + quint32 m_flags; }; class MediaSink : public RuntimeClass, IMediaExtension, IMFMediaSink, IMFClockStateSink> -- cgit v1.2.3