summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThiago Santos <thiago.sousa.santos@collabora.com>2013-04-11 09:47:51 -0300
committerThiago Santos <thiago.sousa.santos@collabora.com>2013-04-23 10:32:19 -0300
commitce20bc1dc0b718e23968a913404d807b5920bb07 (patch)
treeca35ac37edd50dee82011869d048868114071480
parentd77f76049e60358673b081210c4e7dd8e6bdc801 (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
-rw-r--r--gst/typefind/gsttypefindfunctions.c122
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,