Index: multipartdemux.c
===================================================================
RCS file: /cvs/gstreamer/gst-plugins-good/gst/multipart/multipartdemux.c,v
retrieving revision 1.10
diff -u -r1.10 multipartdemux.c
--- multipartdemux.c	8 Dec 2005 16:27:12 -0000	1.10
+++ multipartdemux.c	9 Dec 2005 14:46:28 -0000
@@ -60,6 +60,8 @@
 typedef struct _GstMultipartDemuxClass GstMultipartDemuxClass;
 
 #define MAX_LINE_LEN 500
+#define PREFIX_DEFAULT ("--ThisRandomString\nContent-type: ")
+#define AUTOSCAN_DEFAULT FALSE
 
 /* all information needed for one multipart stream */
 typedef struct
@@ -96,6 +98,11 @@
   gint bufsize;
   gint scanpos;
   gint lastpos;
+  
+  gchar *prefix;
+  gint prefixLen;
+  gboolean first_frame;
+  gboolean autoscan;
 };
 
 struct _GstMultipartDemuxClass
@@ -106,9 +113,6 @@
 GST_DEBUG_CATEGORY_STATIC (gst_multipart_demux_debug);
 #define GST_CAT_DEFAULT gst_multipart_demux_debug
 
-static gchar *toFind = "--ThisRandomString\nContent-type: ";
-static gint toFindLen;
-
 /* elementfactory information */
 static GstElementDetails gst_multipart_demux_details =
 GST_ELEMENT_DETAILS ("multipart demuxer",
@@ -127,6 +131,8 @@
 enum
 {
   ARG_0,
+  ARG_PREFIX,
+  ARG_AUTOSCAN
   /* FILL ME */
 };
 
@@ -148,6 +154,15 @@
 static GstStateChangeReturn gst_multipart_demux_change_state (GstElement *
     element, GstStateChange transition);
 
+static void gst_multipart_set_property(GObject *object, guint prop_id,
+				       const GValue *value,
+				       GParamSpec *pspec);
+
+static void gst_multipart_get_property(GObject *object, guint prop_id,
+				       GValue *value,
+				       GParamSpec *pspec);
+
+static void gst_multipart_demux_finalize (GObject * object);
 
 GST_BOILERPLATE (GstMultipartDemux, gst_multipart_demux, GstElement,
     GST_TYPE_ELEMENT)
@@ -155,23 +170,38 @@
      static void gst_multipart_demux_base_init (gpointer g_class)
 {
   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+  GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
 
   gst_element_class_set_details (element_class, &gst_multipart_demux_details);
+  gobject_class->set_property = gst_multipart_set_property;
+  gobject_class->get_property = gst_multipart_get_property;
 
   gst_element_class_add_pad_template (element_class,
       gst_static_pad_template_get (&multipart_demux_sink_template_factory));
   gst_element_class_add_pad_template (element_class,
       gst_static_pad_template_get (&multipart_demux_src_template_factory));
 
-  toFindLen = strlen (toFind);
+  g_object_class_install_property (gobject_class, ARG_PREFIX,
+      g_param_spec_string ("prefix", "prefix", "prefix",
+			   PREFIX_DEFAULT, 
+			   G_PARAM_READWRITE | G_PARAM_CONSTRUCT ));
+
+  g_object_class_install_property (gobject_class, ARG_AUTOSCAN,
+      g_param_spec_boolean ("autoscan", "autoscan", 
+			    "Try to autofind the prefix",
+			    AUTOSCAN_DEFAULT, 
+			    G_PARAM_READWRITE | G_PARAM_CONSTRUCT ));
+
 }
 
 static void
 gst_multipart_demux_class_init (GstMultipartDemuxClass * klass)
 {
   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
   gstelement_class->change_state = gst_multipart_demux_change_state;
+  gobject_class->finalize = gst_multipart_demux_finalize;
 }
 
 static void
@@ -191,8 +221,24 @@
   multipart->numpads = 0;
   multipart->scanpos = 0;
   multipart->lastpos = 0;
+  
+  multipart->prefix = g_strdup (PREFIX_DEFAULT);
+  multipart->prefixLen = strlen (multipart->prefix);
+  multipart->first_frame = TRUE;
+  multipart->autoscan = AUTOSCAN_DEFAULT;
+}
+
+static void
+gst_multipart_demux_finalize (GObject * object)
+{
+  GstMultipartDemux *demux = GST_MULTIPART_DEMUX (object);
+
+  g_free (demux->prefix);
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
+
 static GstMultipartPad *
 gst_multipart_find_pad_by_mime (GstMultipartDemux * demux, gchar * mime,
     gboolean * created)
@@ -269,6 +315,47 @@
   memcpy (multipart->buffer + multipart->bufsize, data, size);
   multipart->bufsize += size;
 
+
+  if ((TRUE == multipart->first_frame) && (TRUE == multipart->autoscan)) {
+    /* find the prefix if this is the first buffer */    
+    /* the prefix is like --prefix\r\n */
+    size_t i, start;
+    
+    i = 0;
+    start = -1;
+    
+    while ((i+1) < multipart->bufsize) {
+      
+      if (-1 == start) {
+	if ((multipart->buffer[i] == '-') &&
+	    (multipart->buffer[i + 1] == '-')) {
+	  start = i + 2; /* discart -- */
+	}
+      }else {
+	/* look for \r\n or \n\n */
+	if ((multipart->buffer[i] == '\n') ||
+	    ((multipart->buffer[i] == '\r') &&
+	     (multipart->buffer[i + 1] == '\n'))) {
+	  
+	  /* found first \r\n, the prefix is from 0 to i */
+
+	  g_free (multipart->prefix);
+	  multipart->prefix = g_strndup (multipart->buffer + start, (i - start));
+	  multipart->prefixLen = strlen (multipart->prefix);
+	  GST_DEBUG_OBJECT (multipart, 
+			    "set prefix to [%s]\n", multipart->prefix);
+	  
+	  multipart->first_frame = FALSE;
+	  break;
+	}
+      }
+      
+      i++;
+    }
+    
+  }
+
+
   /* find \n */
   while (multipart->scanpos < multipart->bufsize) {
     if (multipart->buffer[multipart->scanpos] == '\n') {
@@ -279,11 +366,11 @@
 
   /* then scan for the boundary */
   for (matchpos = 0;
-      multipart->scanpos + toFindLen + MAX_LINE_LEN - matchpos <
+      multipart->scanpos + multipart->prefixLen + MAX_LINE_LEN - matchpos <
       multipart->bufsize; multipart->scanpos++) {
-    if (multipart->buffer[multipart->scanpos] == toFind[matchpos]) {
+    if (multipart->buffer[multipart->scanpos] == multipart->prefix[matchpos]) {
       matchpos++;
-      if (matchpos == toFindLen) {
+      if (matchpos == multipart->prefixLen) {
         int datalen;
         int i, start;
         gchar *mime_type;
@@ -370,6 +457,7 @@
 
   switch (transition) {
     case GST_STATE_CHANGE_NULL_TO_READY:
+      multipart->first_frame = TRUE;
       break;
     case GST_STATE_CHANGE_READY_TO_PAUSED:
       multipart->buffer = g_malloc (multipart->maxlen);
@@ -402,6 +490,52 @@
   return ret;
 }
 
+static void
+gst_multipart_set_property (GObject *object, guint prop_id,
+			    const GValue *value, GParamSpec *pspec)
+{
+  GstMultipartDemux *filter;
+
+  g_return_if_fail (GST_IS_MULTIPART_DEMUX (object));
+  filter = GST_MULTIPART_DEMUX (object);
+
+  switch (prop_id) {
+  case ARG_PREFIX:
+    g_free (filter->prefix);
+    filter->prefix = g_value_dup_string (value);
+    filter->prefixLen = strlen (filter->prefix);
+    break;
+  case ARG_AUTOSCAN:
+    filter->autoscan = g_value_get_boolean (value);
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    break;
+  }
+}
+
+static void
+gst_multipart_get_property (GObject *object, guint prop_id,
+			    GValue *value, GParamSpec *pspec)
+{
+  GstMultipartDemux *filter;
+  
+  g_return_if_fail (GST_IS_MULTIPART_DEMUX (object));
+  filter = GST_MULTIPART_DEMUX (object);
+  
+  switch (prop_id) {
+  case ARG_PREFIX:
+    g_value_set_string (value, filter->prefix);
+    break;
+  case ARG_AUTOSCAN:
+     g_value_set_boolean (value, filter->autoscan);
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    break;
+  }
+}
+
 gboolean
 gst_multipart_demux_plugin_init (GstPlugin * plugin)
 {
