Index: ext/flac/Makefile.am
===================================================================
RCS file: /cvs/gstreamer/gst-plugins-good/ext/flac/Makefile.am,v
retrieving revision 1.16
diff -u -p -r1.16 Makefile.am
--- ext/flac/Makefile.am	23 May 2006 16:45:22 -0000	1.16
+++ ext/flac/Makefile.am	12 Jun 2006 10:14:53 -0000
@@ -5,8 +5,8 @@ plugin_LTLIBRARIES = libgstflac.la
 
 libgstflac_la_SOURCES = gstflac.c gstflacdec.c gstflacenc.c
 libgstflac_la_CFLAGS = $(GST_CFLAGS) -I$(top_srcdir) $(GST_PLUGINS_BASE_CFLAGS)
-libgstflac_la_LIBADD = $(GST_LIBS) $(FLAC_LIBS) $(GST_PLUGINS_BASE_LIBS) \
-    -lgsttag-@GST_MAJORMINOR@
+libgstflac_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) $(FLAC_LIBS) \
+    $(GST_PLUGINS_BASE_LIBS) -lgsttag-@GST_MAJORMINOR@
 libgstflac_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
 
 noinst_HEADERS = gstflacenc.h gstflacdec.h
Index: ext/flac/gstflacdec.c
===================================================================
RCS file: /cvs/gstreamer/gst-plugins-good/ext/flac/gstflacdec.c,v
retrieving revision 1.77
diff -u -p -r1.77 gstflacdec.c
--- ext/flac/gstflacdec.c	23 May 2006 16:45:22 -0000	1.77
+++ ext/flac/gstflacdec.c	12 Jun 2006 10:14:53 -0000
@@ -76,9 +76,13 @@ static gboolean gst_flac_dec_src_event (
 static gboolean gst_flac_dec_sink_activate (GstPad * sinkpad);
 static gboolean gst_flac_dec_sink_activate_pull (GstPad * sinkpad,
     gboolean active);
+static gboolean gst_flac_dec_sink_activate_push (GstPad * sinkpad,
+    gboolean active);
 static void gst_flac_dec_send_newsegment (GstFlacDec * flacdec,
     gboolean update);
+static GstFlowReturn gst_flac_dec_chain (GstPad * pad, GstBuffer * buffer);
 
+/* Callbacks for pull mode operation (using libflac's SeekableStreamDecoder) */
 static FLAC__SeekableStreamDecoderReadStatus
 gst_flac_dec_read (const FLAC__SeekableStreamDecoder * decoder,
     FLAC__byte buffer[], unsigned *bytes, void *client_data);
@@ -93,14 +97,21 @@ gst_flac_dec_length (const FLAC__Seekabl
     FLAC__uint64 * length, void *client_data);
 static FLAC__bool gst_flac_dec_eof (const FLAC__SeekableStreamDecoder * decoder,
     void *client_data);
+
+/* Callbacks for push-mode operation (libflac's normal StreamDecoder) */
+static FLAC__StreamDecoderReadStatus
+gst_flac_dec_push_read (const FLAC__StreamDecoder *decoder,
+    FLAC__byte buffer[], unsigned *bytes, void *client_data);
+
+/* Callbacks shared between pushmode and pull mode */
 static FLAC__StreamDecoderWriteStatus
-gst_flac_dec_write (const FLAC__SeekableStreamDecoder * decoder,
+gst_flac_dec_write (const void * decoder,
     const FLAC__Frame * frame,
     const FLAC__int32 * const buffer[], void *client_data);
-static void gst_flac_dec_metadata_callback (const FLAC__SeekableStreamDecoder *
-    decoder, const FLAC__StreamMetadata * metadata, void *client_data);
-static void gst_flac_dec_error_callback (const FLAC__SeekableStreamDecoder *
-    decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
+static void gst_flac_dec_metadata_callback (const void *decoder, 
+    const FLAC__StreamMetadata * metadata, void *client_data);
+static void gst_flac_dec_error_callback (const void *decoder, 
+    FLAC__StreamDecoderErrorStatus status, void *client_data);
 
 GST_BOILERPLATE (GstFlacDec, gst_flac_dec, GstElement, GST_TYPE_ELEMENT);
 #define GST_FLAC_DEC_SRC_CAPS                             \
@@ -154,6 +165,10 @@ gst_flac_dec_init (GstFlacDec * flacdec,
       GST_DEBUG_FUNCPTR (gst_flac_dec_sink_activate));
   gst_pad_set_activatepull_function (flacdec->sinkpad,
       GST_DEBUG_FUNCPTR (gst_flac_dec_sink_activate_pull));
+  gst_pad_set_activatepush_function (flacdec->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_flac_dec_sink_activate_push));
+  gst_pad_set_chain_function (flacdec->sinkpad, 
+      GST_DEBUG_FUNCPTR (gst_flac_dec_chain));
   gst_element_add_pad (GST_ELEMENT (flacdec), flacdec->sinkpad);
 
   flacdec->srcpad = gst_pad_new_from_template (src_template, "src");
@@ -166,29 +181,77 @@ gst_flac_dec_init (GstFlacDec * flacdec,
   gst_pad_use_fixed_caps (flacdec->srcpad);
   gst_element_add_pad (GST_ELEMENT (flacdec), flacdec->srcpad);
 
-  flacdec->decoder = FLAC__seekable_stream_decoder_new ();
   flacdec->segment.last_stop = 0;
   flacdec->init = TRUE;
 
-  FLAC__seekable_stream_decoder_set_read_callback (flacdec->decoder,
+  flacdec->pushmode_decoder = NULL;
+  flacdec->seekable_decoder = NULL;
+
+  flacdec->adapter = gst_adapter_new ();
+}
+
+static void create_seekable_decoder (GstFlacDec * flacdec)
+{
+  if (flacdec->seekable_decoder != NULL)
+    return;
+
+  if (flacdec->pushmode_decoder != NULL) {
+    /* Clean up the pushmode_decoder */
+    FLAC__stream_decoder_delete (flacdec->pushmode_decoder);
+    flacdec->pushmode_decoder = NULL;
+  }
+    
+  flacdec->seekable_decoder = FLAC__seekable_stream_decoder_new ();
+
+  FLAC__seekable_stream_decoder_set_read_callback (flacdec->seekable_decoder,
       gst_flac_dec_read);
-  FLAC__seekable_stream_decoder_set_seek_callback (flacdec->decoder,
+  FLAC__seekable_stream_decoder_set_seek_callback (flacdec->seekable_decoder,
       gst_flac_dec_seek);
-  FLAC__seekable_stream_decoder_set_tell_callback (flacdec->decoder,
+  FLAC__seekable_stream_decoder_set_tell_callback (flacdec->seekable_decoder,
       gst_flac_dec_tell);
-  FLAC__seekable_stream_decoder_set_length_callback (flacdec->decoder,
+  FLAC__seekable_stream_decoder_set_length_callback (flacdec->seekable_decoder,
       gst_flac_dec_length);
-  FLAC__seekable_stream_decoder_set_eof_callback (flacdec->decoder,
+  FLAC__seekable_stream_decoder_set_eof_callback (flacdec->seekable_decoder,
       gst_flac_dec_eof);
-  FLAC__seekable_stream_decoder_set_write_callback (flacdec->decoder,
-      gst_flac_dec_write);
-  FLAC__seekable_stream_decoder_set_metadata_respond (flacdec->decoder,
+  FLAC__seekable_stream_decoder_set_write_callback (flacdec->seekable_decoder,
+      (FLAC__SeekableStreamDecoderWriteCallback) gst_flac_dec_write);
+  FLAC__seekable_stream_decoder_set_metadata_respond (flacdec->seekable_decoder,
       FLAC__METADATA_TYPE_VORBIS_COMMENT);
-  FLAC__seekable_stream_decoder_set_metadata_callback (flacdec->decoder,
-      gst_flac_dec_metadata_callback);
-  FLAC__seekable_stream_decoder_set_error_callback (flacdec->decoder,
-      gst_flac_dec_error_callback);
-  FLAC__seekable_stream_decoder_set_client_data (flacdec->decoder, flacdec);
+  FLAC__seekable_stream_decoder_set_metadata_callback (flacdec->seekable_decoder,
+      (FLAC__SeekableStreamDecoderMetadataCallback) gst_flac_dec_metadata_callback);
+  FLAC__seekable_stream_decoder_set_error_callback (flacdec->seekable_decoder,
+      (FLAC__SeekableStreamDecoderErrorCallback) gst_flac_dec_error_callback);
+  FLAC__seekable_stream_decoder_set_client_data (flacdec->seekable_decoder, 
+      flacdec);
+
+  flacdec->init = TRUE;
+}
+
+static void create_pushmode_decoder (GstFlacDec * flacdec)
+{
+  if (flacdec->pushmode_decoder != NULL)
+    return;
+
+  if (flacdec->seekable_decoder != NULL) {
+    FLAC__seekable_stream_decoder_delete (flacdec->seekable_decoder);
+    flacdec->seekable_decoder = NULL;
+  }
+
+  flacdec->pushmode_decoder = FLAC__stream_decoder_new ();
+  FLAC__stream_decoder_set_read_callback (flacdec->pushmode_decoder,
+      gst_flac_dec_push_read);
+  FLAC__stream_decoder_set_write_callback (flacdec->pushmode_decoder,
+      (FLAC__StreamDecoderWriteCallback) gst_flac_dec_write);
+  FLAC__stream_decoder_set_metadata_respond (flacdec->pushmode_decoder,
+      FLAC__METADATA_TYPE_VORBIS_COMMENT);
+  FLAC__stream_decoder_set_metadata_callback (flacdec->pushmode_decoder,
+      (FLAC__StreamDecoderMetadataCallback) gst_flac_dec_metadata_callback);
+  FLAC__stream_decoder_set_error_callback (flacdec->pushmode_decoder,
+      (FLAC__StreamDecoderErrorCallback) gst_flac_dec_error_callback);
+  FLAC__stream_decoder_set_client_data (flacdec->pushmode_decoder, 
+      flacdec);
+
+  flacdec->init = TRUE;
 }
 
 static void
@@ -198,9 +261,12 @@ gst_flac_dec_finalize (GObject * object)
 
   flacdec = GST_FLAC_DEC (object);
 
-  if (flacdec->decoder)
-    FLAC__seekable_stream_decoder_delete (flacdec->decoder);
-  flacdec->decoder = NULL;
+  if (flacdec->seekable_decoder)
+    FLAC__seekable_stream_decoder_delete (flacdec->seekable_decoder);
+  flacdec->seekable_decoder = NULL;
+
+  if (flacdec->adapter)
+    g_object_unref (flacdec->adapter);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -414,8 +480,9 @@ gst_flac_dec_scan_for_last_block (GstFla
   }
 }
 
+/* Used for both the seekable and pushmode decoder callbacks */
 static void
-gst_flac_dec_metadata_callback (const FLAC__SeekableStreamDecoder * decoder,
+gst_flac_dec_metadata_callback (const void * decoder,
     const FLAC__StreamMetadata * metadata, void *client_data)
 {
   GstFlacDec *flacdec;
@@ -435,7 +502,8 @@ gst_flac_dec_metadata_callback (const FL
       GST_DEBUG_OBJECT (flacdec, "blocksize: min=%u, max=%u",
           flacdec->min_blocksize, flacdec->max_blocksize);
 
-      if (samples == 0) {
+      /* Only scan for last block in pull-mode, since it uses pull_range() */
+      if (samples == 0 && flacdec->seekable_decoder) {
         gst_flac_dec_scan_for_last_block (flacdec, &samples);
       }
 
@@ -457,8 +525,9 @@ gst_flac_dec_metadata_callback (const FL
   }
 }
 
+/* Used for both the seekable and pushmode decoder callbacks */
 static void
-gst_flac_dec_error_callback (const FLAC__SeekableStreamDecoder * decoder,
+gst_flac_dec_error_callback (const void * decoder,
     FLAC__StreamDecoderErrorStatus status, void *client_data)
 {
   GstFlacDec *flacdec;
@@ -468,8 +537,8 @@ gst_flac_dec_error_callback (const FLAC_
 
   switch (status) {
     case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
-      error = "lost sync";
-      break;
+      /* Ignore this error and keep processing */
+      return;
     case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
       error = "bad header";
       break;
@@ -593,7 +662,7 @@ gst_flac_dec_read (const FLAC__SeekableS
 }
 
 static FLAC__StreamDecoderWriteStatus
-gst_flac_dec_write (const FLAC__SeekableStreamDecoder * decoder,
+gst_flac_dec_write (const void * decoder,
     const FLAC__Frame * frame,
     const FLAC__int32 * const buffer[], void *client_data)
 {
@@ -749,22 +818,22 @@ gst_flac_dec_loop (GstPad * sinkpad)
 
   if (flacdec->init) {
     GST_DEBUG_OBJECT (flacdec, "initializing decoder");
-    s = FLAC__seekable_stream_decoder_init (flacdec->decoder);
+    s = FLAC__seekable_stream_decoder_init (flacdec->seekable_decoder);
     if (s != FLAC__SEEKABLE_STREAM_DECODER_OK)
       goto analyze_state;
-    /*    FLAC__seekable_stream_decoder_process_metadata (flacdec->decoder); */
+    /*    FLAC__seekable_stream_decoder_process_metadata (flacdec->seekable_decoder); */
     flacdec->init = FALSE;
   }
 
   flacdec->last_flow = GST_FLOW_OK;
 
   GST_LOG_OBJECT (flacdec, "processing single");
-  FLAC__seekable_stream_decoder_process_single (flacdec->decoder);
+  FLAC__seekable_stream_decoder_process_single (flacdec->seekable_decoder);
 
 analyze_state:
 
-  GST_LOG_OBJECT (flacdec, "done processing, checking encoder state");
-  s = FLAC__seekable_stream_decoder_get_state (flacdec->decoder);
+  GST_LOG_OBJECT (flacdec, "done processing, checking decoder state");
+  s = FLAC__seekable_stream_decoder_get_state (flacdec->seekable_decoder);
   switch (s) {
     case FLAC__SEEKABLE_STREAM_DECODER_OK:
     case FLAC__SEEKABLE_STREAM_DECODER_SEEKING:{
@@ -797,7 +866,7 @@ analyze_state:
 
     case FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM:{
       GST_DEBUG_OBJECT (flacdec, "EOS");
-      FLAC__seekable_stream_decoder_reset (flacdec->decoder);
+      FLAC__seekable_stream_decoder_reset (flacdec->seekable_decoder);
 
       if ((flacdec->segment.flags & GST_SEEK_FLAG_SEGMENT) != 0) {
         if (flacdec->segment.duration > 0) {
@@ -1166,7 +1235,7 @@ gst_flac_dec_handle_seek_event (GstFlacD
 
   flacdec->seeking = TRUE;
 
-  seek_ok = FLAC__seekable_stream_decoder_seek_absolute (flacdec->decoder,
+  seek_ok = FLAC__seekable_stream_decoder_seek_absolute (flacdec->seekable_decoder,
       segment.start);
 
   flacdec->seeking = FALSE;
@@ -1242,15 +1311,19 @@ gst_flac_dec_sink_activate (GstPad * sin
   if (gst_pad_check_pull_range (sinkpad))
     return gst_pad_activate_pull (sinkpad, TRUE);
 
-  return FALSE;
+  return gst_pad_activate_push (sinkpad, TRUE);
 }
 
 static gboolean
 gst_flac_dec_sink_activate_pull (GstPad * sinkpad, gboolean active)
 {
   if (active) {
+    GstFlacDec *flacdec = GST_FLAC_DEC (GST_OBJECT_PARENT (sinkpad));
+
+    flacdec->offset = 0;
+    create_seekable_decoder (flacdec);
+
     /* if we have a scheduler we can start the task */
-    GST_FLAC_DEC (GST_OBJECT_PARENT (sinkpad))->offset = 0;
     return gst_pad_start_task (sinkpad, (GstTaskFunction) gst_flac_dec_loop,
         sinkpad);
   } else {
@@ -1258,6 +1331,18 @@ gst_flac_dec_sink_activate_pull (GstPad 
   }
 }
 
+static gboolean
+gst_flac_dec_sink_activate_push (GstPad * sinkpad, gboolean active)
+{
+  if (active) {
+    GstFlacDec *flacdec = GST_FLAC_DEC (GST_OBJECT_PARENT (sinkpad));
+
+    flacdec->offset = 0;
+    create_pushmode_decoder (flacdec);
+  }
+  return TRUE;
+}
+
 static GstStateChangeReturn
 gst_flac_dec_change_state (GstElement * element, GstStateChange transition)
 {
@@ -1274,7 +1359,10 @@ gst_flac_dec_change_state (GstElement * 
       flacdec->width = 0;
       flacdec->sample_rate = 0;
       if (flacdec->init == FALSE) {
-        FLAC__seekable_stream_decoder_reset (flacdec->decoder);
+        if (flacdec->seekable_decoder) 
+          FLAC__seekable_stream_decoder_reset (flacdec->seekable_decoder);
+        else if (flacdec->pushmode_decoder) 
+          FLAC__stream_decoder_reset (flacdec->pushmode_decoder);
       }
       gst_segment_init (&flacdec->segment, GST_FORMAT_DEFAULT);
       break;
@@ -1296,3 +1384,64 @@ gst_flac_dec_change_state (GstElement * 
 
   return ret;
 }
+
+static GstFlowReturn gst_flac_dec_chain (GstPad * pad, GstBuffer * buffer)
+{
+  GstFlacDec *flacdec = GST_FLAC_DEC (gst_pad_get_parent (pad));
+  FLAC__bool dec_success = true;
+  FLAC__StreamDecoderState state;
+
+  if (flacdec->init) {
+    state = FLAC__stream_decoder_init (flacdec->pushmode_decoder);
+    if (state != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA)
+      return GST_FLOW_ERROR;
+    flacdec->init = FALSE;
+  }
+
+  if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) {
+    /* Clear the adapter and the decoder */
+    gst_adapter_clear (flacdec->adapter);
+    FLAC__stream_decoder_flush (flacdec->pushmode_decoder);
+  }
+  
+  gst_adapter_push (flacdec->adapter, buffer);
+  flacdec->last_flow = GST_FLOW_OK;
+
+  while (dec_success && gst_adapter_available (flacdec->adapter) > 0) {
+    dec_success = 
+        FLAC__stream_decoder_process_single (flacdec->pushmode_decoder);
+    if (!dec_success)
+      break;
+
+    state = FLAC__stream_decoder_get_state (flacdec->pushmode_decoder);
+    if (state == FLAC__STREAM_DECODER_ABORTED) {
+      GST_LOG_OBJECT (flacdec, "Breaking for more data with %u",
+          gst_adapter_available (flacdec->adapter));
+      FLAC__stream_decoder_flush (flacdec->pushmode_decoder);
+      break;
+    }
+  }
+
+  return flacdec->last_flow;
+}
+
+static FLAC__StreamDecoderReadStatus
+gst_flac_dec_push_read (const FLAC__StreamDecoder *decoder,
+    FLAC__byte buffer[], unsigned *bytes, void *client_data)
+{
+  GstFlacDec *flacdec = GST_FLAC_DEC (client_data);
+  const guint8 *data;
+  guint32 avail = gst_adapter_available (flacdec->adapter);
+
+  if (avail < *bytes) 
+    *bytes = avail;
+
+  if (avail == 0) 
+    return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
+
+  data = gst_adapter_peek (flacdec->adapter, *bytes);
+  memcpy (buffer, data, *bytes);
+  gst_adapter_flush (flacdec->adapter, *bytes);
+  
+  return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
+}
Index: ext/flac/gstflacdec.h
===================================================================
RCS file: /cvs/gstreamer/gst-plugins-good/ext/flac/gstflacdec.h,v
retrieving revision 1.20
diff -u -p -r1.20 gstflacdec.h
--- ext/flac/gstflacdec.h	6 May 2006 09:01:34 -0000	1.20
+++ ext/flac/gstflacdec.h	12 Jun 2006 10:14:53 -0000
@@ -23,6 +23,7 @@
 
 
 #include <gst/gst.h>
+#include <gst/base/gstadapter.h>
 
 #include <FLAC/all.h>
 
@@ -40,7 +41,8 @@ typedef struct _GstFlacDecClass GstFlacD
 struct _GstFlacDec {
   GstElement     element;
 
-  FLAC__SeekableStreamDecoder *decoder;
+  FLAC__StreamDecoder *pushmode_decoder;
+  FLAC__SeekableStreamDecoder *seekable_decoder;
 
   GstPad        *sinkpad;
   GstPad        *srcpad;
@@ -68,6 +70,9 @@ struct _GstFlacDec {
   /* from the stream info, needed for scanning */
   guint16        min_blocksize;
   guint16        max_blocksize;
+
+  /* Adapter to collect buffers in pushmode */
+  GstAdapter *adapter;
 };
 
 struct _GstFlacDecClass {
