/* takes ownership of tag list */ static gboolean gst_icydemux_tag_found (GstICYDemux * icydemux, GstTagList * tags) { /* send the tag event if we have finished typefinding and have a src pad */ if (icydemux->srcpad) return gst_icydemux_send_tag_event (icydemux, tags); /* if we haven't a source pad yet, cache the tags */ if (!icydemux->cached_tags) { icydemux->cached_tags = tags; } else { gst_tag_list_insert (icydemux->cached_tags, tags, GST_TAG_MERGE_REPLACE_ALL); gst_tag_list_free (tags); } return TRUE; }
static GstFlowReturn gst_icydemux_typefind_or_forward (GstICYDemux * icydemux, GstBuffer * buf) { if (icydemux->typefinding) { GstBuffer *tf_buf; GstCaps *caps = NULL; GstTypeFindProbability prob; /* If we have a content-type from upstream, let's see if we can shortcut * typefinding */ if (G_UNLIKELY (icydemux->content_type)) { if (!g_ascii_strcasecmp (icydemux->content_type, "video/nsv")) { GST_DEBUG ("We have a NSV stream"); caps = gst_caps_new_simple ("video/x-nsv", NULL); } else { GST_DEBUG ("Upstream Content-Type isn't supported"); g_free (icydemux->content_type); icydemux->content_type = NULL; } } if (icydemux->typefind_buf) { icydemux->typefind_buf = gst_buffer_join (icydemux->typefind_buf, buf); } else { icydemux->typefind_buf = buf; } /* Only typefind if we haven't already got some caps */ if (caps == NULL) { caps = gst_type_find_helper_for_buffer (GST_OBJECT (icydemux), icydemux->typefind_buf, &prob); if (caps == NULL) { if (GST_BUFFER_SIZE (icydemux->typefind_buf) < ICY_TYPE_FIND_MAX_SIZE) { /* Just break for more data */ return GST_FLOW_OK; } /* We failed typefind */ GST_ELEMENT_ERROR (icydemux, STREAM, TYPE_NOT_FOUND, (NULL), ("No caps found for contents within an ICY stream")); gst_buffer_unref (icydemux->typefind_buf); icydemux->typefind_buf = NULL; return GST_FLOW_ERROR; } } if (!gst_icydemux_add_srcpad (icydemux, caps)) { GST_DEBUG_OBJECT (icydemux, "Failed to add srcpad"); gst_caps_unref (caps); gst_buffer_unref (icydemux->typefind_buf); icydemux->typefind_buf = NULL; return GST_FLOW_ERROR; } gst_caps_unref (caps); if (icydemux->cached_events) { gst_icydemux_send_cached_events (icydemux); } if (icydemux->cached_tags) { gst_icydemux_send_tag_event (icydemux, icydemux->cached_tags); icydemux->cached_tags = NULL; } /* Move onto streaming: call ourselves recursively with the typefind buffer * to get that forwarded. */ icydemux->typefinding = FALSE; tf_buf = icydemux->typefind_buf; icydemux->typefind_buf = NULL; return gst_icydemux_typefind_or_forward (icydemux, tf_buf); } else { if (G_UNLIKELY (icydemux->srcpad == NULL)) { gst_buffer_unref (buf); return GST_FLOW_ERROR; } buf = gst_buffer_make_metadata_writable (buf); gst_buffer_set_caps (buf, icydemux->src_caps); /* Most things don't care, and it's a pain to track (we should preserve a * 0 offset on the first buffer though if it's there, for id3demux etc.) */ if (GST_BUFFER_OFFSET (buf) != 0) { GST_BUFFER_OFFSET (buf) = GST_BUFFER_OFFSET_NONE; } return gst_pad_push (icydemux->srcpad, buf); } }
static void gst_icydemux_parse_and_send_tags (GstICYDemux * icydemux) { GstTagList *tags = gst_tag_list_new (); const guint8 *data; int length, i; gchar *buffer; gchar **strings; gboolean found_tag = FALSE; length = gst_adapter_available (icydemux->meta_adapter); data = gst_adapter_peek (icydemux->meta_adapter, length); /* Now, copy this to a buffer where we can NULL-terminate it to make things * a bit easier, then do that parsing. */ buffer = g_malloc (length + 1); memcpy (buffer, data, length); buffer[length] = 0; strings = g_strsplit (buffer, "';", 0); for (i = 0; strings[i]; i++) { if (!g_ascii_strncasecmp (strings[i], "StreamTitle=", 12)) { char *title = gst_icydemux_unicodify (strings[i] + 13); if (title && *title) { gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_TITLE, title, NULL); g_free (title); found_tag = TRUE; } } else if (!g_ascii_strncasecmp (strings[i], "StreamUrl=", 10)) { char *url = gst_icydemux_unicodify (strings[i] + 11); if (url) { /* gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_URL, url, NULL); found_tag = TRUE; */ g_free (url); } } } g_strfreev (strings); g_free (buffer); gst_adapter_clear (icydemux->meta_adapter); if (found_tag) { if (icydemux->srcpad) { gst_icydemux_send_tag_event (icydemux, tags); } else { if (!icydemux->cached_tags) { icydemux->cached_tags = gst_tag_list_new (); } gst_tag_list_insert (icydemux->cached_tags, tags, GST_TAG_MERGE_REPLACE_ALL); } } }