[vlc-devel] [RFC 44/82] qt: provide base implementation video sink to render video output within the interface
Pierre Lamot
pierre at videolabs.io
Fri Feb 1 14:01:48 CET 2019
VideoSurface provide a QQuickItem which can be embed within a QML scene to
represent the video node.
VideoSurfaceProvider is the actual implementation of the VideoSurface which will
be selected at runtime
VideoRenderer implement a video sink which will be in charge of rendering the video
---
modules/gui/qt/Makefile.am | 6 +
.../video_renderer/videorenderer.cpp | 63 +++++++
.../video_renderer/videorenderer.hpp | 37 ++++
.../video_renderer/videosurface.cpp | 170 ++++++++++++++++++
.../video_renderer/videosurface.hpp | 102 +++++++++++
5 files changed, 378 insertions(+)
create mode 100644 modules/gui/qt/components/video_renderer/videorenderer.cpp
create mode 100644 modules/gui/qt/components/video_renderer/videorenderer.hpp
create mode 100644 modules/gui/qt/components/video_renderer/videosurface.cpp
create mode 100644 modules/gui/qt/components/video_renderer/videosurface.hpp
diff --git a/modules/gui/qt/Makefile.am b/modules/gui/qt/Makefile.am
index d48aa0c1e2..c061c8a2bd 100644
--- a/modules/gui/qt/Makefile.am
+++ b/modules/gui/qt/Makefile.am
@@ -98,6 +98,10 @@ libqt_plugin_la_SOURCES = \
gui/qt/components/controller.cpp gui/qt/components/controller.hpp \
gui/qt/components/controller_widget.cpp \
gui/qt/components/controller_widget.hpp \
+ gui/qt/components/video_renderer/videosurface.cpp \
+ gui/qt/components/video_renderer/videosurface.hpp \
+ gui/qt/components/video_renderer/videorenderer.cpp \
+ gui/qt/components/video_renderer/videorenderer.hpp \
gui/qt/components/custom_menus.cpp \
gui/qt/components/custom_menus.hpp \
gui/qt/components/epg/EPGChannels.cpp \
@@ -216,6 +220,8 @@ nodist_libqt_plugin_la_SOURCES = \
gui/qt/components/controller.moc.cpp \
gui/qt/components/controller_widget.moc.cpp \
gui/qt/components/custom_menus.moc.cpp \
+ gui/qt/components/video_renderer/videosurface.moc.cpp \
+ gui/qt/components/video_renderer/videorenderer.moc.cpp \
gui/qt/components/epg/EPGChannels.moc.cpp \
gui/qt/components/epg/EPGProgram.moc.cpp \
gui/qt/components/epg/EPGRuler.moc.cpp \
diff --git a/modules/gui/qt/components/video_renderer/videorenderer.cpp b/modules/gui/qt/components/video_renderer/videorenderer.cpp
new file mode 100644
index 0000000000..09150f372d
--- /dev/null
+++ b/modules/gui/qt/components/video_renderer/videorenderer.cpp
@@ -0,0 +1,63 @@
+#include "videorenderer.hpp"
+
+VideoRenderer::VideoRenderer(QObject* parent)
+ : QObject(parent)
+{
+}
+
+void VideoRenderer::setupVoutWindow(vout_window_t* window)
+{
+ QMutexLocker lock(&m_voutlock);
+ m_voutWindow = window;
+ m_hasVideo = false;
+}
+
+void VideoRenderer::enableVideo(unsigned /*width*/, unsigned /*height*/, bool /*fullscreen*/)
+{
+ QMutexLocker lock(&m_voutlock);
+ if (m_voutWindow)
+ m_hasVideo = true;
+}
+
+void VideoRenderer::disableVideo()
+{
+ QMutexLocker lock(&m_voutlock);
+ if (m_voutWindow)
+ m_hasVideo = false;
+}
+
+void VideoRenderer::onMousePressed(int vlcButton)
+{
+ QMutexLocker lock(&m_voutlock);
+ if (m_hasVideo)
+ vout_window_ReportMousePressed(m_voutWindow, vlcButton);
+}
+
+void VideoRenderer::onMouseReleased(int vlcButton)
+{
+ QMutexLocker lock(&m_voutlock);
+ if (m_hasVideo)
+ vout_window_ReportMouseReleased(m_voutWindow, vlcButton);
+}
+
+void VideoRenderer::onMouseDoubleClick(int vlcButton)
+{
+ QMutexLocker lock(&m_voutlock);
+ if (m_hasVideo)
+ vout_window_ReportMouseDoubleClick(m_voutWindow, vlcButton);
+}
+
+void VideoRenderer::onMouseMoved(float x, float y)
+{
+ QMutexLocker lock(&m_voutlock);
+ if (m_hasVideo)
+ vout_window_ReportMouseMoved(m_voutWindow, x, y);
+}
+
+void VideoRenderer::onSurfaceSizeChanged(QSizeF size)
+{
+
+ QMutexLocker lock(&m_voutlock);
+ if (m_hasVideo)
+ vout_window_ReportSize(m_voutWindow, size.width(), size.height());
+}
diff --git a/modules/gui/qt/components/video_renderer/videorenderer.hpp b/modules/gui/qt/components/video_renderer/videorenderer.hpp
new file mode 100644
index 0000000000..98e3ea26c2
--- /dev/null
+++ b/modules/gui/qt/components/video_renderer/videorenderer.hpp
@@ -0,0 +1,37 @@
+#ifndef VIDEORENDERER_HPP
+#define VIDEORENDERER_HPP
+
+#include <QObject>
+#include <QMutex>
+#include "qt.hpp"
+#include "vlc_vout_window.h"
+#include "videosurface.hpp"
+
+class VideoRenderer : public QObject
+{
+ Q_OBJECT
+public:
+ VideoRenderer(QObject* parent = nullptr);
+ virtual ~VideoRenderer() {}
+
+ virtual void setupVoutWindow(vout_window_t* window);
+ virtual void enableVideo(unsigned width, unsigned height, bool fullscreen);
+ virtual void disableVideo();
+
+ virtual VideoSurfaceProvider* getVideoSurfaceProvider() = 0;
+
+public slots:
+ void onMousePressed( int vlcButton );
+ void onMouseReleased( int vlcButton );
+ void onMouseDoubleClick( int vlcButton );
+ void onMouseMoved( float x, float y );
+ void onSurfaceSizeChanged(QSizeF size);
+
+protected:
+ QMutex m_voutlock;
+ vout_window_t* m_voutWindow = nullptr;
+ bool m_hasVideo = false;
+
+};
+
+#endif // VIDEORENDERER_HPP
diff --git a/modules/gui/qt/components/video_renderer/videosurface.cpp b/modules/gui/qt/components/video_renderer/videosurface.cpp
new file mode 100644
index 0000000000..39b453c3c1
--- /dev/null
+++ b/modules/gui/qt/components/video_renderer/videosurface.cpp
@@ -0,0 +1,170 @@
+/*****************************************************************************
+ * Copyright (C) 2019 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+#include "videosurface.hpp"
+#include "main_interface.hpp"
+
+
+VideoSurfaceProvider::VideoSurfaceProvider(QObject* parent)
+ : QObject(parent)
+{
+}
+
+VideoSurface::VideoSurface(QQuickItem* parent)
+ : QQuickItem(parent)
+{
+ setAcceptHoverEvents(true);
+ setAcceptedMouseButtons(Qt::AllButtons);
+ setFlag(ItemAcceptsInputMethod, true);
+ setFlag(ItemHasContents, true);
+
+ connect(this, &QQuickItem::widthChanged, this, &VideoSurface::onSurfaceSizeChanged);
+ connect(this, &QQuickItem::heightChanged, this, &VideoSurface::onSurfaceSizeChanged);
+}
+
+QmlMainContext*VideoSurface::getCtx()
+{
+ return m_mainCtx;
+}
+
+void VideoSurface::setCtx(QmlMainContext* mainctx)
+{
+ m_mainCtx = mainctx;
+ emit ctxChanged(mainctx);
+}
+
+QSize VideoSurface::getSourceSize() const
+{
+ return m_sourceSize;
+}
+
+int VideoSurface::qtMouseButton2VLC( Qt::MouseButton qtButton )
+{
+ switch( qtButton )
+ {
+ case Qt::LeftButton:
+ return 0;
+ case Qt::RightButton:
+ return 2;
+ case Qt::MiddleButton:
+ return 1;
+ default:
+ return -1;
+ }
+}
+
+void VideoSurface::mousePressEvent(QMouseEvent* event)
+{
+ int vlc_button = qtMouseButton2VLC( event->button() );
+ if( vlc_button >= 0 )
+ {
+ emit mousePressed(vlc_button);
+ event->accept();
+ }
+ else
+ event->ignore();
+}
+
+void VideoSurface::mouseReleaseEvent(QMouseEvent* event)
+{
+ int vlc_button = qtMouseButton2VLC( event->button() );
+ if( vlc_button >= 0 )
+ {
+ emit mouseReleased(vlc_button);
+ event->accept();
+ }
+ else
+ event->ignore();
+}
+
+void VideoSurface::mouseMoveEvent(QMouseEvent* event)
+{
+ QPointF current_pos = event->localPos();
+ emit mouseMoved(current_pos.x() , current_pos.y());
+ event->accept();
+}
+
+void VideoSurface::hoverMoveEvent(QHoverEvent* event)
+{
+ QPointF current_pos = event->posF();
+ if (current_pos != m_oldHoverPos)
+ {
+ float scaleW = m_sourceSize.width() / width();
+ float scaleH = m_sourceSize.height() / height();
+ emit mouseMoved(current_pos.x() * scaleW, current_pos.y() * scaleH);
+ m_oldHoverPos = current_pos;
+ }
+ event->accept();
+}
+
+void VideoSurface::mouseDoubleClickEvent(QMouseEvent* event)
+{
+ int vlc_button = qtMouseButton2VLC( event->button() );
+ if( vlc_button >= 0 )
+ {
+ emit mouseDblClicked(vlc_button);
+ event->accept();
+ }
+ else
+ event->ignore();
+}
+
+Qt::CursorShape VideoSurface::getCursorShape() const
+{
+ return cursor().shape();
+}
+
+void VideoSurface::setCursorShape(Qt::CursorShape shape)
+{
+ setCursor(shape);
+}
+
+QSGNode*VideoSurface::updatePaintNode(QSGNode* node, QQuickItem::UpdatePaintNodeData* nodeData)
+{
+ if (m_provider == nullptr) {
+ if (m_mainCtx == nullptr)
+ return nullptr;
+ m_provider = m_mainCtx->getMainInterface()->getVideoSurfaceProvider();
+ if (!m_provider)
+ return nullptr;
+
+ //forward signal to the provider
+ connect(this, &VideoSurface::mouseMoved, m_provider, &VideoSurfaceProvider::mouseMoved);
+ connect(this, &VideoSurface::mousePressed, m_provider, &VideoSurfaceProvider::mousePressed);
+ connect(this, &VideoSurface::mouseDblClicked, m_provider, &VideoSurfaceProvider::mouseDblClicked);
+ connect(this, &VideoSurface::mouseReleased, m_provider, &VideoSurfaceProvider::mouseReleased);
+
+ connect(this, &VideoSurface::surfaceSizeChanged, m_provider, &VideoSurfaceProvider::surfaceSizeChanged);
+
+ connect(m_provider, &VideoSurfaceProvider::update, this, &VideoSurface::update);
+ connect(m_provider, &VideoSurfaceProvider::sourceSizeChanged, this, &VideoSurface::onSourceSizeChanged);
+ }
+ return m_provider->updatePaintNode(this, node, nodeData);
+}
+
+void VideoSurface::onSourceSizeChanged(QSize newSize)
+{
+ if (newSize != m_sourceSize) {
+ m_sourceSize = newSize;
+ emit sourceSizeChanged(m_sourceSize);
+ }
+}
+
+void VideoSurface::onSurfaceSizeChanged()
+{
+ emit surfaceSizeChanged(size());
+}
diff --git a/modules/gui/qt/components/video_renderer/videosurface.hpp b/modules/gui/qt/components/video_renderer/videosurface.hpp
new file mode 100644
index 0000000000..41cb257a0a
--- /dev/null
+++ b/modules/gui/qt/components/video_renderer/videosurface.hpp
@@ -0,0 +1,102 @@
+/*****************************************************************************
+ * Copyright (C) 2019 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+#ifndef VIDEOSURFACE_HPP
+#define VIDEOSURFACE_HPP
+
+#include <QtQuick/QQuickItem>
+#include <QCursor>
+#include <components/qml_main_context.hpp>
+#include "qt.hpp"
+
+class VideoSurfaceProvider : public QObject
+{
+ Q_OBJECT
+public:
+ VideoSurfaceProvider(QObject* parent);
+ virtual ~VideoSurfaceProvider() {}
+ virtual QSGNode* updatePaintNode(QQuickItem* item, QSGNode* oldNode, QQuickItem::UpdatePaintNodeData*) = 0;
+
+signals:
+ void ctxChanged(QmlMainContext*);
+ void sourceSizeChanged(QSize);
+
+ void surfaceSizeChanged(QSizeF);
+
+ void mousePressed( int vlcButton );
+ void mouseReleased( int vlcButton );
+ void mouseDblClicked( int vlcButton );
+ void mouseMoved( float x, float y );
+
+ void update();
+};
+
+
+class VideoSurface : public QQuickItem
+{
+ Q_OBJECT
+ Q_PROPERTY(QmlMainContext* ctx READ getCtx WRITE setCtx NOTIFY ctxChanged)
+ Q_PROPERTY(QSize sourceSize READ getSourceSize NOTIFY sourceSizeChanged)
+ Q_PROPERTY(Qt::CursorShape cursorShape READ getCursorShape WRITE setCursorShape RESET unsetCursor)
+
+public:
+ VideoSurface( QQuickItem* parent = nullptr );
+
+ QmlMainContext* getCtx();
+ void setCtx(QmlMainContext* mainctx);
+
+ QSize getSourceSize() const;
+
+protected:
+ int qtMouseButton2VLC( Qt::MouseButton qtButton );
+
+ virtual void mousePressEvent(QMouseEvent *event) override;
+ virtual void mouseReleaseEvent(QMouseEvent *event) override;
+ virtual void mouseMoveEvent(QMouseEvent *event) override;
+ virtual void hoverMoveEvent(QHoverEvent *event) override;
+ virtual void mouseDoubleClickEvent(QMouseEvent *event) override;
+
+ Qt::CursorShape getCursorShape() const;
+ void setCursorShape(Qt::CursorShape);
+
+ virtual QSGNode* updatePaintNode(QSGNode *, QQuickItem::UpdatePaintNodeData *) override;
+
+signals:
+ void ctxChanged(QmlMainContext*);
+ void sourceSizeChanged(QSize);
+ void surfaceSizeChanged(QSizeF);
+
+ void mousePressed( int vlcButton );
+ void mouseReleased( int vlcButton );
+ void mouseDblClicked( int vlcButton );
+ void mouseMoved( float x, float y );
+
+private slots:
+ void onSourceSizeChanged(QSize);
+ void onSurfaceSizeChanged();
+
+private:
+ QmlMainContext* m_mainCtx = nullptr;
+
+ bool m_sourceSizeChanged = false;
+ QSize m_sourceSize;
+ QPointF m_oldHoverPos;
+
+ VideoSurfaceProvider* m_provider = nullptr;
+};
+
+#endif // VIDEOSURFACE_HPP
--
2.19.1
More information about the vlc-devel
mailing list