qmlgl6src: Use downstream pool when available

This make use of the pool that has been negotiated with downstream in the
decide_allocation function.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7904>
This commit is contained in:
Nicolas Dufresne 2024-08-29 16:39:14 -04:00 committed by GStreamer Marge Bot
parent c1a8ee9655
commit dccddf203f
3 changed files with 74 additions and 62 deletions

View file

@ -333,7 +333,7 @@ gst_qml6_gl_src_decide_allocation (GstBaseSrc * bsrc, GstQuery * query)
GstStructure *config; GstStructure *config;
GstCaps *caps; GstCaps *caps;
guint min, max, size, n, i; guint min, max, size, n, i;
gboolean update_pool, update_allocator; gboolean update_allocator;
GstAllocator *allocator; GstAllocator *allocator;
GstAllocationParams params; GstAllocationParams params;
GstGLVideoAllocationParams *glparams; GstGLVideoAllocationParams *glparams;
@ -355,23 +355,17 @@ gst_qml6_gl_src_decide_allocation (GstBaseSrc * bsrc, GstQuery * query)
n = gst_query_get_n_allocation_pools (query); n = gst_query_get_n_allocation_pools (query);
if (n > 0) { if (n > 0) {
update_pool = TRUE;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
gst_query_parse_nth_allocation_pool (query, i, &pool, &size, &min, &max); gst_query_parse_nth_allocation_pool (query, i, &pool, &size, &min, &max);
if (!pool || !GST_IS_GL_BUFFER_POOL (pool)) { if (pool && GST_IS_GL_BUFFER_POOL (pool))
break;
if (pool) if (pool)
gst_object_unref (pool); gst_object_unref (pool);
pool = NULL; pool = NULL;
} }
} }
}
if (!pool) {
size = vinfo.size;
min = max = 0;
update_pool = FALSE;
}
if (!qt_src->context && !_find_local_gl_context (qt_src)) if (!qt_src->context && !_find_local_gl_context (qt_src))
return FALSE; return FALSE;
@ -383,6 +377,8 @@ gst_qml6_gl_src_decide_allocation (GstBaseSrc * bsrc, GstQuery * query)
if (!qt_src->context || !GST_IS_GL_CONTEXT (qt_src->context)) if (!qt_src->context || !GST_IS_GL_CONTEXT (qt_src->context))
return FALSE; return FALSE;
size = vinfo.size;
min = max = 0;
pool = gst_gl_buffer_pool_new (qt_src->context); pool = gst_gl_buffer_pool_new (qt_src->context);
GST_INFO_OBJECT (qt_src, "No pool, create one ourself %p", pool); GST_INFO_OBJECT (qt_src, "No pool, create one ourself %p", pool);
} }
@ -423,10 +419,11 @@ gst_qml6_gl_src_decide_allocation (GstBaseSrc * bsrc, GstQuery * query)
if (allocator) if (allocator)
gst_object_unref (allocator); gst_object_unref (allocator);
if (update_pool) if (n > 0)
gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max); gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max);
else else
gst_query_add_allocation_pool (query, pool, size, min, max); gst_query_add_allocation_pool (query, pool, size, min, max);
gst_object_unref (pool); gst_object_unref (pool);
GST_INFO_OBJECT (qt_src, "successfully decide_allocation"); GST_INFO_OBJECT (qt_src, "successfully decide_allocation");
@ -437,20 +434,34 @@ static GstFlowReturn
gst_qml6_gl_src_create (GstPushSrc * psrc, GstBuffer ** buffer) gst_qml6_gl_src_create (GstPushSrc * psrc, GstBuffer ** buffer)
{ {
GstQml6GLSrc *qt_src = GST_QML6_GL_SRC (psrc); GstQml6GLSrc *qt_src = GST_QML6_GL_SRC (psrc);
GstCaps *updated_caps = NULL; gboolean updated_caps = FALSE;
GstGLContext* context = qt_src->context; GstGLContext* context = qt_src->context;
GstGLSyncMeta *sync_meta; GstGLSyncMeta *sync_meta;
retry:
*buffer = qt6_gl_window_take_buffer (qt_src->window, &updated_caps); *buffer = qt6_gl_window_take_buffer (qt_src->window, &updated_caps);
GST_DEBUG_OBJECT (qt_src, "produced buffer %p", *buffer);
if (!*buffer)
return GST_FLOW_FLUSHING;
if (updated_caps) { if (updated_caps) {
GST_DEBUG_OBJECT (qt_src, "new_caps %" GST_PTR_FORMAT, updated_caps); QSize size = qt_src->qwindow->size();
gst_base_src_set_caps (GST_BASE_SRC (qt_src), updated_caps);
/* avoid spurious renegotiation */
if (GST_VIDEO_INFO_WIDTH (&qt_src->v_info) != size.width()
|| GST_VIDEO_INFO_HEIGHT (&qt_src->v_info) != size.height()) {
GST_DEBUG_OBJECT (qt_src, "renegotiation needed");
if (!gst_base_src_negotiate (GST_BASE_SRC (qt_src)))
return GST_FLOW_NOT_NEGOTIATED;
} }
gst_clear_caps (&updated_caps);
qt6_gl_window_set_pool (qt_src->window,
gst_base_src_get_buffer_pool (GST_BASE_SRC (qt_src)));
updated_caps = FALSE;
goto retry;
}
GST_DEBUG_OBJECT (qt_src, "produced buffer %p", *buffer);
if (!*buffer)
return GST_FLOW_FLUSHING;
sync_meta = gst_buffer_get_gl_sync_meta(*buffer); sync_meta = gst_buffer_get_gl_sync_meta(*buffer);
if (sync_meta) if (sync_meta)

View file

@ -60,9 +60,8 @@ struct _Qt6GLWindowPrivate
GstBuffer *buffer; GstBuffer *buffer;
GstVideoInfo v_info; GstVideoInfo v_info;
GstVideoFrame mapped_frame; GstVideoFrame mapped_frame;
GstGLBaseMemoryAllocator *gl_allocator;
GstGLAllocationParams *gl_params;
GLenum internal_format; GLenum internal_format;
GstBufferPool *pool;
gboolean initted; gboolean initted;
gboolean updated; gboolean updated;
@ -122,13 +121,9 @@ Qt6GLWindow::~Qt6GLWindow()
gst_clear_object (&this->priv->other_context); gst_clear_object (&this->priv->other_context);
gst_clear_buffer (&this->priv->buffer); gst_clear_buffer (&this->priv->buffer);
gst_clear_buffer (&this->priv->produced_buffer); gst_clear_buffer (&this->priv->produced_buffer);
gst_clear_object (&this->priv->pool);
gst_clear_object (&this->priv->display); gst_clear_object (&this->priv->display);
gst_clear_object (&this->priv->context); gst_clear_object (&this->priv->context);
gst_clear_object (&this->priv->gl_allocator);
if (this->priv->gl_params)
gst_gl_allocation_params_free (this->priv->gl_params);
this->priv->gl_params = NULL;
g_free (this->priv); g_free (this->priv);
this->priv = NULL; this->priv = NULL;
@ -145,46 +140,43 @@ Qt6GLWindow::beforeRendering()
return; return;
} }
if (this->priv->buffer) {
GST_ERROR ("A rendering already started, something went wrong.");
g_mutex_unlock (&this->priv->lock);
return;
}
QSize size = source->size(); QSize size = source->size();
if (!this->priv->pool
if (!this->priv->gl_allocator) || GST_VIDEO_INFO_WIDTH (&this->priv->v_info) != size.width()
this->priv->gl_allocator =
(GstGLBaseMemoryAllocator *) gst_gl_memory_allocator_get_default (this->priv->context);
if (GST_VIDEO_INFO_WIDTH (&this->priv->v_info) != size.width()
|| GST_VIDEO_INFO_HEIGHT (&this->priv->v_info) != size.height()) { || GST_VIDEO_INFO_HEIGHT (&this->priv->v_info) != size.height()) {
this->priv->new_caps = TRUE; this->priv->new_caps = TRUE;
gst_video_info_set_format (&this->priv->v_info, GST_VIDEO_FORMAT_RGBA, gst_video_info_set_format (&this->priv->v_info, GST_VIDEO_FORMAT_RGBA,
size.width(), size.height()); size.width(), size.height());
gst_clear_object (&this->priv->pool);
if (this->priv->gl_params) { GST_LOG ("resolution change, skipping frames until we have a new pool");
GstGLVideoAllocationParams *gl_vid_params = (GstGLVideoAllocationParams *) this->priv->gl_params; g_cond_signal (&this->priv->update_cond);
if (GST_VIDEO_INFO_WIDTH (gl_vid_params->v_info) != source->width() g_mutex_unlock (&this->priv->lock);
|| GST_VIDEO_INFO_HEIGHT (gl_vid_params->v_info) != source->height()) return;
this->priv->gl_params = NULL;
gst_clear_buffer (&this->priv->buffer);
}
} }
if (!this->priv->gl_params) { GstFlowReturn ret = gst_buffer_pool_acquire_buffer (this->priv->pool,
this->priv->gl_params = (GstGLAllocationParams *) &this->priv->buffer, NULL);
gst_gl_video_allocation_params_new (this->priv->context, NULL, if (ret == GST_FLOW_FLUSHING) {
&this->priv->v_info, 0, NULL, GST_GL_TEXTURE_TARGET_2D, GST_GL_RGBA); g_mutex_unlock (&this->priv->lock);
} return;
} else if (ret != GST_FLOW_OK) {
if (!this->priv->buffer) { GST_WARNING ("failed to acquire buffer");
GstGLMemory *gl_mem = g_mutex_unlock (&this->priv->lock);
(GstGLMemory *) gst_gl_base_memory_alloc (this->priv->gl_allocator, return;
this->priv->gl_params);
this->priv->buffer = gst_buffer_new ();
gst_buffer_append_memory (this->priv->buffer, (GstMemory *) gl_mem);
} }
if (!gst_video_frame_map (&this->priv->mapped_frame, &this->priv->v_info, if (!gst_video_frame_map (&this->priv->mapped_frame, &this->priv->v_info,
this->priv->buffer, (GstMapFlags) (GST_MAP_WRITE | GST_MAP_GL))) { this->priv->buffer, (GstMapFlags) (GST_MAP_WRITE | GST_MAP_GL))) {
GST_WARNING ("failed map video frame"); GST_WARNING ("failed map video frame");
gst_clear_buffer (&this->priv->buffer); gst_clear_buffer (&this->priv->buffer);
g_mutex_unlock (&this->priv->lock);
return; return;
} }
@ -424,7 +416,7 @@ qt6_gl_window_is_scenegraph_initialized (Qt6GLWindow * qt6_gl_window)
} }
GstBuffer * GstBuffer *
qt6_gl_window_take_buffer (Qt6GLWindow * qt6_gl_window, GstCaps ** updated_caps) qt6_gl_window_take_buffer (Qt6GLWindow * qt6_gl_window, gboolean * updated_caps)
{ {
g_return_val_if_fail (qt6_gl_window != NULL, FALSE); g_return_val_if_fail (qt6_gl_window != NULL, FALSE);
g_return_val_if_fail (qt6_gl_window->priv->initted, FALSE); g_return_val_if_fail (qt6_gl_window->priv->initted, FALSE);
@ -438,18 +430,16 @@ qt6_gl_window_take_buffer (Qt6GLWindow * qt6_gl_window, GstCaps ** updated_caps)
return NULL; return NULL;
} }
while (!qt6_gl_window->priv->produced_buffer && qt6_gl_window->priv->result) while (!qt6_gl_window->priv->produced_buffer && qt6_gl_window->priv->result
&& !qt6_gl_window->priv->new_caps)
g_cond_wait (&qt6_gl_window->priv->update_cond, &qt6_gl_window->priv->lock); g_cond_wait (&qt6_gl_window->priv->update_cond, &qt6_gl_window->priv->lock);
ret = qt6_gl_window->priv->produced_buffer; ret = qt6_gl_window->priv->produced_buffer;
qt6_gl_window->priv->produced_buffer = NULL; qt6_gl_window->priv->produced_buffer = NULL;
if (qt6_gl_window->priv->new_caps) { if (!ret && qt6_gl_window->priv->new_caps) {
*updated_caps = gst_video_info_to_caps (&qt6_gl_window->priv->v_info);
gst_caps_set_features (*updated_caps, 0,
gst_caps_features_new_single_static_str
(GST_CAPS_FEATURE_MEMORY_GL_MEMORY));
qt6_gl_window->priv->new_caps = FALSE; qt6_gl_window->priv->new_caps = FALSE;
*updated_caps = TRUE;
} }
g_mutex_unlock (&qt6_gl_window->priv->lock); g_mutex_unlock (&qt6_gl_window->priv->lock);
@ -493,3 +483,13 @@ qt6_gl_window_unlock_stop(Qt6GLWindow* qt6_gl_window)
g_mutex_unlock(&qt6_gl_window->priv->lock); g_mutex_unlock(&qt6_gl_window->priv->lock);
} }
void
qt6_gl_window_set_pool (Qt6GLWindow * qt6_gl_window, GstBufferPool * pool)
{
g_mutex_lock(&qt6_gl_window->priv->lock);
if (qt6_gl_window->priv->pool)
gst_object_unref (qt6_gl_window->priv->pool);
qt6_gl_window->priv->pool = pool;
g_mutex_unlock(&qt6_gl_window->priv->lock);
}

View file

@ -55,7 +55,7 @@ private:
extern "C" extern "C"
{ {
GstBuffer * qt6_gl_window_take_buffer (Qt6GLWindow * qt6_window, GstCaps ** updated_caps); GstBuffer * qt6_gl_window_take_buffer (Qt6GLWindow * qt6_window, gboolean * updated_caps);
GstGLContext * qt6_gl_window_get_qt_context (Qt6GLWindow * qt6_window); GstGLContext * qt6_gl_window_get_qt_context (Qt6GLWindow * qt6_window);
GstGLContext * qt6_gl_window_get_context (Qt6GLWindow * qt6_window); GstGLContext * qt6_gl_window_get_context (Qt6GLWindow * qt6_window);
gboolean qt6_gl_window_set_context (Qt6GLWindow * qt6_window, GstGLContext * context); gboolean qt6_gl_window_set_context (Qt6GLWindow * qt6_window, GstGLContext * context);
@ -64,6 +64,7 @@ gboolean qt6_gl_window_is_scenegraph_initialized (Qt6GLWindow * qt6_windo
void qt6_gl_window_use_default_fbo (Qt6GLWindow * qt6_window, gboolean useDefaultFbo); void qt6_gl_window_use_default_fbo (Qt6GLWindow * qt6_window, gboolean useDefaultFbo);
void qt6_gl_window_unlock(Qt6GLWindow* qt6_window); void qt6_gl_window_unlock(Qt6GLWindow* qt6_window);
void qt6_gl_window_unlock_stop(Qt6GLWindow* qt6_window); void qt6_gl_window_unlock_stop(Qt6GLWindow* qt6_window);
void qt6_gl_window_set_pool (Qt6GLWindow * qt6_window, GstBufferPool * pool);
} }
#endif /* __QT6_GL_WINDOW_H__ */ #endif /* __QT6_GL_WINDOW_H__ */