From 59c34a8ff75d8cbfb24759711a2c35599f9ae52d Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 25 Aug 2014 13:44:30 -0300 Subject: [PATCH] baseparse: handle streamheaders by prepending them to the stream Add a first_buffer boolean state flag to have baseparse do actions before pushing data. This is used to check the caps for streamheader buffers that are prepended to the stream, but only if the first buffer isn't already marked with the _HEADER flag. In this case, it is assumed that the _HEADER marked buffer is the same as the streamheader. https://bugzilla.gnome.org/show_bug.cgi?id=735070 --- libs/gst/base/gstbaseparse.c | 66 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/libs/gst/base/gstbaseparse.c b/libs/gst/base/gstbaseparse.c index fdc2673..8fd1103 100644 --- a/libs/gst/base/gstbaseparse.c +++ b/libs/gst/base/gstbaseparse.c @@ -350,6 +350,9 @@ struct _GstBaseParsePrivate GList *detect_buffers; guint detect_buffers_size; + /* True when no buffers have been received yet */ + gboolean first_buffer; + /* if TRUE, a STREAM_START event needs to be pushed */ gboolean push_stream_start; }; @@ -856,6 +859,8 @@ gst_base_parse_reset (GstBaseParse * parse) parse->priv->new_frame = TRUE; + parse->priv->first_buffer = TRUE; + g_list_foreach (parse->priv->detect_buffers, (GFunc) gst_buffer_unref, NULL); g_list_free (parse->priv->detect_buffers); parse->priv->detect_buffers = NULL; @@ -2714,6 +2719,53 @@ gst_base_parse_check_sync (GstBaseParse * parse) } static GstFlowReturn +gst_base_parse_process_streamheader (GstBaseParse * parse) +{ + GstCaps *caps; + GstStructure *str; + const GValue *value; + GstFlowReturn ret = GST_FLOW_OK; + + caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (parse)); + if (caps == NULL) + goto notfound; + + str = gst_caps_get_structure (caps, 0); + value = gst_structure_get_value (str, "streamheader"); + if (value == NULL) + goto notfound; + + GST_DEBUG_OBJECT (parse, "Found streamheader field on input caps"); + + if (GST_VALUE_HOLDS_ARRAY (value)) { + gint i; + gsize len = gst_value_array_get_size (value); + + for (i = 0; i < len; i++) { + GstBuffer *buffer = + gst_value_get_buffer (gst_value_array_get_value (value, i)); + ret = + gst_base_parse_chain (GST_BASE_PARSE_SINK_PAD (parse), + GST_OBJECT_CAST (parse), gst_buffer_ref (buffer)); + } + + } else if (GST_VALUE_HOLDS_BUFFER (value)) { + GstBuffer *buffer = gst_value_get_buffer (value); + ret = + gst_base_parse_chain (GST_BASE_PARSE_SINK_PAD (parse), + GST_OBJECT_CAST (parse), gst_buffer_ref (buffer)); + } + + return ret; + +notfound: + { + GST_DEBUG_OBJECT (parse, "No streamheader on caps"); + return GST_FLOW_OK; + } +} + +static GstFlowReturn gst_base_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) { GstBaseParseClass *bclass; @@ -2730,6 +2782,20 @@ gst_base_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) parse = GST_BASE_PARSE (parent); bclass = GST_BASE_PARSE_GET_CLASS (parse); + if (G_UNLIKELY (parse->priv->first_buffer)) { + parse->priv->first_buffer = FALSE; + if (!GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_HEADER)) { + /* this stream has no header buffers, check if we just prepend the + * streamheader from caps to the stream */ + GST_DEBUG_OBJECT (parse, "Looking for streamheader field on caps to " + "prepend to the stream"); + gst_base_parse_process_streamheader (parse); + } else { + GST_DEBUG_OBJECT (parse, "Stream has header buffers, not prepending " + "streamheader from caps"); + } + } + if (parse->priv->detecting) { GstBuffer *detect_buf; -- 2.7.4