diff --git a/src/gsttools/qgstvideorenderersink.cpp b/src/gsttools/qgstvideorenderersink.cpp
index f66095a7d72ec151f2755d4fc2bd0c81858fa835..4c73c26a30abe761cd47d7250ff281300400298f 100644
--- a/src/gsttools/qgstvideorenderersink.cpp
+++ b/src/gsttools/qgstvideorenderersink.cpp
@@ -247,13 +247,11 @@ GstFlowReturn QVideoSurfaceGstDelegate::render(GstBuffer *buffer)
     m_renderReturn = GST_FLOW_OK;
     m_renderBuffer = buffer;
 
-    GstFlowReturn flowReturn = waitForAsyncEvent(&locker, &m_renderCondition, 300)
-                                                ? m_renderReturn
-                                                : GST_FLOW_ERROR;
+    waitForAsyncEvent(&locker, &m_renderCondition, 300);
 
     m_renderBuffer = 0;
 
-    return flowReturn;
+    return m_renderReturn;
 }
 
 bool QVideoSurfaceGstDelegate::event(QEvent *event)
diff --git a/src/plugins/qnx/mediaplayer/mediaplayer.pri b/src/plugins/qnx/mediaplayer/mediaplayer.pri
index 0871f34bc7588006fa0e725a839e2ee3aae6b437..f1b51a06e257c48452307bcaaa48458e7e6f4dfd 100644
--- a/src/plugins/qnx/mediaplayer/mediaplayer.pri
+++ b/src/plugins/qnx/mediaplayer/mediaplayer.pri
@@ -9,7 +9,8 @@ HEADERS += \
     $$PWD/mmrendererplayervideorenderercontrol.h \
     $$PWD/mmrendererutil.h \
     $$PWD/mmrenderervideowindowcontrol.h \
-    $$PWD/ppsmediaplayercontrol.h
+    $$PWD/mmreventmediaplayercontrol.h \
+    $$PWD/mmreventthread.h
 SOURCES += \
     $$PWD/mmrendereraudiorolecontrol.cpp \
     $$PWD/mmrenderermediaplayercontrol.cpp \
@@ -19,6 +20,7 @@ SOURCES += \
     $$PWD/mmrendererplayervideorenderercontrol.cpp \
     $$PWD/mmrendererutil.cpp \
     $$PWD/mmrenderervideowindowcontrol.cpp \
-    $$PWD/ppsmediaplayercontrol.cpp
+    $$PWD/mmreventmediaplayercontrol.cpp \
+    $$PWD/mmreventthread.cpp
 
 QMAKE_USE += mmrenderer pps
diff --git a/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp b/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp
index 0350958de3375afac106f0725523304047db9f9b..83e24dc67ce9eade89bc2f00b48ba47e9549ee50 100644
--- a/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp
+++ b/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp
@@ -59,14 +59,14 @@ static int idCounter = 0;
 
 MmRendererMediaPlayerControl::MmRendererMediaPlayerControl(QObject *parent)
     : QMediaPlayerControl(parent),
-      m_connection(0),
       m_context(0),
+      m_id(-1),
+      m_connection(0),
       m_audioId(-1),
       m_state(QMediaPlayer::StoppedState),
       m_volume(100),
       m_muted(false),
       m_rate(1),
-      m_id(-1),
       m_position(0),
       m_mediaStatus(QMediaPlayer::NoMedia),
       m_playAfterMediaLoaded(false),
@@ -106,7 +106,7 @@ void MmRendererMediaPlayerControl::openConnection()
         return;
     }
 
-    startMonitoring(m_id, m_contextName);
+    startMonitoring();
 }
 
 void MmRendererMediaPlayerControl::handleMmStopped()
@@ -456,11 +456,6 @@ void MmRendererMediaPlayerControl::continueLoadMedia()
         play();
 }
 
-QString MmRendererMediaPlayerControl::contextName() const
-{
-    return m_contextName;
-}
-
 MmRendererVideoWindowControl *MmRendererMediaPlayerControl::videoWindowControl() const
 {
     return m_videoWindowControl;
diff --git a/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.h b/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.h
index 655570656392ee8c803e0113896e48b3d8be70c9..cff536f4d8847ae92cb3e6b377823dc0932d1393 100644
--- a/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.h
+++ b/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.h
@@ -106,10 +106,9 @@ public:
     void setAudioRoleControl(MmRendererAudioRoleControl *audioRoleControl);
 
 protected:
-    virtual void startMonitoring(int contextId, const QString &contextName) = 0;
+    virtual void startMonitoring() = 0;
     virtual void stopMonitoring() = 0;
 
-    QString contextName() const;
     void openConnection();
     void emitMmError(const QString &msg);
     void emitPError(const QString &msg);
@@ -121,6 +120,10 @@ protected:
     // must be called from subclass dtors (calls virtual function stopMonitoring())
     void destroy();
 
+    mmr_context_t *m_context;
+    int m_id;
+    QString m_contextName;
+
 private Q_SLOTS:
     void continueLoadMedia();
 
@@ -145,8 +148,6 @@ private:
 
     QMediaContent m_media;
     mmr_connection_t *m_connection;
-    mmr_context_t *m_context;
-    QString m_contextName;
     int m_audioId;
     QMediaPlayer::State m_state;
     int m_volume;
@@ -157,7 +158,6 @@ private:
     QPointer<MmRendererMetaDataReaderControl> m_metaDataReaderControl;
     QPointer<MmRendererAudioRoleControl> m_audioRoleControl;
     MmRendererMetaData m_metaData;
-    int m_id;
     qint64 m_position;
     QMediaPlayer::MediaStatus m_mediaStatus;
     bool m_playAfterMediaLoaded;
diff --git a/src/plugins/qnx/mediaplayer/mmrenderermediaplayerservice.cpp b/src/plugins/qnx/mediaplayer/mmrenderermediaplayerservice.cpp
index 6136f946558d6d86052e5f5b8249531aca4dc157..257c437ce6bad767a7e4567d69b1cf97f8752997 100644
--- a/src/plugins/qnx/mediaplayer/mmrenderermediaplayerservice.cpp
+++ b/src/plugins/qnx/mediaplayer/mmrenderermediaplayerservice.cpp
@@ -45,7 +45,7 @@
 #include "mmrendererutil.h"
 #include "mmrenderervideowindowcontrol.h"
 
-#include "ppsmediaplayercontrol.h"
+#include "mmreventmediaplayercontrol.h"
 
 QT_BEGIN_NAMESPACE
 
@@ -74,7 +74,7 @@ QMediaControl *MmRendererMediaPlayerService::requestControl(const char *name)
 {
     if (qstrcmp(name, QMediaPlayerControl_iid) == 0) {
         if (!m_mediaPlayerControl) {
-            m_mediaPlayerControl = new PpsMediaPlayerControl;
+            m_mediaPlayerControl = new MmrEventMediaPlayerControl;
             updateControls();
         }
         return m_mediaPlayerControl;
diff --git a/src/plugins/qnx/mediaplayer/mmreventmediaplayercontrol.cpp b/src/plugins/qnx/mediaplayer/mmreventmediaplayercontrol.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3aac3124c1b0536268ac0e11f5983fc01230bf8d
--- /dev/null
+++ b/src/plugins/qnx/mediaplayer/mmreventmediaplayercontrol.cpp
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 QNX Software Systems. All rights reserved.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mmreventmediaplayercontrol.h"
+#include "mmreventthread.h"
+#include "mmrenderervideowindowcontrol.h"
+
+#include <mm/renderer.h>
+
+QT_BEGIN_NAMESPACE
+
+MmrEventMediaPlayerControl::MmrEventMediaPlayerControl(QObject *parent)
+    : MmRendererMediaPlayerControl(parent)
+    , m_eventThread(nullptr)
+    , m_state(MMR_STATE_IDLE)
+{
+    openConnection();
+}
+
+MmrEventMediaPlayerControl::~MmrEventMediaPlayerControl()
+{
+    destroy();
+}
+
+void MmrEventMediaPlayerControl::startMonitoring()
+{
+    m_eventThread = new MmrEventThread(m_context);
+
+    connect(m_eventThread, &MmrEventThread::eventPending,
+            this, &MmrEventMediaPlayerControl::readEvents);
+
+    m_eventThread->setObjectName(QStringLiteral("MmrEventThread-") + QString::number(m_id));
+    m_eventThread->start();
+}
+
+void MmrEventMediaPlayerControl::stopMonitoring()
+{
+    delete m_eventThread;
+    m_eventThread = nullptr;
+}
+
+bool MmrEventMediaPlayerControl::nativeEventFilter(const QByteArray &eventType,
+                                                   void *message,
+                                                   long *result)
+{
+    Q_UNUSED(result)
+    if (eventType == "screen_event_t") {
+        screen_event_t event = static_cast<screen_event_t>(message);
+        if (MmRendererVideoWindowControl *control = videoWindowControl())
+            control->screenEventHandler(event);
+    }
+
+    return false;
+}
+
+void MmrEventMediaPlayerControl::readEvents()
+{
+    const mmr_event_t *event;
+
+    while ((event = mmr_event_get(m_context))) {
+        if (event->type == MMR_EVENT_NONE)
+            break;
+
+        switch (event->type) {
+        case MMR_EVENT_STATUS: {
+            if (event->data) {
+                const strm_string_t *value;
+                value = strm_dict_find_rstr(event->data, "bufferstatus");
+                if (value)
+                    setMmBufferStatus(QString::fromLatin1(strm_string_get(value)));
+
+                value = strm_dict_find_rstr(event->data, "bufferlevel");
+                if (value)
+                    setMmBufferLevel(QString::fromLatin1(strm_string_get(value)));
+            }
+
+            if (event->pos_str) {
+                const QByteArray valueBa = QByteArray(event->pos_str);
+                bool ok;
+                const qint64 position = valueBa.toLongLong(&ok);
+                if (!ok) {
+                    qCritical("Could not parse position from '%s'", valueBa.constData());
+                } else {
+                    setMmPosition(position);
+                }
+            }
+            break;
+        }
+        case MMR_EVENT_ERROR:
+        case MMR_EVENT_STATE:
+        case MMR_EVENT_NONE:
+        case MMR_EVENT_OVERFLOW:
+        case MMR_EVENT_WARNING:
+        case MMR_EVENT_METADATA:
+        case MMR_EVENT_PLAYLIST:
+        case MMR_EVENT_INPUT:
+        case MMR_EVENT_OUTPUT:
+        case MMR_EVENT_CTXTPAR:
+        case MMR_EVENT_TRKPAR:
+        case MMR_EVENT_OTHER: {
+            break;
+        }
+        }
+
+        // Currently, any exit from the playing state is considered a stop (end-of-media).
+        // If you ever need to separate end-of-media from things like "stopped unexpectedly"
+        // or "stopped because of an error", you'll find that end-of-media is signaled by an
+        // MMR_EVENT_ERROR of MMR_ERROR_NONE with state changed to MMR_STATE_STOPPED.
+        if (event->state != m_state && m_state == MMR_STATE_PLAYING)
+            handleMmStopped();
+        m_state = event->state;
+    }
+
+    if (m_eventThread)
+        m_eventThread->signalRead();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qnx/mediaplayer/ppsmediaplayercontrol.h b/src/plugins/qnx/mediaplayer/mmreventmediaplayercontrol.h
similarity index 73%
rename from src/plugins/qnx/mediaplayer/ppsmediaplayercontrol.h
rename to src/plugins/qnx/mediaplayer/mmreventmediaplayercontrol.h
index eea8388bdd36e4fd76169f535983ce2fdea3e04e..e0aa952a7053a30724f73cc2642c4d3bd2d9399f 100644
--- a/src/plugins/qnx/mediaplayer/ppsmediaplayercontrol.h
+++ b/src/plugins/qnx/mediaplayer/mmreventmediaplayercontrol.h
@@ -1,6 +1,6 @@
 /****************************************************************************
 **
-** Copyright (C) 2016 Research In Motion
+** Copyright (C) 2017 QNX Software Systems. All rights reserved.
 ** Contact: https://www.qt.io/licensing/
 **
 ** This file is part of the Qt Toolkit.
@@ -36,36 +36,37 @@
 ** $QT_END_LICENSE$
 **
 ****************************************************************************/
-#ifndef PPSMEDIAPLAYERCONTROL_H
-#define PPSMEDIAPLAYERCONTROL_H
+#ifndef MMREVENTMEDIAPLAYERCONTROL_H
+#define MMREVENTMEDIAPLAYERCONTROL_H
 
 #include "mmrenderermediaplayercontrol.h"
 
+#include <mm/renderer/events.h>
+
 QT_BEGIN_NAMESPACE
 
-class QSocketNotifier;
+class MmrEventThread;
 
-class PpsMediaPlayerControl Q_DECL_FINAL : public MmRendererMediaPlayerControl
+class MmrEventMediaPlayerControl Q_DECL_FINAL : public MmRendererMediaPlayerControl
 {
     Q_OBJECT
 public:
-    explicit PpsMediaPlayerControl(QObject *parent = 0);
-    ~PpsMediaPlayerControl();
+    explicit MmrEventMediaPlayerControl(QObject *parent = 0);
+    ~MmrEventMediaPlayerControl() override;
 
-    void startMonitoring(int contextId, const QString &contextName) Q_DECL_OVERRIDE;
-    void stopMonitoring() Q_DECL_OVERRIDE;
+    void startMonitoring() override;
+    void stopMonitoring() override;
 
-    bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE;
+    bool nativeEventFilter(const QByteArray &eventType,
+                           void *message,
+                           long *result) override;
 
 private Q_SLOTS:
-    void ppsReadyRead(int fd);
+    void readEvents();
 
 private:
-    QSocketNotifier *m_ppsStatusNotifier;
-    int m_ppsStatusFd;
-    QSocketNotifier *m_ppsStateNotifier;
-    int m_ppsStateFd;
-    QByteArray m_previouslySeenState;
+    MmrEventThread *m_eventThread;
+    mmr_state_t m_state;
 };
 
 QT_END_NAMESPACE
diff --git a/src/plugins/qnx/mediaplayer/mmreventthread.cpp b/src/plugins/qnx/mediaplayer/mmreventthread.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..25f26e216187e6f2f1dd504d93df3fd886beea2b
--- /dev/null
+++ b/src/plugins/qnx/mediaplayer/mmreventthread.cpp
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 QNX Software Systems. All rights reserved.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mmreventthread.h"
+
+#include <QtCore/QDebug>
+
+#include <errno.h>
+#include <mm/renderer/events.h>
+#include <sys/neutrino.h>
+
+static const int c_mmrCode = _PULSE_CODE_MINAVAIL + 0;
+static const int c_readCode = _PULSE_CODE_MINAVAIL + 1;
+static const int c_quitCode = _PULSE_CODE_MINAVAIL + 2;
+
+MmrEventThread::MmrEventThread(mmr_context_t *context)
+    : QThread(),
+      m_mmrContext(context)
+{
+    if (Q_UNLIKELY((m_channelId = ChannelCreate(_NTO_CHF_DISCONNECT
+                                                | _NTO_CHF_UNBLOCK
+                                                | _NTO_CHF_PRIVATE)) == -1)) {
+        qFatal("MmrEventThread: Can't continue without a channel");
+    }
+
+    if (Q_UNLIKELY((m_connectionId = ConnectAttach(0, 0, m_channelId,
+                                                   _NTO_SIDE_CHANNEL, 0)) == -1)) {
+        ChannelDestroy(m_channelId);
+        qFatal("MmrEventThread: Can't continue without a channel connection");
+    }
+
+    SIGEV_PULSE_INIT(&m_mmrEvent, m_connectionId, SIGEV_PULSE_PRIO_INHERIT, c_mmrCode, 0);
+}
+
+MmrEventThread::~MmrEventThread()
+{
+    // block until thread terminates
+    shutdown();
+
+    ConnectDetach(m_connectionId);
+    ChannelDestroy(m_channelId);
+}
+
+void MmrEventThread::run()
+{
+    int armResult = mmr_event_arm(m_mmrContext, &m_mmrEvent);
+    if (armResult > 0)
+        emit eventPending();
+
+    while (1) {
+        struct _pulse msg;
+        memset(&msg, 0, sizeof(msg));
+        int receiveId = MsgReceive(m_channelId, &msg, sizeof(msg), nullptr);
+        if (receiveId == 0) {
+            if (msg.code == c_mmrCode) {
+                emit eventPending();
+            } else if (msg.code == c_readCode) {
+                armResult = mmr_event_arm(m_mmrContext, &m_mmrEvent);
+                if (armResult > 0)
+                    emit eventPending();
+            } else if (msg.code == c_quitCode) {
+                break;
+            } else {
+                qWarning() << Q_FUNC_INFO << "Unexpected pulse" << msg.code;
+            }
+        } else if (receiveId > 0) {
+            qWarning() << Q_FUNC_INFO << "Unexpected message" << msg.code;
+        } else {
+            qWarning() << Q_FUNC_INFO << "MsgReceive error" << strerror(errno);
+        }
+    }
+}
+
+void MmrEventThread::signalRead()
+{
+    MsgSendPulse(m_connectionId, SIGEV_PULSE_PRIO_INHERIT, c_readCode, 0);
+}
+
+void MmrEventThread::shutdown()
+{
+    MsgSendPulse(m_connectionId, SIGEV_PULSE_PRIO_INHERIT, c_quitCode, 0);
+
+    // block until thread terminates
+    wait();
+}
diff --git a/src/plugins/qnx/mediaplayer/mmreventthread.h b/src/plugins/qnx/mediaplayer/mmreventthread.h
new file mode 100644
index 0000000000000000000000000000000000000000..f7bc5cf5ef570a56df7671d110abc15602b187be
--- /dev/null
+++ b/src/plugins/qnx/mediaplayer/mmreventthread.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 QNX Software Systems. All rights reserved.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MMREVENTTHREAD_H
+#define MMREVENTTHREAD_H
+
+#include <QtCore/QThread>
+
+#include <sys/neutrino.h>
+#include <sys/siginfo.h>
+
+QT_BEGIN_NAMESPACE
+
+typedef struct mmr_context mmr_context_t;
+
+class MmrEventThread : public QThread
+{
+    Q_OBJECT
+
+public:
+    MmrEventThread(mmr_context_t *context);
+    ~MmrEventThread() override;
+
+    void signalRead();
+
+protected:
+    void run() override;
+
+Q_SIGNALS:
+    void eventPending();
+
+private:
+    void shutdown();
+
+    int m_channelId;
+    int m_connectionId;
+    struct sigevent m_mmrEvent;
+    mmr_context_t *m_mmrContext;
+};
+
+QT_END_NAMESPACE
+
+#endif // MMREVENTTHREAD_H
diff --git a/src/plugins/qnx/mediaplayer/ppsmediaplayercontrol.cpp b/src/plugins/qnx/mediaplayer/ppsmediaplayercontrol.cpp
deleted file mode 100644
index 40246133190266a2ed7dcaa0165590713a1e39fe..0000000000000000000000000000000000000000
--- a/src/plugins/qnx/mediaplayer/ppsmediaplayercontrol.cpp
+++ /dev/null
@@ -1,200 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Research In Motion
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "ppsmediaplayercontrol.h"
-#include "mmrenderervideowindowcontrol.h"
-
-#include <QtCore/qfile.h>
-#include <QtCore/qsocketnotifier.h>
-#include <QtCore/private/qcore_unix_p.h>
-
-#include <screen/screen.h>
-#include <sys/pps.h>
-
-QT_BEGIN_NAMESPACE
-
-PpsMediaPlayerControl::PpsMediaPlayerControl(QObject *parent)
-    : MmRendererMediaPlayerControl(parent),
-    m_ppsStatusNotifier(0),
-    m_ppsStatusFd(-1),
-    m_ppsStateNotifier(0),
-    m_ppsStateFd(-1)
-  , m_previouslySeenState("stopped")
-{
-    openConnection();
-}
-
-PpsMediaPlayerControl::~PpsMediaPlayerControl()
-{
-    destroy();
-}
-
-void PpsMediaPlayerControl::startMonitoring(int, const QString &contextName)
-{
-    const QString ppsContextPath = QStringLiteral("/pps/services/multimedia/renderer/context/%1/").arg(contextName);
-    const QString ppsStatusPath = ppsContextPath + QStringLiteral("/status");
-
-    Q_ASSERT(m_ppsStatusFd == -1);
-    errno = 0;
-    m_ppsStatusFd = qt_safe_open(QFile::encodeName(ppsStatusPath).constData(), O_RDONLY);
-    if (m_ppsStatusFd == -1) {
-        emitPError(QStringLiteral("Unable to open %1: %2").arg(ppsStatusPath, qt_error_string(errno)));
-        return;
-    }
-
-    Q_ASSERT(!m_ppsStatusNotifier);
-    m_ppsStatusNotifier = new QSocketNotifier(m_ppsStatusFd, QSocketNotifier::Read);
-    connect(m_ppsStatusNotifier, SIGNAL(activated(int)), this, SLOT(ppsReadyRead(int)));
-
-
-    const QString ppsStatePath = ppsContextPath + QStringLiteral("/state");
-
-    Q_ASSERT(m_ppsStateFd == -1);
-    errno = 0;
-    m_ppsStateFd = qt_safe_open(QFile::encodeName(ppsStatePath).constData(), O_RDONLY);
-    if (m_ppsStateFd == -1) {
-        emitPError(QStringLiteral("Unable to open %1: %2").arg(ppsStatePath, qt_error_string(errno)));
-        return;
-    }
-
-    Q_ASSERT(!m_ppsStateNotifier);
-    m_ppsStateNotifier = new QSocketNotifier(m_ppsStateFd, QSocketNotifier::Read);
-    connect(m_ppsStateNotifier, SIGNAL(activated(int)), this, SLOT(ppsReadyRead(int)));
-
-    //ensure we receive any initial state
-    ppsReadyRead(m_ppsStatusFd);
-    ppsReadyRead(m_ppsStateFd);
-}
-
-void PpsMediaPlayerControl::stopMonitoring()
-{
-
-    if (m_ppsStatusFd != -1) {
-        ::close(m_ppsStatusFd);
-        m_ppsStatusFd = -1;
-    }
-
-    delete m_ppsStatusNotifier;
-    m_ppsStatusNotifier = 0;
-
-    if (m_ppsStateFd != -1) {
-        ::close(m_ppsStateFd);
-        m_ppsStateFd = -1;
-    }
-
-    delete m_ppsStateNotifier;
-    m_ppsStateNotifier = 0;
-}
-
-bool PpsMediaPlayerControl::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
-{
-    Q_UNUSED(result)
-    if (eventType == "screen_event_t") {
-        screen_event_t event = static_cast<screen_event_t>(message);
-        if (MmRendererVideoWindowControl *control = videoWindowControl())
-            control->screenEventHandler(event);
-    }
-
-    return false;
-}
-
-void PpsMediaPlayerControl::ppsReadyRead(int fd)
-{
-    Q_ASSERT(fd == m_ppsStateFd || fd == m_ppsStatusFd);
-    const int bufferSize = 2048;
-    char buffer[bufferSize];
-    const ssize_t nread = qt_safe_read(fd, buffer, bufferSize - 1);
-    if (nread < 0) {
-        //TODO emit error?
-    }
-
-    if (nread == 0) {
-        return;
-    }
-
-    // nread is the real space necessary, not the amount read.
-    if (static_cast<size_t>(nread) > bufferSize - 1) {
-        //TODO emit error?
-        qCritical("PpsMediaPlayerControl: PPS buffer size too short; need %zd.", nread + 1);
-        return;
-    }
-
-    buffer[nread] = 0;
-
-    pps_decoder_t decoder;
-
-    if (pps_decoder_initialize(&decoder, buffer) != PPS_DECODER_OK) {
-        //TODO emit error?
-        qCritical("Could not initialize pps_decoder");
-        pps_decoder_cleanup(&decoder);
-        return;
-    }
-
-    pps_decoder_push(&decoder, 0);
-
-    const char *value = 0;
-
-    if (pps_decoder_get_string(&decoder, "bufferstatus", &value) == PPS_DECODER_OK)
-        setMmBufferStatus(QString::fromLatin1(value));
-
-    if (pps_decoder_get_string(&decoder, "bufferlevel", &value) == PPS_DECODER_OK)
-        setMmBufferLevel(QString::fromLatin1(value));
-
-    if (pps_decoder_get_string(&decoder, "state", &value) == PPS_DECODER_OK) {
-        const QByteArray state = value;
-        if (state != m_previouslySeenState && state == "stopped")
-            handleMmStopped();
-        m_previouslySeenState = state;
-    }
-
-    if (pps_decoder_get_string(&decoder, "position", &value) == PPS_DECODER_OK) {
-        const QByteArray valueBa = QByteArray(value);
-        bool ok;
-        const qint64 position = valueBa.toLongLong(&ok);
-        if (!ok) {
-            qCritical("Could not parse position from '%s'", valueBa.constData());
-        } else {
-            setMmPosition(position);
-        }
-    }
-
-    pps_decoder_cleanup(&decoder);
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/winrt/qwinrtabstractvideorenderercontrol.cpp b/src/plugins/winrt/qwinrtabstractvideorenderercontrol.cpp
index b3fd11111a0bbcb042fb9e459ca695ee5d798ec9..79545f6eecf48bce6de48347f52cc61628f3b8d2 100644
--- a/src/plugins/winrt/qwinrtabstractvideorenderercontrol.cpp
+++ b/src/plugins/winrt/qwinrtabstractvideorenderercontrol.cpp
@@ -43,6 +43,7 @@
 #include <QtCore/QGlobalStatic>
 #include <QtCore/QLoggingCategory>
 #include <QtCore/QMetaMethod>
+#include <QtCore/QMutexLocker>
 #include <QtCore/QPointer>
 #include <QtGui/QOpenGLContext>
 #include <QtGui/QOpenGLTexture>
@@ -198,7 +199,7 @@ public:
     QThread renderThread;
     bool active;
     QWinRTAbstractVideoRendererControl::BlitMode blitMode;
-    CRITICAL_SECTION mutex;
+    QMutex mutex;
 };
 
 ID3D11Device *QWinRTAbstractVideoRendererControl::d3dDevice()
@@ -232,7 +233,6 @@ QWinRTAbstractVideoRendererControl::QWinRTAbstractVideoRendererControl(const QSi
     d->eglSurface = EGL_NO_SURFACE;
     d->active = false;
     d->blitMode = DirectVideo;
-    InitializeCriticalSectionEx(&d->mutex, 0, 0);
 
     connect(&d->renderThread, &QThread::started,
             this, &QWinRTAbstractVideoRendererControl::syncAndRender,
@@ -243,9 +243,9 @@ QWinRTAbstractVideoRendererControl::~QWinRTAbstractVideoRendererControl()
 {
     qCDebug(lcMMVideoRender) << __FUNCTION__;
     Q_D(QWinRTAbstractVideoRendererControl);
-    CriticalSectionLocker locker(&d->mutex);
+    QMutexLocker locker(&d->mutex);
     shutdown();
-    DeleteCriticalSection(&d->mutex);
+    locker.unlock();
     eglDestroySurface(d->eglDisplay, d->eglSurface);
 }
 
@@ -272,7 +272,7 @@ void QWinRTAbstractVideoRendererControl::syncAndRender()
         if (currentThread->isInterruptionRequested())
             break;
         {
-            CriticalSectionLocker lock(&d->mutex);
+            QMutexLocker lock(&d->mutex);
             HRESULT hr;
             if (d->dirtyState == TextureDirty) {
                 CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, d->format.frameWidth(), d->format.frameHeight(), 1, 1);
@@ -359,7 +359,7 @@ void QWinRTAbstractVideoRendererControl::setActive(bool active)
         // This only happens for quick restart scenarios, for instance
         // when switching cameras.
         if (d->renderThread.isRunning() && d->renderThread.isInterruptionRequested()) {
-            CriticalSectionLocker lock(&d->mutex);
+            QMutexLocker lock(&d->mutex);
             d->renderThread.wait();
         }
 
@@ -385,7 +385,7 @@ QWinRTAbstractVideoRendererControl::BlitMode QWinRTAbstractVideoRendererControl:
 void QWinRTAbstractVideoRendererControl::setBlitMode(QWinRTAbstractVideoRendererControl::BlitMode mode)
 {
     Q_D(QWinRTAbstractVideoRendererControl);
-    CriticalSectionLocker lock(&d->mutex);
+    QMutexLocker lock(&d->mutex);
 
     if (d->blitMode == mode)
         return;
diff --git a/src/plugins/winrt/qwinrtabstractvideorenderercontrol.h b/src/plugins/winrt/qwinrtabstractvideorenderercontrol.h
index a7ba2998adb3e6e6486c25946c5f76b96da4749e..53dcb6b941aab45a4fceb79faf2f247d6dafb755 100644
--- a/src/plugins/winrt/qwinrtabstractvideorenderercontrol.h
+++ b/src/plugins/winrt/qwinrtabstractvideorenderercontrol.h
@@ -96,22 +96,6 @@ private:
     Q_DECLARE_PRIVATE(QWinRTAbstractVideoRendererControl)
 };
 
-class CriticalSectionLocker
-{
-public:
-    CriticalSectionLocker(CRITICAL_SECTION *section)
-        : m_section(section)
-    {
-        EnterCriticalSection(m_section);
-    }
-    ~CriticalSectionLocker()
-    {
-        LeaveCriticalSection(m_section);
-    }
-private:
-    CRITICAL_SECTION *m_section;
-};
-
 QT_END_NAMESPACE
 
 #endif // QWINRTABSTRACTVIDEORENDERERCONTROL_H
diff --git a/src/plugins/winrt/qwinrtcameracontrol.cpp b/src/plugins/winrt/qwinrtcameracontrol.cpp
index a28d57219fa736f45a6ea3335d27dc22e0b46e1a..527dd6e8fa1ed517e99214bc46eb1be21a165f77 100644
--- a/src/plugins/winrt/qwinrtcameracontrol.cpp
+++ b/src/plugins/winrt/qwinrtcameracontrol.cpp
@@ -47,6 +47,7 @@
 #include "qwinrtcameralockscontrol.h"
 
 #include <QtCore/qfunctions_winrt.h>
+#include <QtCore/QMutex>
 #include <QtCore/QPointer>
 #include <QtGui/QGuiApplication>
 #include <private/qeventdispatcher_winrt_p.h>
@@ -227,8 +228,6 @@ public:
     {
         Q_ASSERT(m_videoRenderer);
 
-        InitializeCriticalSectionEx(&m_mutex, 0, 0);
-
         HRESULT hr;
         hr = MFCreateEventQueue(&m_eventQueue);
         Q_ASSERT_SUCCEEDED(hr);
@@ -238,9 +237,8 @@ public:
 
     ~MediaStream()
     {
-        CriticalSectionLocker locker(&m_mutex);
+        QMutexLocker locker(&m_mutex);
         m_eventQueue->Shutdown();
-        DeleteCriticalSection(&m_mutex);
     }
 
     HRESULT RequestSample()
@@ -254,30 +252,30 @@ public:
 
     HRESULT __stdcall GetEvent(DWORD flags, IMFMediaEvent **event) Q_DECL_OVERRIDE
     {
-        EnterCriticalSection(&m_mutex);
+        QMutexLocker locker(&m_mutex);
         // Create an extra reference to avoid deadlock
         ComPtr<IMFMediaEventQueue> eventQueue = m_eventQueue;
-        LeaveCriticalSection(&m_mutex);
+        locker.unlock();
 
         return eventQueue->GetEvent(flags, event);
     }
 
     HRESULT __stdcall BeginGetEvent(IMFAsyncCallback *callback, IUnknown *state) Q_DECL_OVERRIDE
     {
-        CriticalSectionLocker locker(&m_mutex);
+        QMutexLocker locker(&m_mutex);
         HRESULT hr = m_eventQueue->BeginGetEvent(callback, state);
         return hr;
     }
 
     HRESULT __stdcall EndGetEvent(IMFAsyncResult *result, IMFMediaEvent **event) Q_DECL_OVERRIDE
     {
-        CriticalSectionLocker locker(&m_mutex);
+        QMutexLocker locker(&m_mutex);
         return m_eventQueue->EndGetEvent(result, event);
     }
 
     HRESULT __stdcall QueueEvent(MediaEventType eventType, const GUID &extendedType, HRESULT status, const PROPVARIANT *value) Q_DECL_OVERRIDE
     {
-        CriticalSectionLocker locker(&m_mutex);
+        QMutexLocker locker(&m_mutex);
         return m_eventQueue->QueueEventParamVar(eventType, extendedType, status, value);
     }
 
@@ -372,7 +370,7 @@ public:
     }
 
 private:
-    CRITICAL_SECTION m_mutex;
+    QMutex m_mutex;
     ComPtr<IMFMediaType> m_type;
     IMFMediaSink *m_sink;
     ComPtr<IMFMediaEventQueue> m_eventQueue;
@@ -560,6 +558,10 @@ public:
     QPointer<QWinRTCameraLocksControl> cameraLocksControl;
     QAtomicInt framesMapped;
     QEventLoop *delayClose;
+
+    bool initializing = false;
+    bool initialized = false;
+    HANDLE initializationCompleteEvent;
 };
 
 QWinRTCameraControl::QWinRTCameraControl(QObject *parent)
@@ -584,6 +586,8 @@ QWinRTCameraControl::QWinRTCameraControl(QObject *parent)
     d->cameraFocusControl = new QWinRTCameraFocusControl(this);
     d->cameraLocksControl = new QWinRTCameraLocksControl(this);
 
+    d->initializationCompleteEvent = CreateEvent(NULL, false, false, NULL);
+
     if (qGuiApp) {
         connect(qGuiApp, &QGuiApplication::applicationStateChanged,
                 this, &QWinRTCameraControl::onApplicationStateChanged);
@@ -614,8 +618,23 @@ void QWinRTCameraControl::setState(QCamera::State state)
     case QCamera::ActiveState: {
         // Capture has not been created or initialized
         if (d->state == QCamera::UnloadedState) {
-            hr = initialize();
-            RETURN_VOID_AND_EMIT_ERROR("Failed to initialize media capture");
+            if (!d->initialized) {
+                if (!d->initializing) {
+                    hr = initialize();
+                    RETURN_VOID_AND_EMIT_ERROR("Failed to initialize media capture");
+                }
+                DWORD waitResult = WaitForSingleObjectEx(d->initializationCompleteEvent, 30000, FALSE);
+                if (waitResult != WAIT_OBJECT_0) {
+                    RETURN_VOID_AND_EMIT_ERROR("Failed to initialize camera control.");
+                    return;
+                }
+            }
+
+            d->state = QCamera::LoadedState;
+            emit stateChanged(d->state);
+
+            d->status = QCamera::LoadedStatus;
+            emit statusChanged(d->status);
         }
         Q_ASSERT(d->state == QCamera::LoadedState);
 
@@ -654,8 +673,23 @@ void QWinRTCameraControl::setState(QCamera::State state)
     case QCamera::LoadedState: {
         // If moving from unloaded, initialize the camera
         if (d->state == QCamera::UnloadedState) {
-            hr = initialize();
-            RETURN_VOID_AND_EMIT_ERROR("Failed to initialize media capture");
+            if (!d->initialized) {
+                if (!d->initializing) {
+                    hr = initialize();
+                    RETURN_VOID_AND_EMIT_ERROR("Failed to initialize media capture");
+                }
+                DWORD waitResult = WaitForSingleObjectEx(d->initializationCompleteEvent, 30000, FALSE);
+                if (waitResult != WAIT_OBJECT_0) {
+                    RETURN_VOID_AND_EMIT_ERROR("Failed to initialize camera control.");
+                    return;
+                }
+            }
+
+            d->state = QCamera::LoadedState;
+            emit stateChanged(d->state);
+
+            d->status = QCamera::LoadedStatus;
+            emit statusChanged(d->status);
         }
         // fall through
     }
@@ -745,6 +779,7 @@ void QWinRTCameraControl::setState(QCamera::State state)
                 d->status = QCamera::UnloadedStatus;
                 emit statusChanged(d->status);
             }
+            d->initialized = false;
         }
         break;
     }
@@ -884,8 +919,7 @@ HRESULT QWinRTCameraControl::initialize()
         emit statusChanged(d->status);
     }
 
-    boolean isFocusSupported;
-    HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([this, d, &isFocusSupported]() {
+    HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([this, d]() {
         HRESULT hr;
         ComPtr<IInspectable> capture;
         hr = RoActivateInstance(Wrappers::HString::MakeReference(RuntimeClass_Windows_Media_Capture_MediaCapture).Get(),
@@ -935,121 +969,11 @@ HRESULT QWinRTCameraControl::initialize()
         ComPtr<IAsyncAction> op;
         hr = d->capture->InitializeWithSettingsAsync(settings.Get(), &op);
         RETURN_HR_IF_FAILED("Failed to begin initialization of media capture manager");
-        hr = QWinRTFunctions::await(op, QWinRTFunctions::ProcessThreadEvents);
-        if (hr == E_ACCESSDENIED) {
-            qWarning("Access denied when initializing the media capture manager. "
-                     "Check your manifest settings for microphone and webcam access.");
-        }
-        RETURN_HR_IF_FAILED("Failed to initialize media capture manager");
-
-        ComPtr<IVideoDeviceController> videoDeviceController;
-        hr = d->capture->get_VideoDeviceController(&videoDeviceController);
-        ComPtr<IAdvancedVideoCaptureDeviceController2> advancedVideoDeviceController;
-        hr = videoDeviceController.As(&advancedVideoDeviceController);
-        Q_ASSERT_SUCCEEDED(hr);
-        hr = advancedVideoDeviceController->get_FocusControl(&d->focusControl);
-        Q_ASSERT_SUCCEEDED(hr);
-
-        d->cameraFlashControl->initialize(advancedVideoDeviceController);
-
-        hr = d->focusControl->get_Supported(&isFocusSupported);
-        Q_ASSERT_SUCCEEDED(hr);
-        if (isFocusSupported) {
-            hr = advancedVideoDeviceController->get_RegionsOfInterestControl(&d->regionsOfInterestControl);
-            if (FAILED(hr))
-                qCDebug(lcMMCamera) << "Focus supported, but no control for regions of interest available";
-            hr = initializeFocus();
-            Q_ASSERT_SUCCEEDED(hr);
-        }
-
-        Q_ASSERT_SUCCEEDED(hr);
-        ComPtr<IMediaDeviceController> deviceController;
-        hr = videoDeviceController.As(&deviceController);
-        Q_ASSERT_SUCCEEDED(hr);
-
-        // Get preview stream properties.
-        ComPtr<IVectorView<IMediaEncodingProperties *>> previewPropertiesList;
-        QVector<QSize> previewResolutions;
-        hr = getMediaStreamResolutions(deviceController.Get(),
-                                       MediaStreamType_VideoPreview,
-                                       &previewPropertiesList,
-                                       &previewResolutions);
-        RETURN_HR_IF_FAILED("Failed to find a suitable video format");
-
-        MediaStreamType mediaStreamType =
-                d->captureMode == QCamera::CaptureVideo ? MediaStreamType_VideoRecord : MediaStreamType_Photo;
-
-        // Get capture stream properties.
-        ComPtr<IVectorView<IMediaEncodingProperties *>> capturePropertiesList;
-        QVector<QSize> captureResolutions;
-        hr = getMediaStreamResolutions(deviceController.Get(),
-                                       mediaStreamType,
-                                       &capturePropertiesList,
-                                       &captureResolutions);
-        RETURN_HR_IF_FAILED("Failed to find a suitable video format");
-
-        // Set capture resolutions.
-        d->imageEncoderControl->setSupportedResolutionsList(captureResolutions.toList());
-        const QSize captureResolution = d->imageEncoderControl->imageSettings().resolution();
-        const quint32 captureResolutionIndex = captureResolutions.indexOf(captureResolution);
-        ComPtr<IMediaEncodingProperties> captureProperties;
-        hr = capturePropertiesList->GetAt(captureResolutionIndex, &captureProperties);
-        Q_ASSERT_SUCCEEDED(hr);
-        hr = deviceController->SetMediaStreamPropertiesAsync(mediaStreamType, captureProperties.Get(), &op);
-        Q_ASSERT_SUCCEEDED(hr);
-        hr = QWinRTFunctions::await(op);
-        Q_ASSERT_SUCCEEDED(hr);
-
-        // Set preview resolution.
-        QVector<QSize> filtered;
-        const float captureAspectRatio = float(captureResolution.width()) / captureResolution.height();
-        for (const QSize &resolution : qAsConst(previewResolutions)) {
-            const float aspectRatio = float(resolution.width()) / resolution.height();
-            if (qAbs(aspectRatio - captureAspectRatio) <= ASPECTRATIO_EPSILON)
-                filtered.append(resolution);
-        }
-        qSort(filtered.begin(),
-              filtered.end(),
-              [](QSize size1, QSize size2) { return size1.width() * size1.height() < size2.width() * size2.height(); });
-
-        const QSize &viewfinderResolution = filtered.first();
-        const quint32 viewfinderResolutionIndex = previewResolutions.indexOf(viewfinderResolution);
-        hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Media_MediaProperties_MediaEncodingProfile).Get(),
-                                &d->encodingProfile);
-        Q_ASSERT_SUCCEEDED(hr);
-        ComPtr<IMediaEncodingProperties> previewProperties;
-        hr = previewPropertiesList->GetAt(viewfinderResolutionIndex, &previewProperties);
-        Q_ASSERT_SUCCEEDED(hr);
-        hr = deviceController->SetMediaStreamPropertiesAsync(MediaStreamType_VideoPreview, previewProperties.Get(), &op);
-        Q_ASSERT_SUCCEEDED(hr);
-        hr = QWinRTFunctions::await(op);
-        Q_ASSERT_SUCCEEDED(hr);
-        ComPtr<IVideoEncodingProperties> videoPreviewProperties;
-        hr = previewProperties.As(&videoPreviewProperties);
-        Q_ASSERT_SUCCEEDED(hr);
-        hr = d->encodingProfile->put_Video(videoPreviewProperties.Get());
-        Q_ASSERT_SUCCEEDED(hr);
-
-        if (d->videoRenderer)
-            d->videoRenderer->setSize(viewfinderResolution);
-
+        hr = op.Get()->put_Completed(Callback<IAsyncActionCompletedHandler>(
+                                         this, &QWinRTCameraControl::onInitializationCompleted).Get());
+        RETURN_HR_IF_FAILED("Failed to register initialization callback");
         return S_OK;
     });
-
-    if (!isFocusSupported) {
-        d->cameraFocusControl->setSupportedFocusMode(0);
-        d->cameraFocusControl->setSupportedFocusPointMode(QSet<QCameraFocus::FocusPointMode>());
-    }
-    d->cameraLocksControl->initialize();
-
-    if (SUCCEEDED(hr) && d->state != QCamera::LoadedState) {
-        d->state = QCamera::LoadedState;
-        emit stateChanged(d->state);
-    }
-    if (SUCCEEDED(hr) && d->status != QCamera::LoadedStatus) {
-        d->status = QCamera::LoadedStatus;
-        emit statusChanged(d->status);
-    }
     return hr;
 }
 
@@ -1413,6 +1337,122 @@ HRESULT QWinRTCameraControl::onRecordLimitationExceeded(IMediaCapture *)
     return S_OK;
 }
 
+HRESULT QWinRTCameraControl::onInitializationCompleted(IAsyncAction *, AsyncStatus status)
+{
+    qCDebug(lcMMCamera) << __FUNCTION__;
+    Q_D(QWinRTCameraControl);
+
+    if (status != Completed) {
+        d->initializing = false;
+        d->initialized = true;
+        return S_OK;
+    }
+
+    ComPtr<IVideoDeviceController> videoDeviceController;
+    HRESULT hr = d->capture->get_VideoDeviceController(&videoDeviceController);
+    ComPtr<IAdvancedVideoCaptureDeviceController2> advancedVideoDeviceController;
+    hr = videoDeviceController.As(&advancedVideoDeviceController);
+    Q_ASSERT_SUCCEEDED(hr);
+    hr = advancedVideoDeviceController->get_FocusControl(&d->focusControl);
+    Q_ASSERT_SUCCEEDED(hr);
+
+    d->cameraFlashControl->initialize(advancedVideoDeviceController);
+
+    boolean isFocusSupported;
+    hr = d->focusControl->get_Supported(&isFocusSupported);
+    Q_ASSERT_SUCCEEDED(hr);
+    if (isFocusSupported) {
+        hr = advancedVideoDeviceController->get_RegionsOfInterestControl(&d->regionsOfInterestControl);
+        if (FAILED(hr))
+            qCDebug(lcMMCamera) << "Focus supported, but no control for regions of interest available";
+        hr = initializeFocus();
+        Q_ASSERT_SUCCEEDED(hr);
+    }
+
+    Q_ASSERT_SUCCEEDED(hr);
+    ComPtr<IMediaDeviceController> deviceController;
+    hr = videoDeviceController.As(&deviceController);
+    Q_ASSERT_SUCCEEDED(hr);
+
+    // Get preview stream properties.
+    ComPtr<IVectorView<IMediaEncodingProperties *>> previewPropertiesList;
+    QVector<QSize> previewResolutions;
+    hr = getMediaStreamResolutions(deviceController.Get(),
+                                   MediaStreamType_VideoPreview,
+                                   &previewPropertiesList,
+                                   &previewResolutions);
+    RETURN_HR_IF_FAILED("Failed to find a suitable video format");
+
+    MediaStreamType mediaStreamType =
+            d->captureMode == QCamera::CaptureVideo ? MediaStreamType_VideoRecord : MediaStreamType_Photo;
+
+    // Get capture stream properties.
+    ComPtr<IVectorView<IMediaEncodingProperties *>> capturePropertiesList;
+    QVector<QSize> captureResolutions;
+    hr = getMediaStreamResolutions(deviceController.Get(),
+                                   mediaStreamType,
+                                   &capturePropertiesList,
+                                   &captureResolutions);
+    RETURN_HR_IF_FAILED("Failed to find a suitable video format");
+
+    // Set capture resolutions.
+    d->imageEncoderControl->setSupportedResolutionsList(captureResolutions.toList());
+    const QSize captureResolution = d->imageEncoderControl->imageSettings().resolution();
+    const quint32 captureResolutionIndex = captureResolutions.indexOf(captureResolution);
+    ComPtr<IMediaEncodingProperties> captureProperties;
+    hr = capturePropertiesList->GetAt(captureResolutionIndex, &captureProperties);
+    Q_ASSERT_SUCCEEDED(hr);
+    ComPtr<IAsyncAction> op;
+    hr = deviceController->SetMediaStreamPropertiesAsync(mediaStreamType, captureProperties.Get(), &op);
+    Q_ASSERT_SUCCEEDED(hr);
+    hr = QWinRTFunctions::await(op);
+    Q_ASSERT_SUCCEEDED(hr);
+
+    // Set preview resolution.
+    QVector<QSize> filtered;
+    const float captureAspectRatio = float(captureResolution.width()) / captureResolution.height();
+    for (const QSize &resolution : qAsConst(previewResolutions)) {
+        const float aspectRatio = float(resolution.width()) / resolution.height();
+        if (qAbs(aspectRatio - captureAspectRatio) <= ASPECTRATIO_EPSILON)
+            filtered.append(resolution);
+    }
+    qSort(filtered.begin(),
+          filtered.end(),
+          [](QSize size1, QSize size2) { return size1.width() * size1.height() < size2.width() * size2.height(); });
+
+    const QSize &viewfinderResolution = filtered.first();
+    const quint32 viewfinderResolutionIndex = previewResolutions.indexOf(viewfinderResolution);
+    hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Media_MediaProperties_MediaEncodingProfile).Get(),
+                            &d->encodingProfile);
+    Q_ASSERT_SUCCEEDED(hr);
+    ComPtr<IMediaEncodingProperties> previewProperties;
+    hr = previewPropertiesList->GetAt(viewfinderResolutionIndex, &previewProperties);
+    Q_ASSERT_SUCCEEDED(hr);
+    hr = deviceController->SetMediaStreamPropertiesAsync(MediaStreamType_VideoPreview, previewProperties.Get(), &op);
+    Q_ASSERT_SUCCEEDED(hr);
+    hr = QWinRTFunctions::await(op);
+    Q_ASSERT_SUCCEEDED(hr);
+    ComPtr<IVideoEncodingProperties> videoPreviewProperties;
+    hr = previewProperties.As(&videoPreviewProperties);
+    Q_ASSERT_SUCCEEDED(hr);
+    hr = d->encodingProfile->put_Video(videoPreviewProperties.Get());
+    Q_ASSERT_SUCCEEDED(hr);
+
+    if (d->videoRenderer)
+        d->videoRenderer->setSize(viewfinderResolution);
+
+    if (!isFocusSupported) {
+        d->cameraFocusControl->setSupportedFocusMode(0);
+        d->cameraFocusControl->setSupportedFocusPointMode(QSet<QCameraFocus::FocusPointMode>());
+    }
+    d->cameraLocksControl->initialize();
+
+    d->initializing = false;
+    d->initialized = true;
+    SetEvent(d->initializationCompleteEvent);
+    return S_OK;
+}
+
 void QWinRTCameraControl::emitError(int errorCode, const QString &errorString)
 {
     qCDebug(lcMMCamera) << __FUNCTION__ << errorString << errorCode;
diff --git a/src/plugins/winrt/qwinrtcameracontrol.h b/src/plugins/winrt/qwinrtcameracontrol.h
index f978a8b2cace845380a400a628749a006beaaf80..7ef67e9579dfaf0a87ea6cc42aecd0cf49fbb4bd 100644
--- a/src/plugins/winrt/qwinrtcameracontrol.h
+++ b/src/plugins/winrt/qwinrtcameracontrol.h
@@ -123,6 +123,8 @@ private:
     HRESULT onCaptureFailed(ABI::Windows::Media::Capture::IMediaCapture *,
                             ABI::Windows::Media::Capture::IMediaCaptureFailedEventArgs *);
     HRESULT onRecordLimitationExceeded(ABI::Windows::Media::Capture::IMediaCapture *);
+    HRESULT onInitializationCompleted(ABI::Windows::Foundation::IAsyncAction *,
+                                      ABI::Windows::Foundation::AsyncStatus);
 
     QScopedPointer<QWinRTCameraControlPrivate> d_ptr;
     Q_DECLARE_PRIVATE(QWinRTCameraControl)
diff --git a/tests/auto/integration/qsound/BLACKLIST b/tests/auto/integration/qsound/BLACKLIST
new file mode 100644
index 0000000000000000000000000000000000000000..ccb68f5413e64313ee7dc19ff22c0cb00f5768c6
--- /dev/null
+++ b/tests/auto/integration/qsound/BLACKLIST
@@ -0,0 +1,3 @@
+[testLooping]
+opensuse-42.3
+
diff --git a/tests/auto/integration/qsound/tst_qsound.cpp b/tests/auto/integration/qsound/tst_qsound.cpp
index 729b0f0865751f58d247c3b15c47ef9e9b2c264b..9fcf79184e9b69b5ed4bd10c9108545a0289fa3e 100644
--- a/tests/auto/integration/qsound/tst_qsound.cpp
+++ b/tests/auto/integration/qsound/tst_qsound.cpp
@@ -88,9 +88,7 @@ void tst_QSound::testLooping()
     QVERIFY(!sound->isFinished());
 
     // test.wav is about 200ms, wait until it has finished playing 5 times
-    QTest::qWait(3000);
-
-    QVERIFY(sound->isFinished());
+    QTRY_VERIFY(sound->isFinished());
     QCOMPARE(sound->loopsRemaining(),0);
 }
 
@@ -99,8 +97,7 @@ void tst_QSound::testPlay()
     sound->setLoops(1);
     sound->play();
     QVERIFY(!sound->isFinished());
-    QTest::qWait(1000);
-    QVERIFY(sound->isFinished());
+    QTRY_VERIFY(sound->isFinished());
 }
 
 void tst_QSound::testStop()
@@ -110,8 +107,7 @@ void tst_QSound::testStop()
     QVERIFY(!sound->isFinished());
     QTest::qWait(1000);
     sound->stop();
-    QTest::qWait(1000);
-    QVERIFY(sound->isFinished());
+    QTRY_VERIFY(sound->isFinished());
 }
 
 void tst_QSound::testStaticPlay()