summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/multimedia/platform/gstreamer/common/qgst_p.h6
-rw-r--r--src/multimedia/platform/gstreamer/common/qgstreamervideooutput_p.h1
-rw-r--r--src/multimedia/platform/gstreamer/common/qgstreamervideooverlay.cpp7
-rw-r--r--src/multimedia/platform/gstreamer/common/qgstreamervideorenderer.cpp3
-rw-r--r--src/multimedia/platform/gstreamer/common/qgstreamervideorenderer_p.h8
-rw-r--r--src/multimedia/platform/gstreamer/common/qgstreamervideosink.cpp15
-rw-r--r--src/multimedia/platform/gstreamer/common/qgstreamervideosink_p.h4
-rw-r--r--src/multimedia/platform/gstreamer/common/qgstutils.cpp47
-rw-r--r--src/multimedia/platform/gstreamer/common/qgstutils_p.h3
-rw-r--r--src/multimedia/platform/gstreamer/common/qgstvideobuffer.cpp60
-rw-r--r--src/multimedia/platform/gstreamer/common/qgstvideobuffer_p.h16
-rw-r--r--src/multimedia/platform/gstreamer/common/qgstvideorenderersink.cpp84
-rw-r--r--src/multimedia/platform/gstreamer/common/qgstvideorenderersink_p.h7
-rw-r--r--src/multimedia/platform/qplatformvideosink_p.h2
-rw-r--r--src/multimedia/video/qabstractvideobuffer.cpp14
-rw-r--r--src/multimedia/video/qabstractvideobuffer_p.h5
-rw-r--r--src/multimedia/video/qvideoframe.cpp16
-rw-r--r--src/multimedia/video/qvideoframe.h2
-rw-r--r--src/multimedia/video/qvideosink.cpp3
-rw-r--r--src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp13
-rw-r--r--src/qtmultimediaquicktools/qdeclarativevideooutput_render_p.h2
-rw-r--r--src/qtmultimediaquicktools/qsgvideonode_texture.cpp2
-rw-r--r--src/qtmultimediaquicktools/qsgvideonode_yuv.cpp28
-rw-r--r--tests/auto/unit/multimedia/qabstractvideobuffer/tst_qabstractvideobuffer.cpp2
-rw-r--r--tests/auto/unit/multimedia/qvideoframe/tst_qvideoframe.cpp4
25 files changed, 205 insertions, 149 deletions
diff --git a/src/multimedia/platform/gstreamer/common/qgst_p.h b/src/multimedia/platform/gstreamer/common/qgst_p.h
index d4ee13cd9..e8245ee66 100644
--- a/src/multimedia/platform/gstreamer/common/qgst_p.h
+++ b/src/multimedia/platform/gstreamer/common/qgst_p.h
@@ -233,6 +233,12 @@ public:
gst_caps_unref(caps);
}
+ void create() {
+ caps = gst_caps_new_empty();
+ }
+
+ void addPixelFormats(const QList<QVideoSurfaceFormat::PixelFormat> &formats, const char *modifier = nullptr);
+
bool isNull() const { return !caps; }
int size() const { return gst_caps_get_size(caps); }
diff --git a/src/multimedia/platform/gstreamer/common/qgstreamervideooutput_p.h b/src/multimedia/platform/gstreamer/common/qgstreamervideooutput_p.h
index 8f4946e1f..03dcbcb98 100644
--- a/src/multimedia/platform/gstreamer/common/qgstreamervideooutput_p.h
+++ b/src/multimedia/platform/gstreamer/common/qgstreamervideooutput_p.h
@@ -59,7 +59,6 @@
QT_BEGIN_NAMESPACE
-class QGstreamerVideoRenderer;
class QVideoSink;
class QGstreamerVideoSink;
diff --git a/src/multimedia/platform/gstreamer/common/qgstreamervideooverlay.cpp b/src/multimedia/platform/gstreamer/common/qgstreamervideooverlay.cpp
index 54d38cc06..33b1d91f8 100644
--- a/src/multimedia/platform/gstreamer/common/qgstreamervideooverlay.cpp
+++ b/src/multimedia/platform/gstreamer/common/qgstreamervideooverlay.cpp
@@ -59,9 +59,6 @@ struct ElementMap
// Ordered by descending priority
static constexpr ElementMap elementMap[] =
{
-#if QT_CONFIG(gstreamer_gl)
- { "xcb", "glimagesink" },
-#endif
{ "xcb", "vaapisink" },
{ "xcb", "xvimagesink" },
{ "xcb", "ximagesink" },
@@ -334,10 +331,6 @@ static QGstElement findBestVideoSink()
// First, try some known video sinks, depending on the Qt platform plugin in use.
for (auto i : elementMap) {
-#if QT_CONFIG(gstreamer_gl)
- if (!QGstUtils::useOpenGL() && qstrcmp(i.gstreamerElement, "glimagesink") == 0)
- continue;
-#endif
if (platform != QLatin1String(i.qtPlatform))
continue;
QGstElement choice(i.gstreamerElement, i.gstreamerElement);
diff --git a/src/multimedia/platform/gstreamer/common/qgstreamervideorenderer.cpp b/src/multimedia/platform/gstreamer/common/qgstreamervideorenderer.cpp
index 9a9884079..5de7ee032 100644
--- a/src/multimedia/platform/gstreamer/common/qgstreamervideorenderer.cpp
+++ b/src/multimedia/platform/gstreamer/common/qgstreamervideorenderer.cpp
@@ -46,8 +46,7 @@
#include <gst/gst.h>
QGstreamerVideoRenderer::QGstreamerVideoRenderer(QVideoSink *parent)
- : QObject(parent),
- m_sink(parent)
+ : m_sink(parent)
{
}
diff --git a/src/multimedia/platform/gstreamer/common/qgstreamervideorenderer_p.h b/src/multimedia/platform/gstreamer/common/qgstreamervideorenderer_p.h
index da8eff6cd..2f7bcc72f 100644
--- a/src/multimedia/platform/gstreamer/common/qgstreamervideorenderer_p.h
+++ b/src/multimedia/platform/gstreamer/common/qgstreamervideorenderer_p.h
@@ -58,20 +58,14 @@
QT_BEGIN_NAMESPACE
-class Q_MULTIMEDIA_EXPORT QGstreamerVideoRenderer : public QObject
+class Q_MULTIMEDIA_EXPORT QGstreamerVideoRenderer
{
- Q_OBJECT
public:
QGstreamerVideoRenderer(QVideoSink *parent = nullptr);
virtual ~QGstreamerVideoRenderer();
QGstElement gstVideoSink();
- bool isReady() const { return m_sink != 0; }
-
-signals:
- void readyChanged(bool);
-
private:
QGstElement gstSink;
QPointer<QVideoSink> m_sink;
diff --git a/src/multimedia/platform/gstreamer/common/qgstreamervideosink.cpp b/src/multimedia/platform/gstreamer/common/qgstreamervideosink.cpp
index d8a65a771..75a548225 100644
--- a/src/multimedia/platform/gstreamer/common/qgstreamervideosink.cpp
+++ b/src/multimedia/platform/gstreamer/common/qgstreamervideosink.cpp
@@ -40,6 +40,7 @@
#include "qgstreamervideosink_p.h"
#include "qgstreamervideorenderer_p.h"
#include <private/qgstutils_p.h>
+#include <QtGui/private/qrhi_p.h>
#include <QtCore/qdebug.h>
@@ -57,6 +58,7 @@ QGstreamerVideoSink::QGstreamerVideoSink(QVideoSink *parent)
QGstreamerVideoSink::~QGstreamerVideoSink()
{
delete m_videoOverlay;
+ delete m_videoRenderer;
}
QVideoSink::GraphicsType QGstreamerVideoSink::graphicsType() const
@@ -98,6 +100,16 @@ void QGstreamerVideoSink::setWinId(WId id)
m_videoOverlay->setWindowHandle(m_windowId);
}
+void QGstreamerVideoSink::setRhi(QRhi *rhi)
+{
+ if (rhi && rhi->backend() != QRhi::OpenGLES2)
+ rhi = nullptr;
+ if (m_rhi == rhi)
+ return;
+
+ m_rhi = rhi;
+}
+
bool QGstreamerVideoSink::processSyncMessage(const QGstreamerMessage &message)
{
return m_videoOverlay->processSyncMessage(message);
@@ -205,7 +217,4 @@ void QGstreamerVideoSink::createOverlay()
void QGstreamerVideoSink::createRenderer()
{
m_videoRenderer = new QGstreamerVideoRenderer(sink);
-
- qCDebug(qLcMediaVideoSink) << Q_FUNC_INFO;
- connect(m_videoRenderer, SIGNAL(sinkChanged()), this, SLOT(sinkChanged()));
}
diff --git a/src/multimedia/platform/gstreamer/common/qgstreamervideosink_p.h b/src/multimedia/platform/gstreamer/common/qgstreamervideosink_p.h
index 2b6843694..3142d8de6 100644
--- a/src/multimedia/platform/gstreamer/common/qgstreamervideosink_p.h
+++ b/src/multimedia/platform/gstreamer/common/qgstreamervideosink_p.h
@@ -78,6 +78,9 @@ public:
WId winId() const override;
void setWinId(WId id) override;
+ QRhi *rhi() const { return m_rhi; }
+ void setRhi(QRhi *rhi) override;
+
QRect displayRect() const override;
void setDisplayRect(const QRect &rect) override;
@@ -119,6 +122,7 @@ private:
QGstreamerVideoRenderer *m_videoRenderer = nullptr;
QVideoSink::GraphicsType m_graphicsType = QVideoSink::Memory;
WId m_windowId = 0;
+ QRhi *m_rhi = nullptr;
QRect m_displayRect;
bool m_fullScreen = false;
mutable QColor m_colorKey = QColor::Invalid;
diff --git a/src/multimedia/platform/gstreamer/common/qgstutils.cpp b/src/multimedia/platform/gstreamer/common/qgstutils.cpp
index be121bdcd..24bb4a3a1 100644
--- a/src/multimedia/platform/gstreamer/common/qgstutils.cpp
+++ b/src/multimedia/platform/gstreamer/common/qgstutils.cpp
@@ -250,29 +250,34 @@ QVideoSurfaceFormat QGstUtils::formatForCaps(
return QVideoSurfaceFormat();
}
-QGstMutableCaps QGstUtils::capsForFormats(const QList<QVideoSurfaceFormat::PixelFormat> &formats)
+void QGstMutableCaps::addPixelFormats(const QList<QVideoSurfaceFormat::PixelFormat> &formats, const char *modifier)
{
- GstCaps *caps = gst_caps_new_empty();
+ GValue list = {};
+ g_value_init(&list, GST_TYPE_LIST);
for (QVideoSurfaceFormat::PixelFormat format : formats) {
int index = indexOfVideoFormat(format);
-
- if (index != -1) {
- gst_caps_append_structure(caps, gst_structure_new(
- "video/x-raw",
- "format" , G_TYPE_STRING, gst_video_format_to_string(qt_videoFormatLookup[index].gstFormat),
- nullptr));
- }
+ if (index == -1)
+ continue;
+ GValue item = {};
+
+ g_value_init(&item, G_TYPE_STRING);
+ g_value_set_string(&item, gst_video_format_to_string(qt_videoFormatLookup[index].gstFormat));
+ gst_value_list_append_value(&list, &item);
+ g_value_unset(&item);
}
-
- gst_caps_set_simple(
- caps,
- "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, INT_MAX, 1,
- "width" , GST_TYPE_INT_RANGE, 1, INT_MAX,
- "height" , GST_TYPE_INT_RANGE, 1, INT_MAX,
- nullptr);
-
- return caps;
+ QGValue v(&list);
+ auto *structure = gst_structure_new("video/x-raw",
+ "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, INT_MAX, 1,
+ "width" , GST_TYPE_INT_RANGE, 1, INT_MAX,
+ "height" , GST_TYPE_INT_RANGE, 1, INT_MAX,
+ nullptr);
+ gst_structure_set_value(structure, "format", &list);
+ gst_caps_append_structure(caps, structure);
+ g_value_unset(&list);
+
+ if (modifier)
+ gst_caps_set_features(caps, size() - 1, gst_caps_features_from_string(modifier));
}
void QGstUtils::setFrameTimeStamps(QVideoFrame *frame, GstBuffer *buffer)
@@ -375,12 +380,6 @@ QGRange<float> QGstStructure::frameRateRange() const
return {minRate, maxRate};
}
-bool QGstUtils::useOpenGL()
-{
- static bool result = qEnvironmentVariableIntValue("QT_GSTREAMER_USE_OPENGL_PLUGIN");
- return result;
-}
-
GList *qt_gst_video_sinks()
{
GList *list = nullptr;
diff --git a/src/multimedia/platform/gstreamer/common/qgstutils_p.h b/src/multimedia/platform/gstreamer/common/qgstutils_p.h
index 39063b45a..b71f016a4 100644
--- a/src/multimedia/platform/gstreamer/common/qgstutils_p.h
+++ b/src/multimedia/platform/gstreamer/common/qgstutils_p.h
@@ -78,10 +78,7 @@ namespace QGstUtils {
GstCaps *caps,
GstVideoInfo *info = 0);
- Q_MULTIMEDIA_EXPORT QGstMutableCaps capsForFormats(const QList<QVideoSurfaceFormat::PixelFormat> &formats);
void setFrameTimeStamps(QVideoFrame *frame, GstBuffer *buffer);
-
- Q_MULTIMEDIA_EXPORT bool useOpenGL();
}
Q_MULTIMEDIA_EXPORT GList *qt_gst_video_sinks();
diff --git a/src/multimedia/platform/gstreamer/common/qgstvideobuffer.cpp b/src/multimedia/platform/gstreamer/common/qgstvideobuffer.cpp
index 711472f29..a345fc8c2 100644
--- a/src/multimedia/platform/gstreamer/common/qgstvideobuffer.cpp
+++ b/src/multimedia/platform/gstreamer/common/qgstvideobuffer.cpp
@@ -39,23 +39,27 @@
#include "qgstvideobuffer_p.h"
-QT_BEGIN_NAMESPACE
+#include <gst/video/video.h>
+#include <gst/video/gstvideometa.h>
+
+#include "qgstutils_p.h"
+
+#if QT_CONFIG(gstreamer_gl)
+#include <QtGui/private/qrhi_p.h>
+#include <QtGui/private/qrhigles2_p.h>
+
+#include <gst/gl/gstglconfig.h>
+#include <gst/gl/gstglmemory.h>
+#endif
-QGstVideoBuffer::QGstVideoBuffer(GstBuffer *buffer, const GstVideoInfo &info)
- : QAbstractVideoBuffer(QVideoFrame::NoHandle)
- , m_videoInfo(info)
- , m_buffer(buffer)
-{
- gst_buffer_ref(m_buffer);
-}
-QGstVideoBuffer::QGstVideoBuffer(GstBuffer *buffer, const GstVideoInfo &info,
- QVideoFrame::HandleType handleType,
- const QVariant &handle)
- : QAbstractVideoBuffer(handleType)
+QT_BEGIN_NAMESPACE
+
+QGstVideoBuffer::QGstVideoBuffer(GstBuffer *buffer, const GstVideoInfo &info, QRhi *rhi, BufferFormat format)
+ : QAbstractVideoBuffer(QVideoFrame::NoHandle, rhi)
+ , bufferFormat(format)
, m_videoInfo(info)
, m_buffer(buffer)
- , m_handle(handle)
{
gst_buffer_ref(m_buffer);
}
@@ -116,4 +120,34 @@ void QGstVideoBuffer::unmap()
m_mode = QVideoFrame::NotMapped;
}
+quint64 QGstVideoBuffer::textureHandle(int plane) const
+{
+ if (plane != 0)
+ return 0;
+#if QT_CONFIG(gstreamer_gl)
+ if (bufferFormat == GLTexture) {
+ auto *memory = gst_buffer_peek_memory(m_buffer, 0);
+ if (gst_is_gl_memory(memory)) {
+ GstGLMemory *glmem = GST_GL_MEMORY_CAST(memory);
+ // ### Handle multiple planes
+ return gst_gl_memory_get_texture_id(glmem);
+ }
+ } else if (bufferFormat == VideoGLTextureUploadMeta) {
+ Q_ASSERT(rhi && rhi->backend() == QRhi::OpenGLES2);
+
+ auto *upload = gst_buffer_get_video_gl_texture_upload_meta(m_buffer);
+ if (upload) {
+ rhi->makeThreadLocalNativeContextCurrent();
+ // ### Handle multiple planes
+ guint textures[4];
+ gst_video_gl_texture_upload_meta_upload(upload, textures);
+ return textures[0];
+ } else {
+ qWarning() << "Could not use GstVideoGLTextureUploadMeta";
+ }
+ }
+#endif
+ return 0;
+}
+
QT_END_NAMESPACE
diff --git a/src/multimedia/platform/gstreamer/common/qgstvideobuffer_p.h b/src/multimedia/platform/gstreamer/common/qgstvideobuffer_p.h
index bcda66cf0..5f5899da3 100644
--- a/src/multimedia/platform/gstreamer/common/qgstvideobuffer_p.h
+++ b/src/multimedia/platform/gstreamer/common/qgstvideobuffer_p.h
@@ -63,10 +63,17 @@ QT_BEGIN_NAMESPACE
class Q_MULTIMEDIA_EXPORT QGstVideoBuffer : public QAbstractVideoBuffer
{
public:
- QGstVideoBuffer(GstBuffer *buffer, const GstVideoInfo &info);
- QGstVideoBuffer(GstBuffer *buffer, const GstVideoInfo &info,
- QVideoFrame::HandleType handleType, const QVariant &handle);
+ enum BufferFormat {
+ Memory,
+ GLTexture,
+ VideoGLTextureUploadMeta,
+ DMABuf
+ };
+ QGstVideoBuffer(GstBuffer *buffer, const GstVideoInfo &info, QRhi *rhi, BufferFormat format);
+ QGstVideoBuffer(GstBuffer *buffer, const GstVideoInfo &info)
+ : QGstVideoBuffer(buffer, info, nullptr, Memory)
+ {}
~QGstVideoBuffer();
GstBuffer *buffer() const { return m_buffer; }
@@ -75,8 +82,9 @@ public:
MapData map(QVideoFrame::MapMode mode) override;
void unmap() override;
- QVariant handle() const override { return m_handle; }
+ quint64 textureHandle(int plane) const override;
private:
+ BufferFormat bufferFormat = Memory;
GstVideoInfo m_videoInfo;
GstVideoFrame m_frame;
GstBuffer *m_buffer = nullptr;
diff --git a/src/multimedia/platform/gstreamer/common/qgstvideorenderersink.cpp b/src/multimedia/platform/gstreamer/common/qgstvideorenderersink.cpp
index b6b9704dc..8825097f1 100644
--- a/src/multimedia/platform/gstreamer/common/qgstvideorenderersink.cpp
+++ b/src/multimedia/platform/gstreamer/common/qgstvideorenderersink.cpp
@@ -51,12 +51,15 @@
#include "qgstvideorenderersink_p.h"
#include <gst/video/video.h>
+#include <gst/video/gstvideometa.h>
#include "qgstutils_p.h"
#if QT_CONFIG(gstreamer_gl)
-#include <QOpenGLContext>
+#include <QtGui/private/qrhi_p.h>
+#include <QtGui/private/qrhigles2_p.h>
#include <QGuiApplication>
+#include <QtGui/qopenglcontext.h>
#include <QWindow>
#include <qpa/qplatformnativeinterface.h>
@@ -77,24 +80,30 @@
QT_BEGIN_NAMESPACE
-QGstVideoRenderer::QGstVideoRenderer() = default;
+QGstVideoRenderer::QGstVideoRenderer(QVideoSink *sink)
+ : m_sink(sink)
+{
+}
QGstVideoRenderer::~QGstVideoRenderer() = default;
QGstMutableCaps QGstVideoRenderer::getCaps()
{
+ QGstMutableCaps caps;
+ caps.create();
+
// All the formats that both we and gstreamer support
#if QT_CONFIG(gstreamer_gl)
- if (QGstUtils::useOpenGL()) {
- m_handleType = QVideoFrame::RhiTextureHandle;
+ QRhi *rhi = m_sink->rhi();
+ if (rhi->backend() == QRhi::OpenGLES2) {
auto formats = QList<QVideoSurfaceFormat::PixelFormat>()
- << QVideoSurfaceFormat::Format_YUV420P
- << QVideoSurfaceFormat::Format_YUV422P
- << QVideoSurfaceFormat::Format_YV12
+// << QVideoSurfaceFormat::Format_YUV420P
+// << QVideoSurfaceFormat::Format_YUV422P
+// << QVideoSurfaceFormat::Format_YV12
<< QVideoSurfaceFormat::Format_UYVY
<< QVideoSurfaceFormat::Format_YUYV
- << QVideoSurfaceFormat::Format_NV12
- << QVideoSurfaceFormat::Format_NV21
+// << QVideoSurfaceFormat::Format_NV12
+// << QVideoSurfaceFormat::Format_NV21
<< QVideoSurfaceFormat::Format_AYUV444
<< QVideoSurfaceFormat::Format_YUV444
// << QVideoSurfaceFormat::Format_P010LE
@@ -105,8 +114,8 @@ QGstMutableCaps QGstVideoRenderer::getCaps()
<< QVideoSurfaceFormat::Format_ARGB32
<< QVideoSurfaceFormat::Format_ABGR32
<< QVideoSurfaceFormat::Format_BGRA32
- << QVideoSurfaceFormat::Format_RGB555
- << QVideoSurfaceFormat::Format_BGR555
+// << QVideoSurfaceFormat::Format_RGB555
+// << QVideoSurfaceFormat::Format_BGR555
// << QVideoSurfaceFormat::Format_Y16
// << QVideoSurfaceFormat::Format_RGB24
// << QVideoSurfaceFormat::Format_BGR24
@@ -116,14 +125,10 @@ QGstMutableCaps QGstVideoRenderer::getCaps()
// glupload will be added to the pipeline and GLMemory will be requested.
// This will lead to upload data to gl textures
// and download it when the buffer will be used within rendering.
- if (!formats.isEmpty()) {
- QGstMutableCaps caps = QGstUtils::capsForFormats(formats);
- for (int i = 0; i < caps.size(); ++i)
- gst_caps_set_features(caps.get(), i, gst_caps_features_from_string(GST_CAPS_FEATURE_MEMORY_GL_MEMORY));
-
- return caps;
- }
- m_handleType = QVideoFrame::NoHandle;
+ caps.addPixelFormats(formats, GST_CAPS_FEATURE_MEMORY_GL_MEMORY);
+ // ### needs more work, somehow casting the GstBuffer to texture upload meta
+ // fails. In addition, the texture upload seems to be broken for VAAPI decoders
+// caps.addPixelFormats(formats, GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META);
}
#endif
auto formats = QList<QVideoSurfaceFormat::PixelFormat>()
@@ -150,13 +155,25 @@ QGstMutableCaps QGstVideoRenderer::getCaps()
<< QVideoSurfaceFormat::Format_RGB24
<< QVideoSurfaceFormat::Format_BGR24
<< QVideoSurfaceFormat::Format_RGB565;
- return QGstUtils::capsForFormats(formats);
+ caps.addPixelFormats(formats);
+ qDebug() << "CAPS:" << caps.toString();
+ return caps;
}
bool QGstVideoRenderer::start(GstCaps *caps)
{
m_flushed = true;
m_format = QGstUtils::formatForCaps(caps, &m_videoInfo);
+// qDebug() << "START:" << QGstCaps(caps).toString();
+// qDebug() << m_format;
+
+ auto *features = gst_caps_get_features(caps, 0);
+ if (gst_caps_features_contains(features, GST_CAPS_FEATURE_MEMORY_GL_MEMORY))
+ bufferFormat = QGstVideoBuffer::GLTexture;
+ else if (gst_caps_features_contains(features, GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META))
+ bufferFormat = QGstVideoBuffer::VideoGLTextureUploadMeta;
+ else if (gst_caps_features_contains(features, "memory:DMABuf"))
+ bufferFormat = QGstVideoBuffer::DMABuf;
return m_format.isValid();
}
@@ -170,17 +187,7 @@ bool QGstVideoRenderer::present(QVideoSink *sink, GstBuffer *buffer)
{
m_flushed = false;
- QGstVideoBuffer *videoBuffer = nullptr;
-#if QT_CONFIG(gstreamer_gl)
- if (m_handleType == QVideoFrame::RhiTextureHandle) {
- GstGLMemory *glmem = GST_GL_MEMORY_CAST(gst_buffer_peek_memory(buffer, 0));
- guint textureId = gst_gl_memory_get_texture_id(glmem);
- videoBuffer = new QGstVideoBuffer(buffer, m_videoInfo, m_handleType, textureId);
- }
-#endif
-
- if (!videoBuffer)
- videoBuffer = new QGstVideoBuffer(buffer, m_videoInfo);
+ QGstVideoBuffer *videoBuffer = new QGstVideoBuffer(buffer, m_videoInfo, m_sink->rhi(), bufferFormat);
auto meta = gst_buffer_get_video_crop_meta (buffer);
if (meta) {
@@ -216,7 +223,7 @@ bool QGstVideoRenderer::proposeAllocation(GstQuery *)
QVideoSurfaceGstDelegate::QVideoSurfaceGstDelegate(QVideoSink *sink)
: m_sink(sink)
{
- m_renderer = new QGstVideoRenderer;
+ m_renderer = new QGstVideoRenderer(sink);
updateSupportedFormats();
connect(m_sink, SIGNAL(supportedFormatsChanged()), this, SLOT(updateSupportedFormats()));
}
@@ -240,6 +247,7 @@ QGstMutableCaps QVideoSurfaceGstDelegate::caps()
bool QVideoSurfaceGstDelegate::start(GstCaps *caps)
{
+// qDebug() << "QVideoSurfaceGstDelegate::start" << QGstCaps(caps).toString();
QMutexLocker locker(&m_mutex);
if (m_activeRenderer) {
@@ -332,8 +340,12 @@ GstFlowReturn QVideoSurfaceGstDelegate::render(GstBuffer *buffer)
#if QT_CONFIG(gstreamer_gl)
static GstGLContext *gstGLDisplayContext(QVideoSink *sink)
{
- auto glContext = qobject_cast<QOpenGLContext*>(sink->property("GLContext").value<QObject*>());
- // Context is not ready yet.
+ QRhi *rhi = sink->rhi();
+ if (!rhi || rhi->backend() != QRhi::OpenGLES2)
+ return nullptr;
+
+ auto *nativeHandles = static_cast<const QRhiGles2NativeHandles *>(rhi->nativeHandles());
+ auto glContext = nativeHandles->context;
if (!glContext)
return nullptr;
@@ -427,7 +439,7 @@ bool QVideoSurfaceGstDelegate::query(GstQuery *query)
gst_query_set_context(query, context);
gst_context_unref(context);
- return m_gstGLDisplayContext;
+ return true;
}
#else
Q_UNUSED(query);
@@ -563,7 +575,7 @@ QGstVideoRendererSink *QGstVideoRendererSink::createSink(QVideoSink *sink)
QGstVideoRendererSink *gstSink = reinterpret_cast<QGstVideoRendererSink *>(
g_object_new(QGstVideoRendererSink::get_type(), nullptr));
- g_signal_connect(G_OBJECT(sink), "notify::show-preroll-frame", G_CALLBACK(handleShowPrerollChange), sink);
+ g_signal_connect(G_OBJECT(gstSink), "notify::show-preroll-frame", G_CALLBACK(handleShowPrerollChange), gstSink);
return gstSink;
}
diff --git a/src/multimedia/platform/gstreamer/common/qgstvideorenderersink_p.h b/src/multimedia/platform/gstreamer/common/qgstvideorenderersink_p.h
index aadf1fb78..6833b468d 100644
--- a/src/multimedia/platform/gstreamer/common/qgstvideorenderersink_p.h
+++ b/src/multimedia/platform/gstreamer/common/qgstvideorenderersink_p.h
@@ -62,7 +62,7 @@
#include <QtCore/qwaitcondition.h>
#include <qvideosurfaceformat.h>
#include <qvideoframe.h>
-
+#include <private/qgstvideobuffer_p.h>
#include <private/qgst_p.h>
#if QT_CONFIG(gstreamer_gl)
@@ -78,7 +78,7 @@ class QVideoSink;
class QGstVideoRenderer
{
public:
- QGstVideoRenderer();
+ QGstVideoRenderer(QVideoSink *sink);
~QGstVideoRenderer();
QGstMutableCaps getCaps();
@@ -91,10 +91,11 @@ public:
void flush(QVideoSink *surface);
private:
+ QVideoSink *m_sink = nullptr;
QVideoSurfaceFormat m_format;
GstVideoInfo m_videoInfo;
bool m_flushed = true;
- QVideoFrame::HandleType m_handleType = QVideoFrame::NoHandle;
+ QGstVideoBuffer::BufferFormat bufferFormat = QGstVideoBuffer::Memory;
};
class QVideoSurfaceGstDelegate : public QObject
diff --git a/src/multimedia/platform/qplatformvideosink_p.h b/src/multimedia/platform/qplatformvideosink_p.h
index faa0f6d77..d519f17f0 100644
--- a/src/multimedia/platform/qplatformvideosink_p.h
+++ b/src/multimedia/platform/qplatformvideosink_p.h
@@ -64,6 +64,8 @@ public:
virtual WId winId() const = 0;
virtual void setWinId(WId id) = 0;
+ virtual void setRhi(QRhi */*rhi*/) {}
+
virtual QRect displayRect() const = 0;
virtual void setDisplayRect(const QRect &rect) = 0;
diff --git a/src/multimedia/video/qabstractvideobuffer.cpp b/src/multimedia/video/qabstractvideobuffer.cpp
index bfb97a8fd..db43beb81 100644
--- a/src/multimedia/video/qabstractvideobuffer.cpp
+++ b/src/multimedia/video/qabstractvideobuffer.cpp
@@ -104,8 +104,9 @@ QT_BEGIN_NAMESPACE
/*!
Constructs an abstract video buffer of the given \a type.
*/
-QAbstractVideoBuffer::QAbstractVideoBuffer(QVideoFrame::HandleType type)
- : m_type(type)
+QAbstractVideoBuffer::QAbstractVideoBuffer(QVideoFrame::HandleType type, QRhi *rhi)
+ : m_type(type),
+ rhi(rhi)
{
}
@@ -173,17 +174,12 @@ QVideoFrame::HandleType QAbstractVideoBuffer::handleType() const
\sa map()
*/
-/*!
- Returns a type specific handle to the data buffer.
+/*! \fn quint64 QAbstractVideoBuffer::textureHandle(QRhi *rhi, int plane) const
- The type of the handle is given by handleType() function.
+ Returns a texture handle to the data buffer.
\sa handleType()
*/
-QVariant QAbstractVideoBuffer::handle() const
-{
- return QVariant();
-}
/*!
\fn int QAbstractPlanarVideoBuffer::map(MapMode mode, int *numBytes, int bytesPerLine[4], uchar *data[4])
diff --git a/src/multimedia/video/qabstractvideobuffer_p.h b/src/multimedia/video/qabstractvideobuffer_p.h
index e3a0fb86c..a82f13723 100644
--- a/src/multimedia/video/qabstractvideobuffer_p.h
+++ b/src/multimedia/video/qabstractvideobuffer_p.h
@@ -60,11 +60,12 @@ QT_BEGIN_NAMESPACE
class QVariant;
+class QRhi;
class Q_MULTIMEDIA_EXPORT QAbstractVideoBuffer
{
public:
- QAbstractVideoBuffer(QVideoFrame::HandleType type);
+ QAbstractVideoBuffer(QVideoFrame::HandleType type, QRhi *rhi = nullptr);
virtual ~QAbstractVideoBuffer();
QVideoFrame::HandleType handleType() const;
@@ -81,11 +82,11 @@ public:
virtual MapData map(QVideoFrame::MapMode mode) = 0;
virtual void unmap() = 0;
- virtual QVariant handle() const;
virtual quint64 textureHandle(int /*plane*/) const { return 0; }
protected:
QVideoFrame::HandleType m_type;
+ QRhi *rhi = nullptr;
private:
Q_DISABLE_COPY(QAbstractVideoBuffer)
diff --git a/src/multimedia/video/qvideoframe.cpp b/src/multimedia/video/qvideoframe.cpp
index 375f19930..2fa5f9f88 100644
--- a/src/multimedia/video/qvideoframe.cpp
+++ b/src/multimedia/video/qvideoframe.cpp
@@ -808,21 +808,13 @@ int QVideoFrame::planeCount() const
return d->format.nPlanes();
}
-quint64 QVideoFrame::textureHandle(int plane)
-{
- return d->buffer->textureHandle(plane);
-}
-
/*!
- Returns a type specific handle to a video frame's buffer.
-
- For an OpenGL texture this would be the texture ID.
-
- \sa QAbstractVideoBuffer::handle()
+ \internal
+ Returns a texture id to the video frame's buffers.
*/
-QVariant QVideoFrame::handle() const
+quint64 QVideoFrame::textureHandle(int plane)
{
- return d->buffer != nullptr ? d->buffer->handle() : QVariant();
+ return d->buffer->textureHandle(plane);
}
/*!
diff --git a/src/multimedia/video/qvideoframe.h b/src/multimedia/video/qvideoframe.h
index 5e90b6ca1..ea01ccb92 100644
--- a/src/multimedia/video/qvideoframe.h
+++ b/src/multimedia/video/qvideoframe.h
@@ -115,8 +115,6 @@ public:
quint64 textureHandle(int plane);
- QVariant handle() const;
-
qint64 startTime() const;
void setStartTime(qint64 time);
diff --git a/src/multimedia/video/qvideosink.cpp b/src/multimedia/video/qvideosink.cpp
index f5112b173..b996392b4 100644
--- a/src/multimedia/video/qvideosink.cpp
+++ b/src/multimedia/video/qvideosink.cpp
@@ -126,7 +126,10 @@ QRhi *QVideoSink::rhi() const
void QVideoSink::setRhi(QRhi *rhi)
{
+ if (d->rhi == rhi)
+ return;
d->rhi = rhi;
+ d->videoSink->setRhi(rhi);
}
void QVideoSink::setFullScreen(bool fullscreen)
diff --git a/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp b/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp
index fad92bc5f..a45350fdc 100644
--- a/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp
+++ b/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp
@@ -62,12 +62,6 @@ QDeclarativeVideoBackend::QDeclarativeVideoBackend(QDeclarativeVideoOutput *pare
: q(parent),
m_frameChanged(false)
{
- m_sink = new QVideoSink(q);
- m_sink->setRhi(QQuickWindowPrivate::get(q->window())->rhi);
- 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"));
@@ -324,6 +318,13 @@ QSGNode *QDeclarativeVideoBackend::updatePaintNode(QSGNode *oldNode,
QVideoSink *QDeclarativeVideoBackend::videoSink() const
{
+ if (!m_sink) {
+ m_sink = new QVideoSink(q);
+ m_sink->setRhi(QQuickWindowPrivate::get(q->window())->rhi);
+ qRegisterMetaType<QVideoSurfaceFormat>();
+ QObject::connect(m_sink, SIGNAL(newVideoFrame(const QVideoFrame &)),
+ q, SLOT(_q_newFrame(const QVideoFrame &)), Qt::QueuedConnection);
+ }
return m_sink;
}
diff --git a/src/qtmultimediaquicktools/qdeclarativevideooutput_render_p.h b/src/qtmultimediaquicktools/qdeclarativevideooutput_render_p.h
index 68c73f0c6..95b3f1ebd 100644
--- a/src/qtmultimediaquicktools/qdeclarativevideooutput_render_p.h
+++ b/src/qtmultimediaquicktools/qdeclarativevideooutput_render_p.h
@@ -95,7 +95,7 @@ private:
QDeclarativeVideoOutput *q;
QList<QSGVideoNodeFactoryInterface*> m_videoNodeFactories;
- QVideoSink *m_sink;
+ mutable QVideoSink *m_sink = nullptr;
QVideoSurfaceFormat m_surfaceFormat;
QVideoFrame m_frame;
diff --git a/src/qtmultimediaquicktools/qsgvideonode_texture.cpp b/src/qtmultimediaquicktools/qsgvideonode_texture.cpp
index cc345d61a..70abf5b90 100644
--- a/src/qtmultimediaquicktools/qsgvideonode_texture.cpp
+++ b/src/qtmultimediaquicktools/qsgvideonode_texture.cpp
@@ -185,7 +185,7 @@ void QSGVideoMaterialRhiShader_Texture::updateSampledImage(RenderState &state, i
m->m_frameMutex.lock();
auto size = m->m_frame.size();
if (m->m_frame.isValid())
- m->m_textureId = m->m_frame.handle().toULongLong();
+ m->m_textureId = m->m_frame.textureHandle(0);
m->m_frameMutex.unlock();
m->m_texture->setNativeObject(m->m_textureId, size);
diff --git a/src/qtmultimediaquicktools/qsgvideonode_yuv.cpp b/src/qtmultimediaquicktools/qsgvideonode_yuv.cpp
index efefaf0f1..182e98610 100644
--- a/src/qtmultimediaquicktools/qsgvideonode_yuv.cpp
+++ b/src/qtmultimediaquicktools/qsgvideonode_yuv.cpp
@@ -354,12 +354,12 @@ void QSGVideoMaterialRhiShader_NV12::mapFrame(QSGVideoMaterial_YUV *m)
if (m->m_frame.handleType() == QVideoFrame::RhiTextureHandle) {
m->m_planeWidth[0] = m->m_planeWidth[1] = 1;
- auto textures = m->m_frame.handle().toList();
- if (!textures.isEmpty()) {
+ quint64 textures[2] = { m->m_frame.textureHandle(0), m->m_frame.textureHandle(1) };
+ if (textures[0] && textures[1]) {
auto w = m->m_frame.size().width();
auto h = m->m_frame.size().height();
- m->m_textures[0]->setNativeObject(textures[0].toULongLong(), {w, h}, QRhiTexture::R8);
- m->m_textures[1]->setNativeObject(textures[1].toULongLong(), {w / 2, h / 2}, QRhiTexture::RG8);
+ m->m_textures[0]->setNativeObject(textures[0], {w, h}, QRhiTexture::R8);
+ m->m_textures[1]->setNativeObject(textures[1], {w / 2, h / 2}, QRhiTexture::RG8);
} else {
qWarning() << "NV12/NV21 requires 2 textures";
}
@@ -367,8 +367,12 @@ void QSGVideoMaterialRhiShader_NV12::mapFrame(QSGVideoMaterial_YUV *m)
return;
}
- if (!m->m_frame.map(QVideoFrame::ReadOnly))
+ if (!m->m_frame.map(QVideoFrame::ReadOnly)) {
+ qWarning()<< "NV12: Couldn't map frame";
+ m->m_textures[0]->setData(QRhiTexture::RG8, QSize(1, 1), (const uchar *)"\0\0", 2);
+ m->m_textures[1]->setData(QRhiTexture::BGRA8, QSize(1, 1), (const uchar *)"\0\0\0\0", 4);
return;
+ }
int y = 0;
int uv = 1;
@@ -392,12 +396,12 @@ void QSGVideoMaterialRhiShader_P010::mapFrame(QSGVideoMaterial_YUV *m)
if (m->m_frame.handleType() == QVideoFrame::RhiTextureHandle) {
m->m_planeWidth[0] = m->m_planeWidth[1] = 1;
- auto textures = m->m_frame.handle().toList();
- if (!textures.isEmpty()) {
+ quint64 textures[2] = { m->m_frame.textureHandle(0), m->m_frame.textureHandle(1) };
+ if (textures[0] && textures[1]) {
auto w = m->m_frame.size().width();
auto h = m->m_frame.size().height();
- m->m_textures[0]->setNativeObject(textures[0].toULongLong(), {w, h}, QRhiTexture::RG8);
- m->m_textures[1]->setNativeObject(textures[1].toULongLong(), {w / 2, h / 2}, QRhiTexture::BGRA8);
+ m->m_textures[0]->setNativeObject(textures[0], {w, h}, QRhiTexture::RG8);
+ m->m_textures[1]->setNativeObject(textures[1], {w / 2, h / 2}, QRhiTexture::BGRA8);
} else {
qWarning() << "P010/P016 requires 2 textures";
}
@@ -405,8 +409,12 @@ void QSGVideoMaterialRhiShader_P010::mapFrame(QSGVideoMaterial_YUV *m)
return;
}
- if (!m->m_frame.map(QVideoFrame::ReadOnly))
+ if (!m->m_frame.map(QVideoFrame::ReadOnly)) {
+ qWarning()<< "NV12: Couldn't map frame";
+ m->m_textures[0]->setData(QRhiTexture::RG8, QSize(1, 1), (const uchar *)"\0\0", 2);
+ m->m_textures[1]->setData(QRhiTexture::BGRA8, QSize(1, 1), (const uchar *)"\0\0\0\0", 4);
return;
+ }
int y = 0;
int uv = 1;
diff --git a/tests/auto/unit/multimedia/qabstractvideobuffer/tst_qabstractvideobuffer.cpp b/tests/auto/unit/multimedia/qabstractvideobuffer/tst_qabstractvideobuffer.cpp
index cd6e756ab..94594ba99 100644
--- a/tests/auto/unit/multimedia/qabstractvideobuffer/tst_qabstractvideobuffer.cpp
+++ b/tests/auto/unit/multimedia/qabstractvideobuffer/tst_qabstractvideobuffer.cpp
@@ -121,7 +121,7 @@ void tst_QAbstractVideoBuffer::handle()
{
QtTestVideoBuffer buffer(QVideoFrame::NoHandle);
- QVERIFY(buffer.handle().isNull());
+ QVERIFY(buffer.textureHandle(0) == 0);
}
void tst_QAbstractVideoBuffer::mapMode()
diff --git a/tests/auto/unit/multimedia/qvideoframe/tst_qvideoframe.cpp b/tests/auto/unit/multimedia/qvideoframe/tst_qvideoframe.cpp
index 6db33c7f6..588162085 100644
--- a/tests/auto/unit/multimedia/qvideoframe/tst_qvideoframe.cpp
+++ b/tests/auto/unit/multimedia/qvideoframe/tst_qvideoframe.cpp
@@ -195,7 +195,7 @@ void tst_QVideoFrame::create()
QVERIFY(frame.isValid());
QCOMPARE(frame.handleType(), QVideoFrame::NoHandle);
- QCOMPARE(frame.handle(), QVariant());
+ QCOMPARE(frame.textureHandle(0), 0);
QCOMPARE(frame.pixelFormat(), pixelFormat);
QCOMPARE(frame.size(), size);
QCOMPARE(frame.width(), size.width());
@@ -234,7 +234,7 @@ void tst_QVideoFrame::createInvalid()
QVERIFY(!frame.isValid());
QCOMPARE(frame.handleType(), QVideoFrame::NoHandle);
- QCOMPARE(frame.handle(), QVariant());
+ QCOMPARE(frame.textureHandle(0), 0);
QCOMPARE(frame.pixelFormat(), pixelFormat);
QCOMPARE(frame.size(), size);
QCOMPARE(frame.width(), size.width());