From 6b8cf8419d8ea80081de8150a6b1c3cf763c4d69 Mon Sep 17 00:00:00 2001 From: Matthew Waters Date: Sat, 8 Aug 2015 17:28:03 +0200 Subject: [PATCH] qml: implement the required multiple GL context synchonisation From GStreamer's GL context into the QML context --- ext/qt/gstqsgtexture.cc | 32 ++++++++++++++++++++++++++++++-- ext/qt/gstqsgtexture.h | 6 +++++- ext/qt/qtitem.cc | 7 +++++-- 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/ext/qt/gstqsgtexture.cc b/ext/qt/gstqsgtexture.cc index 1e5203832a..a9be90c198 100644 --- a/ext/qt/gstqsgtexture.cc +++ b/ext/qt/gstqsgtexture.cc @@ -45,11 +45,13 @@ GstQSGTexture::GstQSGTexture () gst_video_info_init (&this->v_info); this->buffer_ = NULL; + this->sync_buffer_ = gst_buffer_new (); } GstQSGTexture::~GstQSGTexture () { gst_buffer_replace (&this->buffer_, NULL); + gst_buffer_replace (&this->sync_buffer_, NULL); } /* only called from the streaming thread with scene graph thread blocked */ @@ -62,18 +64,26 @@ GstQSGTexture::setCaps (GstCaps * caps) } /* only called from the streaming thread with scene graph thread blocked */ -void +gboolean GstQSGTexture::setBuffer (GstBuffer * buffer) { GST_LOG ("%p setBuffer %" GST_PTR_FORMAT, this, buffer); /* FIXME: update more state here */ - gst_buffer_replace (&this->buffer_, buffer); + if (!gst_buffer_replace (&this->buffer_, buffer)) + return FALSE; + + this->qt_context_ = gst_gl_context_get_current (); + + return TRUE; } /* only called from qt's scene graph render thread */ void GstQSGTexture::bind () { + GstGLContext *context; + GstGLSyncMeta *sync_meta; + GstMemory *mem; guint tex_id; if (!this->buffer_) @@ -81,6 +91,10 @@ GstQSGTexture::bind () if (GST_VIDEO_INFO_FORMAT (&this->v_info) == GST_VIDEO_FORMAT_UNKNOWN) return; + this->mem_ = gst_buffer_peek_memory (this->buffer_, 0); + if (!this->mem_) + return; + /* FIXME: should really lock the memory to prevent write access */ if (!gst_video_frame_map (&this->v_frame, &this->v_info, this->buffer_, (GstMapFlags) (GST_MAP_READ | GST_MAP_GL))) { @@ -88,6 +102,20 @@ GstQSGTexture::bind () return; } + mem = gst_buffer_peek_memory (this->buffer_, 0); + g_assert (gst_is_gl_memory (mem)); + + context = ((GstGLBaseBuffer *)mem)->context; + + sync_meta = gst_buffer_get_gl_sync_meta (this->sync_buffer_); + if (!sync_meta) + sync_meta = gst_buffer_add_gl_sync_meta (context, this->sync_buffer_); + + gst_gl_sync_meta_set_sync_point (sync_meta, context); + + g_assert (this->qt_context_); + gst_gl_sync_meta_wait (sync_meta, this->qt_context_); + tex_id = *(guint *) this->v_frame.data[0]; GST_LOG ("%p binding Qt texture %u", this, tex_id); diff --git a/ext/qt/gstqsgtexture.h b/ext/qt/gstqsgtexture.h index 93fb60d063..bf8f03f4ec 100644 --- a/ext/qt/gstqsgtexture.h +++ b/ext/qt/gstqsgtexture.h @@ -25,6 +25,7 @@ #include #include #include +#include class GstQSGTexture : public QSGTexture, protected QOpenGLFunctions { @@ -34,7 +35,7 @@ public: ~GstQSGTexture (); void setCaps (GstCaps * caps); - void setBuffer (GstBuffer * buffer); + gboolean setBuffer (GstBuffer * buffer); /* QSGTexture */ void bind (); @@ -45,6 +46,9 @@ public: private: GstBuffer * buffer_; + GstBuffer * sync_buffer_; + GstGLContext * qt_context_; + GstMemory * mem_; GstVideoInfo v_info; GstVideoFrame v_frame; }; diff --git a/ext/qt/qtitem.cc b/ext/qt/qtitem.cc index 7686a7378e..8c3e4b9be3 100644 --- a/ext/qt/qtitem.cc +++ b/ext/qt/qtitem.cc @@ -171,6 +171,7 @@ QtGLVideoItem::updatePaintNode(QSGNode * oldNode, GstQSGTexture *tex; g_mutex_lock (&this->priv->lock); + gst_gl_context_activate (this->priv->other_context, TRUE); GST_TRACE ("%p updatePaintNode", this); @@ -181,14 +182,15 @@ QtGLVideoItem::updatePaintNode(QSGNode * oldNode, if (!texNode) { texNode = new QSGSimpleTextureNode (); - tex = new GstQSGTexture (); - texNode->setTexture (tex); + texNode->setOwnsTexture (true); } else { tex = static_cast (texNode->texture()); } + tex = new GstQSGTexture (); tex->setCaps (this->priv->caps); tex->setBuffer (this->priv->buffer); + texNode->setTexture (tex); if (this->priv->force_aspect_ratio) { src.w = this->priv->display_width; @@ -209,6 +211,7 @@ QtGLVideoItem::updatePaintNode(QSGNode * oldNode, texNode->setRect (QRectF (result.x, result.y, result.w, result.h)); + gst_gl_context_activate (this->priv->other_context, FALSE); g_mutex_unlock (&this->priv->lock); return texNode;