diff --git a/subprojects/gst-plugins-good/ext/qt6/gstqml6glsrc.cc b/subprojects/gst-plugins-good/ext/qt6/gstqml6glsrc.cc index 5a4a1fbd31..017edb9160 100644 --- a/subprojects/gst-plugins-good/ext/qt6/gstqml6glsrc.cc +++ b/subprojects/gst-plugins-good/ext/qt6/gstqml6glsrc.cc @@ -333,7 +333,7 @@ gst_qml6_gl_src_decide_allocation (GstBaseSrc * bsrc, GstQuery * query) GstStructure *config; GstCaps *caps; guint min, max, size, n, i; - gboolean update_pool, update_allocator; + gboolean update_allocator; GstAllocator *allocator; GstAllocationParams params; GstGLVideoAllocationParams *glparams; @@ -355,22 +355,16 @@ gst_qml6_gl_src_decide_allocation (GstBaseSrc * bsrc, GstQuery * query) n = gst_query_get_n_allocation_pools (query); if (n > 0) { - update_pool = TRUE; for (i = 0; i < n; i++) { gst_query_parse_nth_allocation_pool (query, i, &pool, &size, &min, &max); - if (!pool || !GST_IS_GL_BUFFER_POOL (pool)) { - if (pool) - gst_object_unref (pool); - pool = NULL; - } - } - } + if (pool && GST_IS_GL_BUFFER_POOL (pool)) + break; - if (!pool) { - size = vinfo.size; - min = max = 0; - update_pool = FALSE; + if (pool) + gst_object_unref (pool); + pool = NULL; + } } if (!qt_src->context && !_find_local_gl_context (qt_src)) @@ -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)) return FALSE; + size = vinfo.size; + min = max = 0; pool = gst_gl_buffer_pool_new (qt_src->context); 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) gst_object_unref (allocator); - if (update_pool) + if (n > 0) gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max); else gst_query_add_allocation_pool (query, pool, size, min, max); + gst_object_unref (pool); GST_INFO_OBJECT (qt_src, "successfully decide_allocation"); @@ -437,20 +434,34 @@ static GstFlowReturn gst_qml6_gl_src_create (GstPushSrc * psrc, GstBuffer ** buffer) { GstQml6GLSrc *qt_src = GST_QML6_GL_SRC (psrc); - GstCaps *updated_caps = NULL; + gboolean updated_caps = FALSE; GstGLContext* context = qt_src->context; GstGLSyncMeta *sync_meta; +retry: *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) { - GST_DEBUG_OBJECT (qt_src, "new_caps %" GST_PTR_FORMAT, updated_caps); - gst_base_src_set_caps (GST_BASE_SRC (qt_src), updated_caps); + QSize size = qt_src->qwindow->size(); + + /* 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; + } + + 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_clear_caps (&updated_caps); + + GST_DEBUG_OBJECT (qt_src, "produced buffer %p", *buffer); + + if (!*buffer) + return GST_FLOW_FLUSHING; sync_meta = gst_buffer_get_gl_sync_meta(*buffer); if (sync_meta) diff --git a/subprojects/gst-plugins-good/ext/qt6/qt6glwindow.cc b/subprojects/gst-plugins-good/ext/qt6/qt6glwindow.cc index ca51cf5a20..6eb0d09f42 100644 --- a/subprojects/gst-plugins-good/ext/qt6/qt6glwindow.cc +++ b/subprojects/gst-plugins-good/ext/qt6/qt6glwindow.cc @@ -60,9 +60,8 @@ struct _Qt6GLWindowPrivate GstBuffer *buffer; GstVideoInfo v_info; GstVideoFrame mapped_frame; - GstGLBaseMemoryAllocator *gl_allocator; - GstGLAllocationParams *gl_params; GLenum internal_format; + GstBufferPool *pool; gboolean initted; gboolean updated; @@ -122,13 +121,9 @@ Qt6GLWindow::~Qt6GLWindow() gst_clear_object (&this->priv->other_context); gst_clear_buffer (&this->priv->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->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); this->priv = NULL; @@ -145,46 +140,43 @@ Qt6GLWindow::beforeRendering() 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(); - - if (!this->priv->gl_allocator) - 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() + if (!this->priv->pool + || GST_VIDEO_INFO_WIDTH (&this->priv->v_info) != size.width() || GST_VIDEO_INFO_HEIGHT (&this->priv->v_info) != size.height()) { this->priv->new_caps = TRUE; - gst_video_info_set_format (&this->priv->v_info, GST_VIDEO_FORMAT_RGBA, size.width(), size.height()); + gst_clear_object (&this->priv->pool); - if (this->priv->gl_params) { - GstGLVideoAllocationParams *gl_vid_params = (GstGLVideoAllocationParams *) this->priv->gl_params; - if (GST_VIDEO_INFO_WIDTH (gl_vid_params->v_info) != source->width() - || GST_VIDEO_INFO_HEIGHT (gl_vid_params->v_info) != source->height()) - this->priv->gl_params = NULL; - gst_clear_buffer (&this->priv->buffer); - } + GST_LOG ("resolution change, skipping frames until we have a new pool"); + g_cond_signal (&this->priv->update_cond); + g_mutex_unlock (&this->priv->lock); + return; } - if (!this->priv->gl_params) { - this->priv->gl_params = (GstGLAllocationParams *) - gst_gl_video_allocation_params_new (this->priv->context, NULL, - &this->priv->v_info, 0, NULL, GST_GL_TEXTURE_TARGET_2D, GST_GL_RGBA); - } - - if (!this->priv->buffer) { - GstGLMemory *gl_mem = - (GstGLMemory *) gst_gl_base_memory_alloc (this->priv->gl_allocator, - this->priv->gl_params); - this->priv->buffer = gst_buffer_new (); - gst_buffer_append_memory (this->priv->buffer, (GstMemory *) gl_mem); + GstFlowReturn ret = gst_buffer_pool_acquire_buffer (this->priv->pool, + &this->priv->buffer, NULL); + if (ret == GST_FLOW_FLUSHING) { + g_mutex_unlock (&this->priv->lock); + return; + } else if (ret != GST_FLOW_OK) { + GST_WARNING ("failed to acquire buffer"); + g_mutex_unlock (&this->priv->lock); + return; } if (!gst_video_frame_map (&this->priv->mapped_frame, &this->priv->v_info, this->priv->buffer, (GstMapFlags) (GST_MAP_WRITE | GST_MAP_GL))) { GST_WARNING ("failed map video frame"); gst_clear_buffer (&this->priv->buffer); + g_mutex_unlock (&this->priv->lock); return; } @@ -424,7 +416,7 @@ qt6_gl_window_is_scenegraph_initialized (Qt6GLWindow * qt6_gl_window) } 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->priv->initted, FALSE); @@ -438,18 +430,16 @@ qt6_gl_window_take_buffer (Qt6GLWindow * qt6_gl_window, GstCaps ** updated_caps) 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); ret = qt6_gl_window->priv->produced_buffer; qt6_gl_window->priv->produced_buffer = NULL; - if (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)); + if (!ret && qt6_gl_window->priv->new_caps) { qt6_gl_window->priv->new_caps = FALSE; + *updated_caps = TRUE; } 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); } + +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); +} diff --git a/subprojects/gst-plugins-good/ext/qt6/qt6glwindow.h b/subprojects/gst-plugins-good/ext/qt6/qt6glwindow.h index 3c0fc14d97..8f7d56a304 100644 --- a/subprojects/gst-plugins-good/ext/qt6/qt6glwindow.h +++ b/subprojects/gst-plugins-good/ext/qt6/qt6glwindow.h @@ -55,7 +55,7 @@ private: 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_context (Qt6GLWindow * qt6_window); 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_unlock(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__ */