Index: gst/gstpad.h
===================================================================
RCS file: /cvs/gstreamer/gstreamer/gst/gstpad.h,v
retrieving revision 1.207
diff -u -3 -p -r1.207 gstpad.h
--- gst/gstpad.h	14 May 2006 21:16:58 -0000	1.207
+++ gst/gstpad.h	18 May 2006 20:08:06 -0000
@@ -112,7 +112,8 @@ typedef enum {
   GST_FLOW_UNEXPECTED     = -3,
   GST_FLOW_NOT_NEGOTIATED = -4,
   GST_FLOW_ERROR	  = -5,
-  GST_FLOW_NOT_SUPPORTED  = -6
+  GST_FLOW_NOT_SUPPORTED  = -6,
+  GST_FLOW_LAST = GST_FLOW_NOT_SUPPORTED
 } GstFlowReturn;
 
 /**
Index: libs/gst/base/gstbasesink.c
===================================================================
RCS file: /cvs/gstreamer/gstreamer/libs/gst/base/gstbasesink.c,v
retrieving revision 1.148
diff -u -3 -p -r1.148 gstbasesink.c
--- libs/gst/base/gstbasesink.c	15 May 2006 11:54:22 -0000	1.148
+++ libs/gst/base/gstbasesink.c	18 May 2006 20:08:06 -0000
@@ -688,6 +688,7 @@ gst_base_sink_preroll_queue_flush (GstBa
   basesink->buffers_queued = 0;
   basesink->events_queued = 0;
   basesink->have_preroll = FALSE;
+  basesink->preroll_need_more_data = TRUE;
   /* and signal any waiters now */
   GST_PAD_PREROLL_SIGNAL (pad);
 }
@@ -1570,9 +1571,17 @@ gst_base_sink_preroll_object (GstBaseSin
         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
 
     bclass = GST_BASE_SINK_GET_CLASS (basesink);
-    if (bclass->preroll)
-      if ((ret = bclass->preroll (basesink, buf)) != GST_FLOW_OK)
-        goto preroll_failed;
+    if (bclass->preroll) {
+      if ( G_UNLIKELY( (ret = bclass->preroll (basesink, buf)) != GST_FLOW_OK )  ) {
+	if ( G_LIKELY(ret == GST_BASE_SINK_PREROLL_NEED_MORE_DATA) ) {
+	  goto preroll_need_more_data;
+	} else {
+	  goto preroll_failed;
+	}
+      } else {
+	basesink->preroll_need_more_data = FALSE;
+      }
+    }
   } else {
   }
 
@@ -1586,6 +1595,11 @@ gst_base_sink_preroll_object (GstBaseSin
   return GST_FLOW_OK;
 
   /* ERRORS */
+preroll_need_more_data:
+  {
+    GST_DEBUG_OBJECT (basesink, "preroll need more data");
+    return GST_BASE_SINK_PREROLL_NEED_MORE_DATA;
+  }
 preroll_failed:
   {
     GST_DEBUG_OBJECT (basesink, "preroll failed, abort state");
@@ -1624,10 +1638,14 @@ gst_base_sink_queue_object_unlocked (Gst
     GST_DEBUG_OBJECT (basesink, "now %d prerolled items", length);
 
     /* first prerollable item needs to finish the preroll */
-    if (length == 1) {
+    if ( length && basesink->preroll_need_more_data && ! basesink->eos ) {
       ret = gst_base_sink_preroll_object (basesink, pad, obj);
-      if (G_UNLIKELY (ret != GST_FLOW_OK))
-        goto preroll_failed;
+      if (G_UNLIKELY (ret != GST_FLOW_OK)) {
+	if ( G_LIKELY(ret == GST_BASE_SINK_PREROLL_NEED_MORE_DATA) )
+	  goto preroll_need_more_data;
+	else
+	  goto preroll_failed;
+      }
     }
     /* need to recheck if we need preroll, commmit state during preroll 
      * could have made us not need more preroll. */
@@ -1658,6 +1676,10 @@ gst_base_sink_queue_object_unlocked (Gst
   return ret;
 
   /* special cases */
+preroll_need_more_data:
+  {
+    return GST_FLOW_OK;
+  }
 preroll_failed:
   {
     GST_DEBUG_OBJECT (basesink, "preroll failed, reason %s",
@@ -2462,6 +2484,7 @@ gst_base_sink_change_state (GstElement *
       basesink->have_preroll = FALSE;
       basesink->need_preroll = TRUE;
       basesink->playing_async = TRUE;
+      basesink->preroll_need_more_data = TRUE;
       basesink->priv->current_sstart = 0;
       basesink->priv->current_sstop = 0;
       basesink->priv->eos_rtime = -1;
@@ -2488,6 +2511,7 @@ gst_base_sink_change_state (GstElement *
       } else {
         GST_DEBUG_OBJECT (basesink, "PAUSED to PLAYING, need preroll");
         basesink->need_preroll = TRUE;
+        basesink->preroll_need_more_data = TRUE;
         basesink->playing_async = TRUE;
         ret = GST_STATE_CHANGE_ASYNC;
       }
@@ -2527,6 +2551,7 @@ gst_base_sink_change_state (GstElement *
       } else {
         GST_DEBUG_OBJECT (basesink, "PLAYING to PAUSED, need preroll");
         basesink->playing_async = TRUE;
+        basesink->preroll_need_more_data = TRUE;	
         ret = GST_STATE_CHANGE_ASYNC;
       }
       GST_DEBUG_OBJECT (basesink, "rendered: %" G_GUINT64_FORMAT
Index: libs/gst/base/gstbasesink.h
===================================================================
RCS file: /cvs/gstreamer/gstreamer/libs/gst/base/gstbasesink.h,v
retrieving revision 1.37
diff -u -3 -p -r1.37 gstbasesink.h
--- libs/gst/base/gstbasesink.h	3 May 2006 16:42:08 -0000	1.37
+++ libs/gst/base/gstbasesink.h	18 May 2006 20:08:06 -0000
@@ -48,6 +48,8 @@ typedef struct _GstBaseSink GstBaseSink;
 typedef struct _GstBaseSinkClass GstBaseSinkClass;
 typedef struct _GstBaseSinkPrivate GstBaseSinkPrivate;
 
+#define GST_BASE_SINK_PREROLL_NEED_MORE_DATA (GST_FLOW_LAST-1)
+
 /**
  * GstBaseSink:
  * @element: the parent element.
@@ -77,6 +79,7 @@ struct _GstBaseSink {
   gboolean       need_preroll;
   gboolean       have_preroll;
   gboolean       playing_async;
+  gboolean       preroll_need_more_data;
 
   /*< protected >*/ /* with STREAM_LOCK */
   gboolean	 have_newsegment;
