diff options
author | VaL Doroshchuk <valentyn.doroshchuk@qt.io> | 2018-10-23 14:47:18 +0200 |
---|---|---|
committer | VaL Doroshchuk <valentyn.doroshchuk@qt.io> | 2018-11-06 11:49:17 +0000 |
commit | 9800e9d1204174eeabff4c8c0a3b14c1f1657828 (patch) | |
tree | c69bda2c70c04125e3e115c1a47ce3b70a97de2a /src/qtmultimediaquicktools | |
parent | 2a77249b1954f0c57ab9de41cf96345b9e575ee7 (diff) |
VideoOutput: Introduce flushMode property
Added flushMode property to QML VideoOutput element to define
what should be shown when flush is requested.
Takes affect only for QDeclarativeVideoRendererBackend
and when QSGVideoItemSurface is already started.
Flushing (passing empty video frame to the surface) is usually performed
when EndOfMedia or playback is stopped.
Which caused disappearing the content and blinking if playlist is used.
Using this property now possible to define
what frame (last, first or empty) should be shown when playback is stopped or finished.
By default shows empty frame (clears the video output).
To show a frame it requires to keep QVideoFrame and thus its data.
Task-number: QTBUG-37301
Task-number: QTBUG-49446
Change-Id: I3be5309217b9f543da804e3b616dee9d97fba65f
Reviewed-by: Andy Shaw <andy.shaw@qt.io>
Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
Diffstat (limited to 'src/qtmultimediaquicktools')
3 files changed, 41 insertions, 7 deletions
diff --git a/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp b/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp index 3c6a6f9c5..fccab54ab 100644 --- a/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp +++ b/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp @@ -878,4 +878,28 @@ void QDeclarativeVideoOutput::_q_invalidateSceneGraph() m_backend->invalidateSceneGraph(); } +/*! + \qmlproperty enumeration QtMultimedia::VideoOutput::flushMode + + Set this property to define what \c VideoOutput should show + when playback is finished or stopped. + + \list + \li EmptyFrame - clears video output. + \li FirstFrame - shows the first valid frame. + \li LastFrame - shows the last valid frame. + \endlist + + The default flush mode is EmptyFrame. +*/ + +void QDeclarativeVideoOutput::setFlushMode(FlushMode mode) +{ + if (m_flushMode == mode) + return; + + m_flushMode = mode; + emit flushModeChanged(); +} + QT_END_NAMESPACE diff --git a/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp b/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp index c51aec088..007e52409 100644 --- a/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp +++ b/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp @@ -210,13 +210,13 @@ void QDeclarativeVideoRendererBackend::releaseControl() QSize QDeclarativeVideoRendererBackend::nativeSize() const { - return m_surface->surfaceFormat().sizeHint(); + return m_surfaceFormat.sizeHint(); } void QDeclarativeVideoRendererBackend::updateGeometry() { - const QRectF viewport = videoSurface()->surfaceFormat().viewport(); - const QSizeF frameSize = videoSurface()->surfaceFormat().frameSize(); + const QRectF viewport = m_surfaceFormat.viewport(); + const QSizeF frameSize = m_surfaceFormat.frameSize(); const QRectF normalizedViewport(viewport.x() / frameSize.width(), viewport.y() / frameSize.height(), viewport.width() / frameSize.width(), @@ -257,13 +257,13 @@ void QDeclarativeVideoRendererBackend::updateGeometry() } } - if (videoSurface()->surfaceFormat().scanLineDirection() == QVideoSurfaceFormat::BottomToTop) { + if (m_surfaceFormat.scanLineDirection() == QVideoSurfaceFormat::BottomToTop) { qreal top = m_sourceTextureRect.top(); m_sourceTextureRect.setTop(m_sourceTextureRect.bottom()); m_sourceTextureRect.setBottom(top); } - if (videoSurface()->surfaceFormat().property("mirrored").toBool()) { + if (m_surfaceFormat.property("mirrored").toBool()) { qreal left = m_sourceTextureRect.left(); m_sourceTextureRect.setLeft(m_sourceTextureRect.right()); m_sourceTextureRect.setRight(left); @@ -294,7 +294,7 @@ QSGNode *QDeclarativeVideoRendererBackend::updatePaintNode(QSGNode *oldNode, if (m_frameChanged) { // Run the VideoFilter if there is one. This must be done before potentially changing the videonode below. if (m_frame.isValid() && !m_filters.isEmpty()) { - const QVideoSurfaceFormat surfaceFormat = videoSurface()->surfaceFormat(); + const QVideoSurfaceFormat surfaceFormat = m_surfaceFormat; for (int i = 0; i < m_filters.count(); ++i) { QAbstractVideoFilter *filter = m_filters[i].filter; QVideoFilterRunnable *&runnable = m_filters[i].runnable; @@ -367,6 +367,12 @@ QSGNode *QDeclarativeVideoRendererBackend::updatePaintNode(QSGNode *oldNode, if (isFrameModified) flags |= QSGVideoNode::FrameFiltered; videoNode->setCurrentFrame(m_frame, flags); + + if ((q->flushMode() == QDeclarativeVideoOutput::FirstFrame && !m_frameOnFlush.isValid()) + || q->flushMode() == QDeclarativeVideoOutput::LastFrame) { + m_frameOnFlush = m_frame; + } + //don't keep the frame for more than really necessary m_frameChanged = false; m_frame = QVideoFrame(); @@ -403,7 +409,7 @@ QOpenGLContext *QDeclarativeVideoRendererBackend::glContext() const void QDeclarativeVideoRendererBackend::present(const QVideoFrame &frame) { m_frameMutex.lock(); - m_frame = frame; + m_frame = frame.isValid() ? frame : m_frameOnFlush; m_frameChanged = true; m_frameMutex.unlock(); @@ -450,10 +456,12 @@ QList<QVideoFrame::PixelFormat> QSGVideoItemSurface::supportedPixelFormats( bool QSGVideoItemSurface::start(const QVideoSurfaceFormat &format) { qCDebug(qLcVideo) << "Video surface format:" << format << "all supported formats:" << supportedPixelFormats(format.handleType()); + m_backend->m_frameOnFlush = QVideoFrame(); if (!supportedPixelFormats(format.handleType()).contains(format.pixelFormat())) return false; + m_backend->m_surfaceFormat = format; return QAbstractVideoSurface::start(format); } diff --git a/src/qtmultimediaquicktools/qdeclarativevideooutput_render_p.h b/src/qtmultimediaquicktools/qdeclarativevideooutput_render_p.h index 4f1a90c8b..c69e74150 100644 --- a/src/qtmultimediaquicktools/qdeclarativevideooutput_render_p.h +++ b/src/qtmultimediaquicktools/qdeclarativevideooutput_render_p.h @@ -100,8 +100,10 @@ private: QPointer<QVideoRendererControl> m_rendererControl; QList<QSGVideoNodeFactoryInterface*> m_videoNodeFactories; QSGVideoItemSurface *m_surface; + QVideoSurfaceFormat m_surfaceFormat; QOpenGLContext *m_glContext; QVideoFrame m_frame; + QVideoFrame m_frameOnFlush; bool m_frameChanged; QSGVideoNodeFactory_YUV m_i420Factory; QSGVideoNodeFactory_RGB m_rgbFactory; |