summaryrefslogtreecommitdiffstats
path: root/src/multimedia
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2021-03-24 21:37:55 +0100
committerLars Knoll <lars.knoll@qt.io>2021-04-07 12:24:44 +0000
commit9e90ac3ce400df30217de98f0eb4e08f75e06cdf (patch)
treedf5844843df9785c69d970e2976a8762b1f165ef /src/multimedia
parent3769db3e753bcb4bb8cd76d71a1ab148cb3fccbb (diff)
More work to enable HW decoding for Qt Quick
Request GL textures from the pipeline for now. Some initial code to also use the texture upload meta functionality in gstreamer, but that will require some more work so we don't make the GL context current in the wrong thread. The gstreamer VAAPI elements on AMD hardware (or in general...) seem to have some bugs. Converting a VASurface to a GL texture using the texture upload meta doesn't create an ARGB texture as promised, but does write some YUV data into the texture. And trying to map a SW buffer received from the VAAPI decoders fails. Change-Id: I9b629eb84f3f32adc23ae2e2fd1cd3e42e6afbc0 Reviewed-by: Doris Verria <doris.verria@qt.io> Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/multimedia')
-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
19 files changed, 175 insertions, 128 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)