Index: ChangeLog
===================================================================
RCS file: /home/cvs/gstreamer/gstreamer/ChangeLog,v
retrieving revision 1.789
diff -u -r1.789 ChangeLog
--- ChangeLog	19 Sep 2004 07:58:12 -0000	1.789
+++ ChangeLog	25 Sep 2004 13:49:49 -0000
@@ -1,3 +1,20 @@
+2004-09-24  Ronald S. Bultje  <rbultje@ronald.bitfreak.net>
+
+	* gst/elements/gsttypefindelement.c: (stop_typefinding),
+	(gst_type_find_element_handle_event),
+	(gst_type_find_element_chain):
+	* gst/elements/gsttypefindelement.h:
+	  Prevent output of discont events after typefinding. Typefind
+	  will seek until the position of its internal bufferstore size
+	  and then act as an identity. However, filesrc, gnomevfssrc or
+	  any other seekable element will send a discont before this, and
+	  this breaks a surprising amount of elements (including, but not
+	  limited to, avidemux, asfdemux and matroskademux). This patch
+	  makes typefind filter out this discont event. Has been tested
+	  with both seekable and non-seekable elements and has the correct
+	  behaviour in both cases. Also fixes the mentioned demuxers in
+	  pipelines with typefind.
+
 2004-09-19  Steve Lhomme  <steve.lhomme@free.fr>
 
 	* win32/dirent.c:
Index: gst/elements/gsttypefindelement.c
===================================================================
RCS file: /home/cvs/gstreamer/gstreamer/gst/elements/gsttypefindelement.c,v
retrieving revision 1.18
diff -u -r1.18 gsttypefindelement.c
--- gst/elements/gsttypefindelement.c	12 Aug 2004 09:12:13 -0000	1.18
+++ gst/elements/gsttypefindelement.c	25 Sep 2004 13:49:50 -0000
@@ -84,6 +84,8 @@
 enum
 {
   MODE_NORMAL,                  /* act as identity */
+  MODE_TRANSITION,              /* wait for the discont between the two
+                                 * other modes */
   MODE_TYPEFIND                 /* do typefinding */
 };
 
@@ -277,7 +279,7 @@
 {
   GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
 
-  if (typefind->mode == MODE_TYPEFIND) {
+  if (typefind->mode != MODE_NORMAL) {
     /* need to do more? */
     gst_data_unref (GST_DATA (event));
     return FALSE;
@@ -350,10 +352,11 @@
     typefind->possibilities = NULL;
   }
 
-  typefind->mode = MODE_NORMAL;
+  typefind->mode = MODE_TRANSITION;
 
-  if (push_cached_buffers) {
-    GstBuffer *buffer;
+  if (!push_cached_buffers) {
+    gst_buffer_store_clear (typefind->store);
+  } else {
     guint size = gst_buffer_store_get_size (typefind->store, 0);
 
     GST_DEBUG_OBJECT (typefind, "seeking back to current position %u", size);
@@ -362,18 +365,32 @@
                 size))) {
       GST_WARNING_OBJECT (typefind,
           "could not seek to required position %u, hope for the best", size);
-    }
-    gst_pad_push (typefind->src, GST_DATA (gst_event_new_discontinuous (TRUE,
-                GST_FORMAT_DEFAULT, (guint64) 0, GST_FORMAT_BYTES, (guint64) 0,
-                GST_FORMAT_UNDEFINED)));
-    if (size
-        && (buffer = gst_buffer_store_get_buffer (typefind->store, 0, size))) {
-      GST_DEBUG_OBJECT (typefind, "pushing cached data (%u bytes)", size);
-      gst_pad_push (typefind->src, GST_DATA (buffer));
+      typefind->mode = MODE_NORMAL;
+      gst_buffer_store_clear (typefind->store);
     } else {
-      size = 0;
+      typefind->waiting_for_discont_offset = size;
     }
   }
+}
+
+static void
+push_buffer_store (GstTypeFindElement *typefind)
+{
+  guint size = gst_buffer_store_get_size (typefind->store, 0);
+  GstBuffer *buffer;
+
+  gst_pad_push (typefind->src, GST_DATA (gst_event_new_discontinuous (TRUE,
+              GST_FORMAT_DEFAULT, (guint64) 0, GST_FORMAT_BYTES, (guint64) 0,
+              GST_FORMAT_UNDEFINED)));
+  if (size
+      && (buffer = gst_buffer_store_get_buffer (typefind->store, 0, size))) {
+    GST_DEBUG_OBJECT (typefind, "pushing cached data (%u bytes)", size);
+    gst_pad_push (typefind->src, GST_DATA (buffer));
+  } else {
+    /* FIXME: shouldn't we throw an error here? */
+    size = 0;
+  }
+
   gst_buffer_store_clear (typefind->store);
 }
 
@@ -416,40 +433,64 @@
   TypeFindEntry *entry;
   GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
 
-  if (typefind->mode == MODE_TYPEFIND) {
-    /* need to do more? */
-    switch (GST_EVENT_TYPE (event)) {
-      case GST_EVENT_EOS:
-        /* this should only happen when we got all available data */
-        entry =
-            (TypeFindEntry *) typefind->possibilities ? typefind->
-            possibilities->data : NULL;
-        if (entry && entry->probability >= typefind->min_probability) {
-          GST_INFO_OBJECT (typefind,
-              "'%s' is the best typefind left after we got all data, using it now (probability %u)",
-              GST_PLUGIN_FEATURE_NAME (entry->factory), entry->probability);
-          g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0,
-              entry->probability, entry->caps);
-          stop_typefinding (typefind);
-          gst_pad_event_default (pad, event);
+  switch (typefind->mode) {
+    case MODE_TYPEFIND:
+      switch (GST_EVENT_TYPE (event)) {
+        case GST_EVENT_EOS:
+          /* this should only happen when we got all available data */
+          entry =
+              (TypeFindEntry *) typefind->possibilities ? typefind->
+              possibilities->data : NULL;
+          if (entry && entry->probability >= typefind->min_probability) {
+            GST_INFO_OBJECT (typefind,
+                "'%s' is the best typefind left after we got all data, using it now (probability %u)",
+                GST_PLUGIN_FEATURE_NAME (entry->factory), entry->probability);
+            g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0,
+                entry->probability, entry->caps);
+            stop_typefinding (typefind);
+            gst_pad_event_default (pad, event);
+          } else {
+            gst_pad_event_default (pad, event);
+            GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
+            stop_typefinding (typefind);
+          }
+          break;
+        default:
+          gst_data_unref (GST_DATA (event));
+          break;
+      }
+      break;
+    case MODE_TRANSITION:
+      if (GST_EVENT_TYPE (event) == GST_EVENT_DISCONTINUOUS) {
+        if (GST_EVENT_DISCONT_NEW_MEDIA (event)) {
+          start_typefinding (typefind);
+          gst_event_unref (event);
         } else {
-          gst_pad_event_default (pad, event);
-          GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
-          stop_typefinding (typefind);
+          guint64 off;
+
+          if (gst_event_discont_get_value (event, GST_FORMAT_BYTES, &off) &&
+              off == typefind->waiting_for_discont_offset) {
+            typefind->mode = MODE_NORMAL;
+            push_buffer_store (typefind);
+          } else {
+            gst_event_unref (event);
+          }
         }
-        break;
-      default:
-        gst_data_unref (GST_DATA (event));
-        break;
-    }
-  } else {
-    if (GST_EVENT_TYPE (event) == GST_EVENT_DISCONTINUOUS &&
-        GST_EVENT_DISCONT_NEW_MEDIA (event)) {
-      start_typefinding (typefind);
-      gst_event_unref (event);
-    } else {
-      gst_pad_event_default (pad, event);
-    }
+      } else {
+        gst_event_unref (event);
+      }
+      break;
+    case MODE_NORMAL:
+      if (GST_EVENT_TYPE (event) == GST_EVENT_DISCONTINUOUS &&
+          GST_EVENT_DISCONT_NEW_MEDIA (event)) {
+        start_typefinding (typefind);
+        gst_event_unref (event);
+      } else {
+        gst_pad_event_default (pad, event);
+      }
+      break;
+    default:
+      g_assert_not_reached ();
   }
 }
 static guint8 *
@@ -537,6 +578,9 @@
     case MODE_NORMAL:
       gst_pad_push (typefind->src, data);
       return;
+    case MODE_TRANSITION:
+      gst_data_unref (data);
+      return;
     case MODE_TYPEFIND:{
       guint64 current_offset;
 
Index: gst/elements/gsttypefindelement.h
===================================================================
RCS file: /home/cvs/gstreamer/gstreamer/gst/elements/gsttypefindelement.h,v
retrieving revision 1.6
diff -u -r1.6 gsttypefindelement.h
--- gst/elements/gsttypefindelement.h	29 Apr 2004 00:32:28 -0000	1.6
+++ gst/elements/gsttypefindelement.h	25 Sep 2004 13:49:50 -0000
@@ -53,6 +53,7 @@
   GstCaps *		caps;
 
   guint			mode;
+  guint64		waiting_for_discont_offset;
   GstBufferStore *	store;
   guint64		stream_length;
   gboolean		stream_length_available;
