diff options
author | Thiago Santos <thiago.sousa.santos@collabora.com> | 2013-04-11 09:47:51 -0300 |
---|---|---|
committer | Thiago Santos <thiago.sousa.santos@collabora.com> | 2013-04-23 10:32:19 -0300 |
commit | ce20bc1dc0b718e23968a913404d807b5920bb07 (patch) | |
tree | ca35ac37edd50dee82011869d048868114071480 /gst/typefind | |
parent | d77f76049e60358673b081210c4e7dd8e6bdc801 (diff) |
typefind: add smoothstreaming manifest typefinding
Checks if the received XML is a smoothstreaming manifest
in both UTF8 and UTF16 formats. The check is made for a
SmoothStreamingMedia top level element.
Conflicts:
gst/typefind/gsttypefindfunctions.c
Diffstat (limited to 'gst/typefind')
-rw-r--r-- | gst/typefind/gsttypefindfunctions.c | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/gst/typefind/gsttypefindfunctions.c b/gst/typefind/gsttypefindfunctions.c index faf55b97f..b3134d537 100644 --- a/gst/typefind/gsttypefindfunctions.c +++ b/gst/typefind/gsttypefindfunctions.c @@ -477,6 +477,67 @@ hls_type_find (GstTypeFind * tf, gpointer unused) } \ } +#define XML_INC_BUFFER_DATA { \ + pos++; \ + if (pos >= length) { \ + return FALSE; \ + } else { \ + data++; \ + } \ +} + +static gboolean +xml_check_first_element_from_data (const guint8 * data, guint length, + const gchar * element, guint elen, gboolean strict) +{ + gboolean got_xmldec; + guint pos = 0; + + g_return_val_if_fail (data != NULL, FALSE); + + if (length <= 5) + return FALSE; + + /* look for the XMLDec + * see XML spec 2.8, Prolog and Document Type Declaration + * http://www.w3.org/TR/2004/REC-xml-20040204/#sec-prolog-dtd */ + got_xmldec = (memcmp (data, "<?xml", 5) == 0); + + if (strict && !got_xmldec) + return FALSE; + + /* skip XMLDec in any case if we've got one */ + if (got_xmldec) { + if (pos + 5 >= length) + return FALSE; + pos += 5; + data += 5; + } + + /* look for the first element, it has to be the requested element. Bail + * out if it is not within the first 4kB. */ + while (data && pos < MIN (4096, length)) { + while (*data != '<' && pos < MIN (4096, length)) { + XML_INC_BUFFER_DATA; + } + + XML_INC_BUFFER_DATA; + if (!g_ascii_isalpha (*data)) { + /* if not alphabetic, it's a PI or an element / attribute declaration + * like <?xxx or <!xxx */ + XML_INC_BUFFER_DATA; + continue; + } + + /* the first normal element, check if it's the one asked for */ + if (pos + elen + 1 >= length) + return FALSE; + return (data && element && strncmp ((char *) data, element, elen) == 0); + } + + return FALSE; +} + static gboolean xml_check_first_element (GstTypeFind * tf, const gchar * element, guint elen, gboolean strict) @@ -3199,6 +3260,64 @@ swf_type_find (GstTypeFind * tf, gpointer unused) } } +/*** application/vnd.ms-sstr+xml ***/ + +static GstStaticCaps mss_manifest_caps = +GST_STATIC_CAPS ("application/vnd.ms-sstr+xml"); +#define MSS_MANIFEST_CAPS (gst_static_caps_get(&mss_manifest_caps)) +static void +mss_manifest_type_find (GstTypeFind * tf, gpointer unused) +{ + if (xml_check_first_element (tf, "SmoothStreamingMedia", 20, TRUE)) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MSS_MANIFEST_CAPS); + } else { + const guint8 *data; + gboolean utf16_le, utf16_be; + const gchar *convert_from = NULL; + guint8 *converted_data; + + /* try detecting the charset */ + data = gst_type_find_peek (tf, 0, 2); + + /* look for a possible BOM */ + utf16_le = data[0] == 0xFF && data[1] == 0xFE; + utf16_be = data[0] == 0xFE && data[1] == 0xFF; + if (utf16_le) { + convert_from = "UTF-16LE"; + } else if (utf16_be) { + convert_from = "UTF-16BE"; + } + + if (convert_from) { + gsize new_size = 0; + guint length = gst_type_find_get_length (tf); + + /* try a default that should be enough */ + if (length == 0) + length = 512; + data = gst_type_find_peek (tf, 0, length); + + if (data) { + /* skip the BOM */ + data += 2; + length -= 2; + + converted_data = + (guint8 *) g_convert ((gchar *) data, length, "UTF-8", convert_from, + NULL, &new_size, NULL); + if (converted_data) { + if (xml_check_first_element_from_data (converted_data, new_size, + "SmoothStreamingMedia", 20, TRUE)) + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, + MSS_MANIFEST_CAPS); + + g_free (converted_data); + } + } + } + } +} + /*** image/jpeg ***/ #define JPEG_MARKER_IS_START_OF_FRAME(x) \ @@ -5058,6 +5177,9 @@ plugin_init (GstPlugin * plugin) GST_TYPE_FIND_MAXIMUM); TYPE_FIND_REGISTER (plugin, "application/x-shockwave-flash", GST_RANK_SECONDARY, swf_type_find, "swf,swfl", SWF_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "application/vnd.ms-sstr+xml", + GST_RANK_PRIMARY, mss_manifest_type_find, NULL, MSS_MANIFEST_CAPS, NULL, + NULL); TYPE_FIND_REGISTER_START_WITH (plugin, "video/x-flv", GST_RANK_SECONDARY, "flv", "FLV", 3, GST_TYPE_FIND_MAXIMUM); TYPE_FIND_REGISTER (plugin, "text/plain", GST_RANK_MARGINAL, utf8_type_find, |