summaryrefslogtreecommitdiffstats
path: root/src/qtmultimediaquicktools
diff options
context:
space:
mode:
Diffstat (limited to 'src/qtmultimediaquicktools')
-rw-r--r--src/qtmultimediaquicktools/qdeclarativevideooutput.cpp49
-rw-r--r--src/qtmultimediaquicktools/qdeclarativevideooutput_p.h4
-rw-r--r--src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp7
-rw-r--r--src/qtmultimediaquicktools/qsgvideonode_texture.cpp147
-rw-r--r--src/qtmultimediaquicktools/qsgvideonode_texture_p.h2
-rw-r--r--src/qtmultimediaquicktools/qtmultimediaquicktools.qrc5
-rw-r--r--src/qtmultimediaquicktools/shaders/rectsampler.vert10
-rw-r--r--src/qtmultimediaquicktools/shaders/rectsampler_core.vert11
-rw-r--r--src/qtmultimediaquicktools/shaders/rectsampler_rgb.frag8
-rw-r--r--src/qtmultimediaquicktools/shaders/rectsampler_rgb_core.frag10
10 files changed, 200 insertions, 53 deletions
diff --git a/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp b/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp
index 32166502d..a948a5218 100644
--- a/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp
+++ b/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp
@@ -138,6 +138,7 @@ QDeclarativeVideoOutput::QDeclarativeVideoOutput(QQuickItem *parent) :
{
initResource();
setFlag(ItemHasContents, true);
+ createBackend(nullptr);
}
QDeclarativeVideoOutput::~QDeclarativeVideoOutput()
@@ -148,6 +149,23 @@ QDeclarativeVideoOutput::~QDeclarativeVideoOutput()
}
/*!
+ \qmlproperty object QtMultimedia::VideoOutput::videoSurface
+ \since 5.15
+
+ This property holds the underlaying video surface that can be used
+ to render the video frames to this VideoOutput element.
+ It is similar to setting a QObject with \c videoSurface property as a source,
+ where this video surface will be set.
+
+ \sa source
+*/
+
+QAbstractVideoSurface *QDeclarativeVideoOutput::videoSurface() const
+{
+ return m_backend ? m_backend->videoSurface() : nullptr;
+}
+
+/*!
\qmlproperty variant QtMultimedia::VideoOutput::source
This property holds the source item providing the video frames like MediaPlayer or Camera.
@@ -206,21 +224,10 @@ void QDeclarativeVideoOutput::setSource(QObject *source)
}
m_sourceType = MediaObjectSource;
-#if QT_CONFIG(opengl)
} else if (metaObject->indexOfProperty("videoSurface") != -1) {
- // Make sure our backend is a QDeclarativeVideoRendererBackend
- m_backend.reset();
- createBackend(0);
- Q_ASSERT(m_backend);
-#ifndef QT_NO_DYNAMIC_CAST
- Q_ASSERT(dynamic_cast<QDeclarativeVideoRendererBackend *>(m_backend.data()));
-#endif
- QAbstractVideoSurface * const surface = m_backend->videoSurface();
- Q_ASSERT(surface);
m_source.data()->setProperty("videoSurface",
- QVariant::fromValue<QAbstractVideoSurface*>(surface));
+ QVariant::fromValue<QAbstractVideoSurface *>(videoSurface()));
m_sourceType = VideoSurfaceSource;
-#endif
} else {
m_sourceType = NoSource;
}
@@ -242,7 +249,8 @@ bool QDeclarativeVideoOutput::createBackend(QMediaService *service)
const auto instances = videoBackendFactoryLoader()->instances(QLatin1String("declarativevideobackend"));
for (QObject *instance : instances) {
if (QDeclarativeVideoBackendFactoryInterface *plugin = qobject_cast<QDeclarativeVideoBackendFactoryInterface*>(instance)) {
- m_backend.reset(plugin->create(this));
+ if (!m_backend)
+ m_backend.reset(plugin->create(this));
if (m_backend && m_backend->init(service)) {
backendAvailable = true;
break;
@@ -251,7 +259,8 @@ bool QDeclarativeVideoOutput::createBackend(QMediaService *service)
}
#if QT_CONFIG(opengl)
if (!backendAvailable) {
- m_backend.reset(new QDeclarativeVideoRendererBackend(this));
+ if (!m_backend)
+ m_backend.reset(new QDeclarativeVideoRendererBackend(this));
if (m_backend->init(service))
backendAvailable = true;
}
@@ -293,9 +302,6 @@ void QDeclarativeVideoOutput::_q_updateMediaObject()
if (m_mediaObject.data() == mediaObject)
return;
- if (m_sourceType != VideoSurfaceSource)
- m_backend.reset();
-
m_mediaObject.clear();
m_service.clear();
@@ -368,6 +374,8 @@ void QDeclarativeVideoOutput::_q_updateNativeSize()
if (!m_backend)
return;
+ m_geometryDirty = true;
+
QSize size = m_backend->nativeSize();
if (!qIsDefaultAspect(m_orientation)) {
size.transpose();
@@ -376,8 +384,6 @@ void QDeclarativeVideoOutput::_q_updateNativeSize()
if (m_nativeSize != size) {
m_nativeSize = size;
- m_geometryDirty = true;
-
setImplicitWidth(size.width());
setImplicitHeight(size.height());
@@ -415,9 +421,8 @@ void QDeclarativeVideoOutput::_q_updateGeometry()
}
if (m_backend) {
- if (!m_backend->videoSurface() || m_backend->videoSurface()->isActive())
- m_backend->updateGeometry();
- else
+ m_backend->updateGeometry();
+ if (m_backend->videoSurface() && !m_backend->videoSurface()->isActive())
m_geometryDirty = true;
}
diff --git a/src/qtmultimediaquicktools/qdeclarativevideooutput_p.h b/src/qtmultimediaquicktools/qdeclarativevideooutput_p.h
index 8ea0dc338..d14731c91 100644
--- a/src/qtmultimediaquicktools/qdeclarativevideooutput_p.h
+++ b/src/qtmultimediaquicktools/qdeclarativevideooutput_p.h
@@ -67,6 +67,7 @@ class QMediaObject;
class QMediaService;
class QDeclarativeVideoBackend;
class QVideoOutputOrientationHandler;
+class QAbstractVideoSurface;
class Q_MULTIMEDIAQUICK_EXPORT QDeclarativeVideoOutput : public QQuickItem
{
@@ -80,6 +81,7 @@ 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_ENUMS(FlushMode)
Q_ENUMS(FillMode)
@@ -102,6 +104,8 @@ public:
QDeclarativeVideoOutput(QQuickItem *parent = 0);
~QDeclarativeVideoOutput();
+ QAbstractVideoSurface *videoSurface() const;
+
QObject *source() const { return m_source.data(); }
void setSource(QObject *source);
diff --git a/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp b/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp
index 863cefa4e..bdfa23dfb 100644
--- a/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp
+++ b/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp
@@ -46,7 +46,6 @@
#include <QtCore/qloggingcategory.h>
#include <private/qmediapluginloader_p.h>
#include <private/qsgvideonode_p.h>
-#include <private/qvideoframe_p.h>
#include <QtGui/QOpenGLContext>
#include <QtQuick/QQuickWindow>
@@ -304,7 +303,7 @@ QSGNode *QDeclarativeVideoRendererBackend::updatePaintNode(QSGNode *oldNode,
if (!runnable)
continue;
- QVideoFilterRunnable::RunFlags flags = 0;
+ QVideoFilterRunnable::RunFlags flags;
if (i == m_filters.count() - 1)
flags |= QVideoFilterRunnable::LastInChain;
@@ -363,7 +362,7 @@ QSGNode *QDeclarativeVideoRendererBackend::updatePaintNode(QSGNode *oldNode,
videoNode->setTexturedRectGeometry(m_renderedRect, m_sourceTextureRect,
qNormalizedOrientation(q->orientation()));
if (m_frameChanged) {
- QSGVideoNode::FrameFlags flags = 0;
+ QSGVideoNode::FrameFlags flags;
if (isFrameModified)
flags |= QSGVideoNode::FrameFiltered;
videoNode->setCurrentFrame(m_frame, flags);
@@ -372,7 +371,7 @@ QSGNode *QDeclarativeVideoRendererBackend::updatePaintNode(QSGNode *oldNode,
|| q->flushMode() == QDeclarativeVideoOutput::LastFrame) {
m_frameOnFlush = m_surfaceFormat.handleType() == QAbstractVideoBuffer::NoHandle
? m_frame
- : qt_imageFromVideoFrame(m_frame);
+ : m_frame.image();
}
//don't keep the frame for more than really necessary
diff --git a/src/qtmultimediaquicktools/qsgvideonode_texture.cpp b/src/qtmultimediaquicktools/qsgvideonode_texture.cpp
index 473a4144f..bac143b43 100644
--- a/src/qtmultimediaquicktools/qsgvideonode_texture.cpp
+++ b/src/qtmultimediaquicktools/qsgvideonode_texture.cpp
@@ -53,6 +53,13 @@ QList<QVideoFrame::PixelFormat> QSGVideoNodeFactory_Texture::supportedPixelForma
{
QList<QVideoFrame::PixelFormat> pixelFormats;
+#ifdef Q_OS_MACOS
+ if (handleType == QAbstractVideoBuffer::GLTextureRectangleHandle) {
+ pixelFormats.append(QVideoFrame::Format_BGR32);
+ pixelFormats.append(QVideoFrame::Format_BGRA32);
+ }
+#endif
+
if (handleType == QAbstractVideoBuffer::GLTextureHandle) {
pixelFormats.append(QVideoFrame::Format_RGB565);
pixelFormats.append(QVideoFrame::Format_RGB32);
@@ -82,8 +89,6 @@ public:
QSGVideoMaterialShader_Texture()
: QSGMaterialShader()
{
- setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/qtmultimediaquicktools/shaders/monoplanarvideo.vert"));
- setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qtmultimediaquicktools/shaders/rgbvideo.frag"));
}
void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
@@ -109,10 +114,20 @@ protected:
int m_id_opacity;
};
-class QSGVideoMaterialShader_Texture_swizzle : public QSGVideoMaterialShader_Texture
+class QSGVideoMaterialShader_Texture_2D : public QSGVideoMaterialShader_Texture
{
public:
- QSGVideoMaterialShader_Texture_swizzle(bool hasAlpha)
+ QSGVideoMaterialShader_Texture_2D()
+ {
+ setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/qtmultimediaquicktools/shaders/monoplanarvideo.vert"));
+ setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qtmultimediaquicktools/shaders/rgbvideo.frag"));
+ }
+};
+
+class QSGVideoMaterialShader_Texture_2D_swizzle : public QSGVideoMaterialShader_Texture_2D
+{
+public:
+ QSGVideoMaterialShader_Texture_2D_swizzle(bool hasAlpha)
: m_hasAlpha(hasAlpha)
{
setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qtmultimediaquicktools/shaders/rgbvideo_swizzle.frag"));
@@ -120,14 +135,13 @@ public:
protected:
void initialize() override {
- QSGVideoMaterialShader_Texture::initialize();
+ QSGVideoMaterialShader_Texture_2D::initialize();
program()->setUniformValue(program()->uniformLocation("hasAlpha"), GLboolean(m_hasAlpha));
}
int m_hasAlpha;
};
-
class QSGVideoMaterial_Texture : public QSGMaterial
{
public:
@@ -149,12 +163,6 @@ public:
return needsSwizzling() ? &swizzleType : &normalType;
}
- QSGMaterialShader *createShader() const override {
- const bool hasAlpha = m_format.pixelFormat() == QVideoFrame::Format_ARGB32;
- return needsSwizzling() ? new QSGVideoMaterialShader_Texture_swizzle(hasAlpha)
- : new QSGVideoMaterialShader_Texture;
- }
-
int compare(const QSGMaterial *other) const override {
const QSGVideoMaterial_Texture *m = static_cast<const QSGVideoMaterial_Texture *>(other);
@@ -179,9 +187,42 @@ public:
void setVideoFrame(const QVideoFrame &frame) {
QMutexLocker lock(&m_frameMutex);
m_frame = frame;
+ m_textureSize = frame.size();
+ }
+
+ virtual void bind() = 0;
+
+ QVideoFrame m_frame;
+ QMutex m_frameMutex;
+ QSize m_textureSize;
+ QVideoSurfaceFormat m_format;
+ GLuint m_textureId;
+ qreal m_opacity;
+
+protected:
+ bool needsSwizzling() const {
+ return !QMediaOpenGLHelper::isANGLE()
+ && (m_format.pixelFormat() == QVideoFrame::Format_RGB32
+ || m_format.pixelFormat() == QVideoFrame::Format_ARGB32);
+ }
+};
+
+class QSGVideoMaterial_Texture_2D : public QSGVideoMaterial_Texture
+{
+public:
+ QSGVideoMaterial_Texture_2D(const QVideoSurfaceFormat &format) :
+ QSGVideoMaterial_Texture(format)
+ {
}
- void bind()
+ QSGMaterialShader *createShader() const override
+ {
+ const bool hasAlpha = m_format.pixelFormat() == QVideoFrame::Format_ARGB32;
+ return needsSwizzling() ? new QSGVideoMaterialShader_Texture_2D_swizzle(hasAlpha)
+ : new QSGVideoMaterialShader_Texture_2D;
+ }
+
+ void bind() override
{
QMutexLocker lock(&m_frameMutex);
if (m_frame.isValid()) {
@@ -197,28 +238,84 @@ public:
m_textureId = 0;
}
}
+};
+
+#ifdef Q_OS_MACOS
+class QSGVideoMaterialShader_Texture_Rectangle : public QSGVideoMaterialShader_Texture
+{
+public:
+ QSGVideoMaterialShader_Texture_Rectangle()
+ {
+ setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/qtmultimediaquicktools/shaders/rectsampler.vert"));
+ setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qtmultimediaquicktools/shaders/rectsampler_rgb.frag"));
+ }
- QVideoFrame m_frame;
- QMutex m_frameMutex;
- QSize m_textureSize;
- QVideoSurfaceFormat m_format;
- GLuint m_textureId;
- qreal m_opacity;
+ void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override
+ {
+ QSGVideoMaterial_Texture *mat = static_cast<QSGVideoMaterial_Texture *>(newMaterial);
+ QVector2D size(mat->m_textureSize.width(), mat->m_textureSize.height());
+ program()->setUniformValue(m_id_videoSize, size);
-private:
- bool needsSwizzling() const {
- return !QMediaOpenGLHelper::isANGLE()
- && (m_format.pixelFormat() == QVideoFrame::Format_RGB32
- || m_format.pixelFormat() == QVideoFrame::Format_ARGB32);
+ QSGVideoMaterialShader_Texture::updateState(state, newMaterial, oldMaterial);
}
+
+protected:
+ void initialize() override
+ {
+ QSGVideoMaterialShader_Texture::initialize();
+ m_id_videoSize = program()->uniformLocation("qt_videoSize");
+ }
+
+ int m_id_videoSize;
};
+class QSGVideoMaterial_Texture_Rectangle : public QSGVideoMaterial_Texture
+{
+public:
+ QSGVideoMaterial_Texture_Rectangle(const QVideoSurfaceFormat &format) :
+ QSGVideoMaterial_Texture(format)
+ {
+ }
+
+ QSGMaterialShader *createShader() const override
+ {
+ Q_ASSERT(!needsSwizzling());
+ return new QSGVideoMaterialShader_Texture_Rectangle;
+ }
+
+ void bind() override
+ {
+ QMutexLocker lock(&m_frameMutex);
+ if (m_frame.isValid()) {
+ m_textureId = m_frame.handle().toUInt();
+ QOpenGLFunctions *functions = QOpenGLContext::currentContext()->functions();
+ functions->glActiveTexture(GL_TEXTURE0);
+ functions->glBindTexture(GL_TEXTURE_RECTANGLE, m_textureId);
+
+ functions->glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ functions->glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ functions->glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ functions->glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ } else {
+ m_textureId = 0;
+ }
+ }
+};
+#endif
QSGVideoNode_Texture::QSGVideoNode_Texture(const QVideoSurfaceFormat &format) :
m_format(format)
{
setFlag(QSGNode::OwnsMaterial);
- m_material = new QSGVideoMaterial_Texture(format);
+
+#ifdef Q_OS_MACOS
+ if (format.handleType() == QAbstractVideoBuffer::GLTextureRectangleHandle)
+ m_material = new QSGVideoMaterial_Texture_Rectangle(format);
+#endif
+
+ if (!m_material)
+ m_material = new QSGVideoMaterial_Texture_2D(format);
+
setMaterial(m_material);
}
diff --git a/src/qtmultimediaquicktools/qsgvideonode_texture_p.h b/src/qtmultimediaquicktools/qsgvideonode_texture_p.h
index 12685dd24..21c905bd5 100644
--- a/src/qtmultimediaquicktools/qsgvideonode_texture_p.h
+++ b/src/qtmultimediaquicktools/qsgvideonode_texture_p.h
@@ -74,7 +74,7 @@ public:
private:
QVideoSurfaceFormat m_format;
- QSGVideoMaterial_Texture *m_material;
+ QSGVideoMaterial_Texture *m_material = nullptr;
QVideoFrame m_frame;
};
diff --git a/src/qtmultimediaquicktools/qtmultimediaquicktools.qrc b/src/qtmultimediaquicktools/qtmultimediaquicktools.qrc
index b8180e31f..86523e771 100644
--- a/src/qtmultimediaquicktools/qtmultimediaquicktools.qrc
+++ b/src/qtmultimediaquicktools/qtmultimediaquicktools.qrc
@@ -11,7 +11,6 @@
<file>shaders/triplanaryuvvideo.vert</file>
<file>shaders/uyvyvideo.frag</file>
<file>shaders/yuyvvideo.frag</file>
-
<file>shaders/monoplanarvideo_core.vert</file>
<file>shaders/rgbvideo_core.frag</file>
<file>shaders/rgbvideo_swizzle_core.frag</file>
@@ -23,5 +22,9 @@
<file>shaders/triplanaryuvvideo_core.vert</file>
<file>shaders/uyvyvideo_core.frag</file>
<file>shaders/yuyvvideo_core.frag</file>
+ <file>shaders/rectsampler.vert</file>
+ <file>shaders/rectsampler_rgb.frag</file>
+ <file>shaders/rectsampler_core.vert</file>
+ <file>shaders/rectsampler_rgb_core.frag</file>
</qresource>
</RCC>
diff --git a/src/qtmultimediaquicktools/shaders/rectsampler.vert b/src/qtmultimediaquicktools/shaders/rectsampler.vert
new file mode 100644
index 000000000..762ec7e7e
--- /dev/null
+++ b/src/qtmultimediaquicktools/shaders/rectsampler.vert
@@ -0,0 +1,10 @@
+uniform highp mat4 qt_Matrix;
+uniform highp vec2 qt_videoSize;
+attribute highp vec4 qt_VertexPosition;
+attribute highp vec2 qt_VertexTexCoord;
+varying highp vec2 qt_TexCoord;
+
+void main() {
+ qt_TexCoord = vec2(qt_VertexTexCoord.x * qt_videoSize.x, qt_VertexTexCoord.y * qt_videoSize.y);
+ gl_Position = qt_Matrix * qt_VertexPosition;
+}
diff --git a/src/qtmultimediaquicktools/shaders/rectsampler_core.vert b/src/qtmultimediaquicktools/shaders/rectsampler_core.vert
new file mode 100644
index 000000000..f0fe02349
--- /dev/null
+++ b/src/qtmultimediaquicktools/shaders/rectsampler_core.vert
@@ -0,0 +1,11 @@
+#version 150 core
+uniform highp mat4 qt_Matrix;
+uniform highp vec2 qt_videoSize;
+in highp vec4 qt_VertexPosition;
+in highp vec2 qt_VertexTexCoord;
+out highp vec2 qt_TexCoord;
+
+void main() {
+ qt_TexCoord = vec2(qt_VertexTexCoord.x * qt_videoSize.x, qt_VertexTexCoord.y * qt_videoSize.y);
+ gl_Position = qt_Matrix * qt_VertexPosition;
+}
diff --git a/src/qtmultimediaquicktools/shaders/rectsampler_rgb.frag b/src/qtmultimediaquicktools/shaders/rectsampler_rgb.frag
new file mode 100644
index 000000000..2a30f7c3d
--- /dev/null
+++ b/src/qtmultimediaquicktools/shaders/rectsampler_rgb.frag
@@ -0,0 +1,8 @@
+uniform sampler2DRect rgbTexture;
+uniform lowp float opacity;
+varying highp vec2 qt_TexCoord;
+
+void main()
+{
+ gl_FragColor = texture2DRect(rgbTexture, qt_TexCoord) * opacity;
+}
diff --git a/src/qtmultimediaquicktools/shaders/rectsampler_rgb_core.frag b/src/qtmultimediaquicktools/shaders/rectsampler_rgb_core.frag
new file mode 100644
index 000000000..17f306456
--- /dev/null
+++ b/src/qtmultimediaquicktools/shaders/rectsampler_rgb_core.frag
@@ -0,0 +1,10 @@
+#version 150 core
+uniform sampler2DRect rgbTexture;
+uniform lowp float opacity;
+in highp vec2 qt_TexCoord;
+out vec4 fragColor;
+
+void main()
+{
+ fragColor = texture(rgbTexture, qt_TexCoord) * opacity;
+}