From d599f7319af86265083bae96f21d942aeff24737 Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Fri, 12 Jul 2013 12:30:39 +0200 Subject: [PATCH 1/3] WMF: fixed MediaPlayer buffering logic. To have a consistent behavior with other backends, the WMF plugin now starts the session after loading a media in order to start buffering some data and correctly notify when the media is buffered. It was previously reporting a BufferedMedia status only (and wrongly) after explicitly starting the media player. Not all source readers (usually a source reader is specific to a file format) implement the service needed to query buffering progress. In that case just report the media to be buffered immediately after loading. Change-Id: I6e6332ae08e96fc789556761e5169b88c36c5e37 Reviewed-by: Christian Stromme --- src/plugins/wmf/player/mfplayersession.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/plugins/wmf/player/mfplayersession.cpp b/src/plugins/wmf/player/mfplayersession.cpp index c52498f6..fb150c3e 100644 --- a/src/plugins/wmf/player/mfplayersession.cpp +++ b/src/plugins/wmf/player/mfplayersession.cpp @@ -1326,8 +1326,6 @@ void MFPlayerSession::start() switch (m_status) { case QMediaPlayer::EndOfMedia: m_varStart.hVal.QuadPart = 0; - //since it must be loaded already, just fallthrough - case QMediaPlayer::LoadedMedia: changeStatus(QMediaPlayer::BufferedMedia); return; } @@ -1911,10 +1909,12 @@ void MFPlayerSession::handleSessionEvent(IMFMediaEvent *sessionEvent) switch (meType) { case MEBufferingStarted: - changeStatus(QMediaPlayer::StalledMedia); + changeStatus(m_status == QMediaPlayer::LoadedMedia ? QMediaPlayer::BufferingMedia : QMediaPlayer::StalledMedia); emit bufferStatusChanged(bufferStatus()); break; case MEBufferingStopped: + if (m_status == QMediaPlayer::BufferingMedia) + stop(true); changeStatus(QMediaPlayer::BufferedMedia); emit bufferStatusChanged(bufferStatus()); break; @@ -1979,6 +1979,16 @@ void MFPlayerSession::handleSessionEvent(IMFMediaEvent *sessionEvent) } } MFGetService(m_session, MFNETSOURCE_STATISTICS_SERVICE, IID_PPV_ARGS(&m_netsourceStatistics)); + + if (!m_netsourceStatistics || bufferStatus() == 100) { + // If the source reader doesn't implement the statistics service, just set the status + // to buffered, since there is no way to query the buffering progress... + changeStatus(QMediaPlayer::BufferedMedia); + } else { + // Start to trigger buffering. Once enough buffering is done, the session will + // be automatically stopped unless the user has explicitly started playback. + start(); + } } } } From d8e56bc4b8d2bb35074d1158a068832054386c1a Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Fri, 19 Jul 2013 12:29:12 +0200 Subject: [PATCH 2/3] DirectShow: Don't create the widget and renderer controls until requested. Task-number: QTBUG-32282 Change-Id: If37ed4c35bcc2cc879f50d3b2ea3720b90603e9a Reviewed-by: Yoann Lopes --- .../directshow/camera/dscameraservice.cpp | 40 ++++++++++++++----- .../directshow/camera/dscameraservice.h | 6 +-- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/src/plugins/directshow/camera/dscameraservice.cpp b/src/plugins/directshow/camera/dscameraservice.cpp index 2c6ea0e9..9d99c6dd 100644 --- a/src/plugins/directshow/camera/dscameraservice.cpp +++ b/src/plugins/directshow/camera/dscameraservice.cpp @@ -62,6 +62,10 @@ QT_BEGIN_NAMESPACE DSCameraService::DSCameraService(QObject *parent): QMediaService(parent) +#if defined(HAVE_WIDGETS) + , m_viewFinderWidget(0) + #endif + , m_videoRenderer(0) { m_session = new DSCameraSession(this); @@ -69,14 +73,8 @@ DSCameraService::DSCameraService(QObject *parent): m_videoDevice = new DSVideoDeviceControl(m_session); - m_videoRenderer = new DSVideoRendererControl(m_session, this); - m_imageCapture = new DSImageCaptureControl(m_session); -#if defined(HAVE_WIDGETS) - m_viewFinderWidget = new DSVideoWidgetControl(m_session); -#endif - m_device = QByteArray("default"); } @@ -102,14 +100,23 @@ QMediaControl* DSCameraService::requestControl(const char *name) #if defined(HAVE_WIDGETS) if (qstrcmp(name, QVideoWidgetControl_iid) == 0) { - if (m_viewFinderWidget) { + if (!m_viewFinderWidget && !m_videoRenderer) { + m_viewFinderWidget = new DSVideoWidgetControl(m_session); return m_viewFinderWidget; } } #endif - if(qstrcmp(name,QVideoRendererControl_iid) == 0) - return m_videoRenderer; + if (qstrcmp(name,QVideoRendererControl_iid) == 0) { +#if defined(HAVE_WIDGETS) + if (!m_videoRenderer && !m_viewFinderWidget) { +#else + if (!m_videoRenderer) { +#endif + m_videoRenderer = new DSVideoRendererControl(m_session, this); + return m_videoRenderer; + } + } if (qstrcmp(name,QVideoDeviceSelectorControl_iid) == 0) return m_videoDevice; @@ -119,8 +126,19 @@ QMediaControl* DSCameraService::requestControl(const char *name) void DSCameraService::releaseControl(QMediaControl *control) { - Q_UNUSED(control) - // Implemented as a singleton, so we do nothing. + if (control == m_videoRenderer) { + delete m_videoRenderer; + m_videoRenderer = 0; + return; + } + +#if defined(HAVE_WIDGETS) + if (control == m_viewFinderWidget) { + delete m_viewFinderWidget; + m_viewFinderWidget = 0; + return; + } +#endif } QT_END_NAMESPACE diff --git a/src/plugins/directshow/camera/dscameraservice.h b/src/plugins/directshow/camera/dscameraservice.h index e39ea0ad..fb8b7886 100644 --- a/src/plugins/directshow/camera/dscameraservice.h +++ b/src/plugins/directshow/camera/dscameraservice.h @@ -52,9 +52,7 @@ class DSCameraControl; class DSCameraSession; class DSVideoOutputControl; class DSVideoDeviceControl; -class DSVideoRendererControl; class DSImageCaptureControl; -class DSVideoWidgetControl; class DSCameraService : public QMediaService @@ -73,10 +71,10 @@ private: DSCameraSession *m_session; DSVideoOutputControl *m_videoOutput; #if defined(HAVE_WIDGETS) - DSVideoWidgetControl *m_viewFinderWidget; + QMediaControl *m_viewFinderWidget; #endif DSVideoDeviceControl *m_videoDevice; - DSVideoRendererControl *m_videoRenderer; + QMediaControl *m_videoRenderer; DSImageCaptureControl *m_imageCapture; QByteArray m_device; }; From c74b544610376c753ea0a29ff2465e2bcfe70e1d Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Fri, 19 Jul 2013 14:36:06 +0200 Subject: [PATCH 3/3] DirectShow: avoid unnecessary RGB32 -> BGR32 conversion. Frames in the RGB32 format are actually using the BGR byte order, no need to do the conversion. Task-number: QTBUG-29206 Change-Id: I13527bd9dacc8330df78beb0965b31469c1d7a87 Reviewed-by: Yoann Lopes --- src/plugins/directshow/camera/dscamerasession.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/directshow/camera/dscamerasession.cpp b/src/plugins/directshow/camera/dscamerasession.cpp index 353078f4..cc1594fe 100644 --- a/src/plugins/directshow/camera/dscamerasession.cpp +++ b/src/plugins/directshow/camera/dscamerasession.cpp @@ -595,7 +595,7 @@ void DSCameraSession::captureFrame() mutex.lock(); image = QImage(frames.at(0)->buffer,m_windowSize.width(),m_windowSize.height(), - QImage::Format_RGB32).rgbSwapped().mirrored(true); + QImage::Format_RGB32).mirrored(true); QVideoFrame frame(image); frame.setStartTime(frames.at(0)->time);