From c150928756e6a4f610f3b468914450a2cb5a3ab9 Mon Sep 17 00:00:00 2001 From: Matthew Waters Date: Thu, 3 May 2018 13:59:07 +1000 Subject: [PATCH] glbasefilter: expose finding the local GL context And use it to attempt to find the GL context sooner for upload and color conversion caps transformations. --- ext/gl/gstglcolorconvertelement.c | 32 +++---- ext/gl/gstglcolorconvertelement.h | 2 - ext/gl/gstgluploadelement.c | 41 ++++----- ext/gl/gstgluploadelement.h | 2 - gst-libs/gst/gl/gstglbasefilter.c | 171 +++++++++++++++++++++++--------------- gst-libs/gst/gl/gstglbasefilter.h | 3 + 6 files changed, 132 insertions(+), 119 deletions(-) diff --git a/ext/gl/gstglcolorconvertelement.c b/ext/gl/gstglcolorconvertelement.c index 642b494..9cd041d 100644 --- a/ext/gl/gstglcolorconvertelement.c +++ b/ext/gl/gstglcolorconvertelement.c @@ -76,9 +76,6 @@ gst_gl_color_convert_element_stop (GstBaseTransform * bt) convert->convert = NULL; } - gst_caps_replace (&convert->in_caps, NULL); - gst_caps_replace (&convert->out_caps, NULL); - return GST_BASE_TRANSFORM_CLASS (gst_gl_color_convert_element_parent_class)->stop (bt); @@ -127,11 +124,8 @@ gst_gl_color_convert_element_set_caps (GstBaseTransform * bt, { GstGLColorConvertElement *convert = GST_GL_COLOR_CONVERT_ELEMENT (bt); - gst_caps_replace (&convert->in_caps, in_caps); - gst_caps_replace (&convert->out_caps, out_caps); - - if (convert->convert) - gst_gl_color_convert_set_caps (convert->convert, in_caps, out_caps); + if (!gst_gl_color_convert_set_caps (convert->convert, in_caps, out_caps)) + return FALSE; return TRUE; } @@ -140,7 +134,17 @@ static GstCaps * gst_gl_color_convert_element_transform_caps (GstBaseTransform * bt, GstPadDirection direction, GstCaps * caps, GstCaps * filter) { - GstGLContext *context = GST_GL_BASE_FILTER (bt)->context; + GstGLColorConvertElement *convert = GST_GL_COLOR_CONVERT_ELEMENT (bt); + GstGLBaseFilter *base_filter = GST_GL_BASE_FILTER (bt); + GstGLContext *context; + + if (base_filter->display && !gst_gl_base_filter_find_gl_context (base_filter)) + return NULL; + + context = GST_GL_BASE_FILTER (bt)->context; + + if (!convert->convert && context) + convert->convert = gst_gl_color_convert_new (context); return gst_gl_color_convert_transform_caps (context, direction, caps, filter); } @@ -172,7 +176,6 @@ gst_gl_color_convert_element_decide_allocation (GstBaseTransform * trans, GstQuery * query) { GstGLColorConvertElement *convert = GST_GL_COLOR_CONVERT_ELEMENT (trans); - GstGLContext *context; /* get gl context */ if (!GST_BASE_TRANSFORM_CLASS @@ -180,15 +183,6 @@ gst_gl_color_convert_element_decide_allocation (GstBaseTransform * trans, query)) return FALSE; - context = GST_GL_BASE_FILTER (trans)->context; - - if (!convert->convert) - convert->convert = gst_gl_color_convert_new (context); - - if (!gst_gl_color_convert_set_caps (convert->convert, convert->in_caps, - convert->out_caps)) - return FALSE; - if (!gst_gl_color_convert_decide_allocation (convert->convert, query)) return FALSE; diff --git a/ext/gl/gstglcolorconvertelement.h b/ext/gl/gstglcolorconvertelement.h index 2a0dd1d..211871a 100644 --- a/ext/gl/gstglcolorconvertelement.h +++ b/ext/gl/gstglcolorconvertelement.h @@ -45,8 +45,6 @@ struct _GstGLColorConvertElement GstGLBaseFilter parent; GstGLColorConvert *convert; - GstCaps *in_caps; - GstCaps *out_caps; }; struct _GstGLColorConvertElementClass diff --git a/ext/gl/gstgluploadelement.c b/ext/gl/gstgluploadelement.c index f9e52f6..cac11b5 100644 --- a/ext/gl/gstgluploadelement.c +++ b/ext/gl/gstgluploadelement.c @@ -124,9 +124,6 @@ gst_gl_upload_element_stop (GstBaseTransform * bt) upload->upload = NULL; } - gst_caps_replace (&upload->in_caps, NULL); - gst_caps_replace (&upload->out_caps, NULL); - return GST_BASE_TRANSFORM_CLASS (parent_class)->stop (bt); } @@ -148,11 +145,16 @@ static GstCaps * _gst_gl_upload_element_transform_caps (GstBaseTransform * bt, GstPadDirection direction, GstCaps * caps, GstCaps * filter) { + GstGLBaseFilter *base_filter = GST_GL_BASE_FILTER (bt); GstGLUploadElement *upload = GST_GL_UPLOAD_ELEMENT (bt); - GstGLContext *context = GST_GL_BASE_FILTER (bt)->context; + GstGLContext *context; + if (base_filter->display && !gst_gl_base_filter_find_gl_context (base_filter)) + return NULL; + + context = GST_GL_BASE_FILTER (bt)->context; if (upload->upload == NULL) - upload->upload = gst_gl_upload_new (NULL); + upload->upload = gst_gl_upload_new (context); return gst_gl_upload_transform_caps (upload->upload, context, direction, caps, filter); @@ -171,10 +173,15 @@ _gst_gl_upload_element_propose_allocation (GstBaseTransform * bt, GstQuery * decide_query, GstQuery * query) { GstGLUploadElement *upload = GST_GL_UPLOAD_ELEMENT (bt); + GstGLContext *context = GST_GL_BASE_FILTER (bt)->context; gboolean ret; if (!upload->upload) return FALSE; + if (!context) + return FALSE; + + gst_gl_upload_set_context (upload->upload, context); ret = GST_BASE_TRANSFORM_CLASS (parent_class)->propose_allocation (bt, decide_query, query); @@ -187,23 +194,9 @@ static gboolean _gst_gl_upload_element_decide_allocation (GstBaseTransform * trans, GstQuery * query) { - GstGLUploadElement *upload = GST_GL_UPLOAD_ELEMENT (trans); - GstGLContext *context; - gboolean ret; - - ret = + return GST_BASE_TRANSFORM_CLASS (gst_gl_upload_element_parent_class)->decide_allocation (trans, query); - if (!ret) - return FALSE; - - /* GstGLBaseFilter populates ->context in ::decide_allocation so now it's the - * time to set the ->upload context */ - context = GST_GL_BASE_FILTER (trans)->context; - gst_gl_upload_set_context (upload->upload, context); - - return gst_gl_upload_set_caps (upload->upload, upload->in_caps, - upload->out_caps); } static gboolean @@ -212,13 +205,7 @@ _gst_gl_upload_element_set_caps (GstBaseTransform * bt, GstCaps * in_caps, { GstGLUploadElement *upload = GST_GL_UPLOAD_ELEMENT (bt); - gst_caps_replace (&upload->in_caps, in_caps); - gst_caps_replace (&upload->out_caps, out_caps); - - if (upload->upload) - return gst_gl_upload_set_caps (upload->upload, in_caps, out_caps); - - return TRUE; + return gst_gl_upload_set_caps (upload->upload, in_caps, out_caps); } GstFlowReturn diff --git a/ext/gl/gstgluploadelement.h b/ext/gl/gstgluploadelement.h index 615773c..05f98c3 100644 --- a/ext/gl/gstgluploadelement.h +++ b/ext/gl/gstgluploadelement.h @@ -50,8 +50,6 @@ struct _GstGLUploadElement GstGLBaseFilter parent; GstGLUpload *upload; - GstCaps *in_caps; - GstCaps *out_caps; }; /** diff --git a/gst-libs/gst/gl/gstglbasefilter.c b/gst-libs/gst/gl/gstglbasefilter.c index 3c9eb91..61514ce 100644 --- a/gst-libs/gst/gl/gstglbasefilter.c +++ b/gst-libs/gst/gl/gstglbasefilter.c @@ -63,7 +63,8 @@ enum #define gst_gl_base_filter_parent_class parent_class G_DEFINE_TYPE_WITH_CODE (GstGLBaseFilter, gst_gl_base_filter, GST_TYPE_BASE_TRANSFORM, GST_DEBUG_CATEGORY_INIT (gst_gl_base_filter_debug, - "glbasefilter", 0, "glbasefilter element");); + "glbasefilter", 0, "glbasefilter element"); + ); static void gst_gl_base_filter_finalize (GObject * object); static void gst_gl_base_filter_set_property (GObject * object, guint prop_id, @@ -180,11 +181,13 @@ gst_gl_base_filter_set_context (GstElement * element, GstContext * context) GstGLBaseFilter *filter = GST_GL_BASE_FILTER (element); GstGLBaseFilterClass *filter_class = GST_GL_BASE_FILTER_GET_CLASS (filter); + GST_OBJECT_LOCK (filter); gst_gl_handle_set_context (element, context, &filter->display, &filter->priv->other_context); if (filter->display) gst_gl_display_filter_gl_api (filter->display, filter_class->supported_gl_api); + GST_OBJECT_UNLOCK (filter); GST_ELEMENT_CLASS (parent_class)->set_context (element, context); } @@ -220,8 +223,12 @@ gst_gl_base_filter_query (GstBaseTransform * trans, GstPadDirection direction, } case GST_QUERY_CONTEXT: { - if (gst_gl_handle_context_query ((GstElement *) filter, query, - filter->display, filter->context, filter->priv->other_context)) + gboolean ret; + GST_OBJECT_LOCK (filter); + ret = gst_gl_handle_context_query ((GstElement *) filter, query, + filter->display, filter->context, filter->priv->other_context); + GST_OBJECT_UNLOCK (filter); + if (ret) return TRUE; break; } @@ -319,50 +326,9 @@ gst_gl_base_filter_decide_allocation (GstBaseTransform * trans, { GstGLBaseFilter *filter = GST_GL_BASE_FILTER (trans); GstGLBaseFilterClass *filter_class = GST_GL_BASE_FILTER_GET_CLASS (filter); - GError *error = NULL; - gboolean new_context = FALSE; - - if (!filter->context) - new_context = TRUE; - - _find_local_gl_context (filter); - - if (!filter->context) { - GST_OBJECT_LOCK (filter->display); - do { - if (filter->context) - gst_object_unref (filter->context); - /* just get a GL context. we don't care */ - filter->context = - gst_gl_display_get_gl_context_for_thread (filter->display, NULL); - if (!filter->context) { - if (!gst_gl_display_create_context (filter->display, - filter->priv->other_context, &filter->context, &error)) { - GST_OBJECT_UNLOCK (filter->display); - goto context_error; - } - } - } while (!gst_gl_display_add_context (filter->display, filter->context)); - GST_OBJECT_UNLOCK (filter->display); - } - - if (new_context || !filter->priv->gl_started) { - if (filter->priv->gl_started) - gst_gl_context_thread_add (filter->context, gst_gl_base_filter_gl_stop, - filter); - - { - GstGLAPI current_gl_api = gst_gl_context_get_gl_api (filter->context); - if ((current_gl_api & filter_class->supported_gl_api) == 0) - goto unsupported_gl_api; - } - gst_gl_context_thread_add (filter->context, gst_gl_base_filter_gl_start, - filter); - - if (!filter->priv->gl_started) - goto error; - } + if (!gst_gl_base_filter_find_gl_context (filter)) + return FALSE; if (filter_class->gl_set_caps) { gst_gl_context_thread_add (filter->context, @@ -374,28 +340,6 @@ gst_gl_base_filter_decide_allocation (GstBaseTransform * trans, return GST_BASE_TRANSFORM_CLASS (parent_class)->decide_allocation (trans, query); - -unsupported_gl_api: - { - GstGLAPI gl_api = gst_gl_context_get_gl_api (filter->context); - gchar *gl_api_str = gst_gl_api_to_string (gl_api); - gchar *supported_gl_api_str = - gst_gl_api_to_string (filter_class->supported_gl_api); - GST_ELEMENT_ERROR (filter, RESOURCE, BUSY, - ("GL API's not compatible context: %s supported: %s", gl_api_str, - supported_gl_api_str), (NULL)); - - g_free (supported_gl_api_str); - g_free (gl_api_str); - return FALSE; - } -context_error: - { - GST_ELEMENT_ERROR (trans, RESOURCE, NOT_FOUND, ("%s", error->message), - (NULL)); - g_clear_error (&error); - return FALSE; - } error: { GST_ELEMENT_ERROR (trans, LIBRARY, INIT, @@ -431,8 +375,10 @@ gst_gl_base_filter_change_state (GstElement * element, switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: if (!gst_gl_ensure_element_data (element, &filter->display, - &filter->priv->other_context)) + &filter->priv->other_context)) { + GST_OBJECT_UNLOCK (filter); return GST_STATE_CHANGE_FAILURE; + } gst_gl_display_filter_gl_api (filter->display, filter_class->supported_gl_api); @@ -463,3 +409,90 @@ gst_gl_base_filter_change_state (GstElement * element, return ret; } + +/** + * gst_gl_base_filter_find_gl_context: + * @filter: a #GstGLBaseFilter + * + * Returns: Whether an OpenGL context could be retrieved or created successfully + */ +gboolean +gst_gl_base_filter_find_gl_context (GstGLBaseFilter * filter) +{ + GstGLBaseFilterClass *filter_class = GST_GL_BASE_FILTER_GET_CLASS (filter); + GError *error = NULL; + gboolean new_context = FALSE; + + if (!filter->context) + new_context = TRUE; + + _find_local_gl_context (filter); + + if (!filter->context) { + GST_OBJECT_LOCK (filter->display); + do { + if (filter->context) + gst_object_unref (filter->context); + /* just get a GL context. we don't care */ + filter->context = + gst_gl_display_get_gl_context_for_thread (filter->display, NULL); + if (!filter->context) { + if (!gst_gl_display_create_context (filter->display, + filter->priv->other_context, &filter->context, &error)) { + GST_OBJECT_UNLOCK (filter->display); + goto context_error; + } + } + } while (!gst_gl_display_add_context (filter->display, filter->context)); + GST_OBJECT_UNLOCK (filter->display); + } + + if (new_context || !filter->priv->gl_started) { + if (filter->priv->gl_started) + gst_gl_context_thread_add (filter->context, gst_gl_base_filter_gl_stop, + filter); + + { + GstGLAPI current_gl_api = gst_gl_context_get_gl_api (filter->context); + if ((current_gl_api & filter_class->supported_gl_api) == 0) + goto unsupported_gl_api; + } + + gst_gl_context_thread_add (filter->context, gst_gl_base_filter_gl_start, + filter); + + if (!filter->priv->gl_started) + goto error; + } + + return TRUE; + +unsupported_gl_api: + { + GstGLAPI gl_api = gst_gl_context_get_gl_api (filter->context); + gchar *gl_api_str = gst_gl_api_to_string (gl_api); + gchar *supported_gl_api_str = + gst_gl_api_to_string (filter_class->supported_gl_api); + + GST_ELEMENT_ERROR (filter, RESOURCE, BUSY, + ("GL API's not compatible context: %s supported: %s", gl_api_str, + supported_gl_api_str), (NULL)); + + g_free (supported_gl_api_str); + g_free (gl_api_str); + return FALSE; + } +context_error: + { + GST_ELEMENT_ERROR (filter, RESOURCE, NOT_FOUND, ("%s", error->message), + (NULL)); + g_clear_error (&error); + return FALSE; + } +error: + { + GST_ELEMENT_ERROR (filter, LIBRARY, INIT, + ("Subclass failed to initialize."), (NULL)); + return FALSE; + } +} diff --git a/gst-libs/gst/gl/gstglbasefilter.h b/gst-libs/gst/gl/gstglbasefilter.h index 16d2b68..48c1311 100644 --- a/gst-libs/gst/gl/gstglbasefilter.h +++ b/gst-libs/gst/gl/gstglbasefilter.h @@ -88,6 +88,9 @@ struct _GstGLBaseFilterClass gpointer _padding[GST_PADDING]; }; +GST_EXPORT +gboolean gst_gl_base_filter_find_gl_context (GstGLBaseFilter * filter); + G_END_DECLS #endif /* _GST_GL_BASE_FILTER_H_ */ -- 2.7.4