#ifdef HAVE_CONFIG_H # include <config.h> #endif #include <string.h> #include <gst/gst.h> #include "gstdashdemux.h" #define XML_BUFFER_SIZE 16 #define XML_INC_BUFFER { \ pos++; \ if (pos == XML_BUFFER_SIZE) { \ pos = 0; \ offset += XML_BUFFER_SIZE; \ data = gst_type_find_peek (tf, offset, XML_BUFFER_SIZE); \ if (data == NULL) return FALSE; \ } else { \ data++; \ } \ } static gboolean xml_check_first_element (GstTypeFind * tf, const gchar * element, guint elen, gboolean strict) { gboolean got_xmldec; const guint8 *data; guint offset = 0; guint pos = 0; data = gst_type_find_peek (tf, 0, XML_BUFFER_SIZE); if (!data) 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) { 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 && (offset + pos) < 4096) { while (*data != '<' && (offset + pos) < 4096) { XML_INC_BUFFER; } XML_INC_BUFFER; if (!g_ascii_isalpha (*data)) { /* if not alphabetic, it's a PI or an element / attribute declaration * like <?xxx or <!xxx */ XML_INC_BUFFER; continue; } /* the first normal element, check if it's the one asked for */ data = gst_type_find_peek (tf, offset + pos, elen + 1); return (data && element && strncmp ((char *) data, element, elen) == 0); } return FALSE; } /*** application/dash+xml typefind helper ***/ static GstStaticCaps dash_caps = GST_STATIC_CAPS ("application/dash+xml"); #define DASH_CAPS gst_static_caps_get (&dash_caps) static void dash_type_find (GstTypeFind * tf, gpointer unused) { if (xml_check_first_element (tf, "MPD", 3, FALSE) || xml_check_first_element (tf, "mpd", 3, FALSE)) { gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, DASH_CAPS); } } static gboolean fragmented_init (GstPlugin * plugin) { if (!gst_element_register (plugin, "dashdemux", GST_RANK_PRIMARY, GST_TYPE_DASH_DEMUX) || FALSE) return FALSE; gst_type_find_register (plugin, "application/dash+xml", GST_RANK_SECONDARY, dash_type_find, NULL, DASH_CAPS, NULL, NULL); return TRUE; } GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, dashdemux, "DASH demuxer plugin", fragmented_init, VERSION, "LGPL", PACKAGE_NAME, "http://www.gstreamer.org/")