diff options
author | Lars Knoll <lars.knoll@qt.io> | 2021-03-18 14:42:35 +0100 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2021-04-06 08:08:40 +0000 |
commit | f67cea4dd9c2ba44c85267962655235c6143a966 (patch) | |
tree | 4590d90f6f37e21a37cdd05c8e5d55193365b67e /src/qtmultimediaquicktools | |
parent | 782711418999c8e1f5914e805124ba7014687f93 (diff) |
Fix QML video rendering
Use the new QVideoSink class to get the video frames.
Fix some APIs, so that we correctly connect VideoOutput and
MediaPlayer.
Change-Id: I65a0d045988c46a917f70dfb922c1bbdb32f6511
Reviewed-by: Doris Verria <doris.verria@qt.io>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/qtmultimediaquicktools')
4 files changed, 29 insertions, 95 deletions
diff --git a/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp b/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp index 1cd331279..68d03bb95 100644 --- a/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp +++ b/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp @@ -46,6 +46,8 @@ #include <QtMultimedia/qmediacapturesession.h> #include <private/qfactoryloader_p.h> #include <QtCore/qloggingcategory.h> +#include <qvideosink.h> + static void initResource() { Q_INIT_RESOURCE(qtmultimediaquicktools); @@ -157,9 +159,9 @@ QDeclarativeVideoOutput::~QDeclarativeVideoOutput() \sa source */ -QAbstractVideoSurface *QDeclarativeVideoOutput::videoSurface() const +QVideoSink *QDeclarativeVideoOutput::videoSink() const { - return m_backend ? m_backend->videoSurface() : nullptr; + return m_backend ? m_backend->videoSink() : nullptr; } /*! @@ -186,9 +188,9 @@ void QDeclarativeVideoOutput::setSource(QObject *source) } if (QMediaCaptureSession *s = qobject_cast<QMediaCaptureSession *>(source)) { - s->setVideoPreview(videoSurface()); + s->setVideoPreview(videoSink()); } else if (QMediaPlayer *p = qobject_cast<QMediaPlayer *>(source)) { - p->setVideoOutput(videoSurface()); + p->setVideoOutput(videoSink()); } emit sourceChanged(); } @@ -238,12 +240,13 @@ void QDeclarativeVideoOutput::setFillMode(FillMode mode) emit fillModeChanged(mode); } -void QDeclarativeVideoOutput::_q_updateNativeSize() +void QDeclarativeVideoOutput::_q_newFrame(const QVideoFrame &frame) { if (!m_backend) return; - QSize size = m_backend->nativeSize(); + m_backend->present(frame); + QSize size = frame.size(); if (!qIsDefaultAspect(m_orientation)) { size.transpose(); } @@ -289,12 +292,8 @@ void QDeclarativeVideoOutput::_q_updateGeometry() m_contentRect.moveCenter(rect.center()); } - if (m_backend) { - if (!m_backend->videoSurface() || m_backend->videoSurface()->isActive()) - m_backend->updateGeometry(); - else - m_geometryDirty = true; - } + if (m_backend) + m_backend->updateGeometry(); if (m_contentRect != oldContentRect) diff --git a/src/qtmultimediaquicktools/qdeclarativevideooutput_p.h b/src/qtmultimediaquicktools/qdeclarativevideooutput_p.h index 7a4111602..264744520 100644 --- a/src/qtmultimediaquicktools/qdeclarativevideooutput_p.h +++ b/src/qtmultimediaquicktools/qdeclarativevideooutput_p.h @@ -66,7 +66,7 @@ QT_BEGIN_NAMESPACE class QDeclarativeVideoBackend; class QVideoOutputOrientationHandler; -class QAbstractVideoSurface; +class QVideoSink; class Q_MULTIMEDIAQUICK_EXPORT QDeclarativeVideoOutput : public QQuickItem { @@ -80,9 +80,10 @@ class Q_MULTIMEDIAQUICK_EXPORT QDeclarativeVideoOutput : public QQuickItem Q_PROPERTY(QRectF contentRect READ contentRect NOTIFY contentRectChanged) Q_PROPERTY(QQmlListProperty<QAbstractVideoFilter> filters READ filters); Q_PROPERTY(FlushMode flushMode READ flushMode WRITE setFlushMode NOTIFY flushModeChanged REVISION 13) - Q_PROPERTY(QAbstractVideoSurface* videoSurface READ videoSurface CONSTANT REVISION 15) + Q_PROPERTY(QVideoSink* videoSink READ videoSink CONSTANT REVISION 15) Q_ENUMS(FlushMode) Q_ENUMS(FillMode) + Q_MOC_INCLUDE(qvideosink.h) public: @@ -106,7 +107,7 @@ public: QObject *source() const { return m_source.data(); } void setSource(QObject *source); - Q_INVOKABLE QAbstractVideoSurface *videoSurface() const; + Q_INVOKABLE QVideoSink *videoSink() const; FillMode fillMode() const; void setFillMode(FillMode mode); @@ -157,7 +158,7 @@ protected: void releaseResources() override; private Q_SLOTS: - void _q_updateNativeSize(); + void _q_newFrame(const QVideoFrame &); void _q_updateGeometry(); void _q_screenOrientationChanged(int); void _q_invalidateSceneGraph(); diff --git a/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp b/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp index 10aead543..6ae8aa7be 100644 --- a/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp +++ b/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp @@ -45,6 +45,7 @@ #include <QtCore/qloggingcategory.h> #include <private/qmediapluginloader_p.h> #include <private/qsgvideonode_p.h> +#include <qvideosink.h> #include <QtQuick/QQuickWindow> #include <QtCore/QRunnable> @@ -60,9 +61,10 @@ QDeclarativeVideoBackend::QDeclarativeVideoBackend(QDeclarativeVideoOutput *pare : q(parent), m_frameChanged(false) { - m_surface = new QSGVideoItemSurface(this); - QObject::connect(m_surface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)), - q, SLOT(_q_updateNativeSize()), Qt::QueuedConnection); + m_sink = new QVideoSink(q); + qRegisterMetaType<QVideoSurfaceFormat>(); + QObject::connect(m_sink, SIGNAL(newVideoFrame(const QVideoFrame &)), + q, SLOT(_q_newFrame(const QVideoFrame &)), Qt::QueuedConnection); // Prioritize the plugin requested by the environment QString requestedVideoNode = QString::fromLatin1(qgetenv("QT_VIDEONODE")); @@ -88,7 +90,7 @@ QDeclarativeVideoBackend::QDeclarativeVideoBackend(QDeclarativeVideoOutput *pare QDeclarativeVideoBackend::~QDeclarativeVideoBackend() { - delete m_surface; + delete m_sink; } void QDeclarativeVideoBackend::appendFilter(QAbstractVideoFilter *filter) @@ -286,6 +288,7 @@ QSGNode *QDeclarativeVideoBackend::updatePaintNode(QSGNode *oldNode, nodeFormat.setFrameRate(m_surfaceFormat.frameRate()); // Update current surface format if something has changed. m_surfaceFormat = nodeFormat; + updateGeometry(); videoNode = factory->createNode(nodeFormat); if (videoNode) { qCDebug(qLcVideo) << "updatePaintNode: Video node created. Handle type:" << m_frame.handleType() @@ -326,9 +329,9 @@ QSGNode *QDeclarativeVideoBackend::updatePaintNode(QSGNode *oldNode, return videoNode; } -QAbstractVideoSurface *QDeclarativeVideoBackend::videoSurface() const +QVideoSink *QDeclarativeVideoBackend::videoSink() const { - return m_surface; + return m_sink; } QRectF QDeclarativeVideoBackend::adjustedViewport() const @@ -339,6 +342,7 @@ QRectF QDeclarativeVideoBackend::adjustedViewport() const void QDeclarativeVideoBackend::present(const QVideoFrame &frame) { m_frameMutex.lock(); + m_surfaceFormat = QVideoSurfaceFormat(frame.size(), frame.pixelFormat(), QVideoFrame::NoHandle); m_frame = frame.isValid() ? frame : m_frameOnFlush; m_frameChanged = true; m_frameMutex.unlock(); @@ -351,58 +355,4 @@ void QDeclarativeVideoBackend::stop() present(QVideoFrame()); } -QSGVideoItemSurface::QSGVideoItemSurface(QDeclarativeVideoBackend *backend, QObject *parent) - : QAbstractVideoSurface(parent), - m_backend(backend) -{ -} - -QSGVideoItemSurface::~QSGVideoItemSurface() = default; - -QList<QVideoFrame::PixelFormat> QSGVideoItemSurface::supportedPixelFormats( - QVideoFrame::HandleType handleType) const -{ - QList<QVideoFrame::PixelFormat> formats; - - static bool noGLTextures = false; - static bool noGLTexturesChecked = false; - if (handleType == QVideoFrame::GLTextureHandle) { - if (!noGLTexturesChecked) { - noGLTexturesChecked = true; - noGLTextures = qEnvironmentVariableIsSet("QT_QUICK_NO_TEXTURE_VIDEOFRAMES"); - } - if (noGLTextures) - return formats; - } - - for (QSGVideoNodeFactoryInterface* factory : qAsConst(m_backend->m_videoNodeFactories)) - formats.append(factory->supportedPixelFormats(handleType)); - - return formats; -} - -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); -} - -void QSGVideoItemSurface::stop() -{ - m_backend->stop(); - QAbstractVideoSurface::stop(); -} - -bool QSGVideoItemSurface::present(const QVideoFrame &frame) -{ - m_backend->present(frame); - return true; -} - QT_END_NAMESPACE diff --git a/src/qtmultimediaquicktools/qdeclarativevideooutput_render_p.h b/src/qtmultimediaquicktools/qdeclarativevideooutput_render_p.h index 17ed319e0..874b237ca 100644 --- a/src/qtmultimediaquicktools/qdeclarativevideooutput_render_p.h +++ b/src/qtmultimediaquicktools/qdeclarativevideooutput_render_p.h @@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE -class QSGVideoItemSurface; +class QVideoSink; class QObject; class QAbstractVideoFilter; class QVideoFilterRunnable; @@ -79,7 +79,7 @@ public: QSize nativeSize() const; void updateGeometry(); QSGNode *updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *data); - QAbstractVideoSurface *videoSurface() const; + QVideoSink *videoSink() const; QRectF adjustedViewport() const; friend class QSGVideoItemSurface; @@ -96,7 +96,7 @@ private: QDeclarativeVideoOutput *q; QList<QSGVideoNodeFactoryInterface*> m_videoNodeFactories; - QSGVideoItemSurface *m_surface; + QVideoSink *m_sink; QVideoSurfaceFormat m_surfaceFormat; QVideoFrame m_frame; @@ -118,22 +118,6 @@ private: QList<Filter> m_filters; }; -class QSGVideoItemSurface : public QAbstractVideoSurface -{ - Q_OBJECT -public: - explicit QSGVideoItemSurface(QDeclarativeVideoBackend *backend, QObject *parent = 0); - ~QSGVideoItemSurface(); - QList<QVideoFrame::PixelFormat> supportedPixelFormats(QVideoFrame::HandleType handleType) const override; - bool start(const QVideoSurfaceFormat &format) override; - void stop() override; - bool present(const QVideoFrame &frame) override; - -private: - QDeclarativeVideoBackend *m_backend; -}; - - namespace { inline bool qIsDefaultAspect(int o) |