Wavpack ported to 0.9. No support for correction file yet.
authorEdgard Lima <edgard.lima@indt.org.br>
Fri, 25 Nov 2005 19:58:19 +0000 (19:58 +0000)
committerEdgard Lima <edgard.lima@indt.org.br>
Fri, 25 Nov 2005 19:58:19 +0000 (19:58 +0000)
Original commit message from CVS:
Wavpack ported to 0.9. No support for correction file yet.

ChangeLog
PORTED_09
configure.ac
ext/Makefile.am
ext/wavpack/Makefile.am
ext/wavpack/gstwavpackdec.c
ext/wavpack/gstwavpackdec.h
ext/wavpack/gstwavpackparse.c
ext/wavpack/gstwavpackparse.h

index 5277e17..d951973 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2005-11-25  Edgard Lima  <edgard.lima@indt.org.br>
+
+       * configure.ac:
+       * PORTED_09:
+       * ext/Makefile.am:
+       * ext/wavpack/Makefile.am:
+       * ext/wavpack/gstwavpackdec.c:
+       * ext/wavpack/gstwavpackdec.h:
+       * ext/wavpack/gstwavpackparse.c:
+       * ext/wavpack/gstwavpackparse.h:
+       Wavpack ported to 0.9. No support for correction file yet.
+
 2005-11-25  Thomas Vander Stichele  <thomas at apestaart dot org>
 
        * ext/wavpack/Makefile.am:
index 3db4c8e..52de38f 100644 (file)
--- a/PORTED_09
+++ b/PORTED_09
@@ -1,6 +1,7 @@
 When porting a plugin start with 0.8 CVS head, not the old code in this module. There are many bugfixes which have gone into 0.8 which you want to keep.
 
 List of ported plugins (update when you commit a ported plugin):
+wavpack     (alima)
 musepack    (alima)
 ivorbis     (alima)
 gsmdec      (alima)
index dc922ec..ce1fcea 100644 (file)
@@ -418,6 +418,15 @@ GST_CHECK_FEATURE(SDL, [SDL plug-in], sdlvideosink, [
     AM_PATH_SDL(, HAVE_SDL=yes, HAVE_SDL=no)
 ])
 
+dnl *** wavpack ***
+dnl We ship our own version of the library
+translit(dnm, m, l) AM_CONDITIONAL(USE_WAVPACK, true)
+GST_CHECK_FEATURE(WAVPACK, [wavpack plug-in], wavpack, [
+  PKG_CHECK_MODULES(WAVPACK, wavpack >= 4.2, HAVE_WAVPACK=yes, HAVE_WAVPACK=no)
+  AC_SUBST(WAVPACK_CFLAGS)
+  AC_SUBST(WAVPACK_LIBS)
+])
+
 dnl *** ivorbis ***
 dnl AM_PATH_IVORBIS only takes two options
 translit(dnm, m, l) AM_CONDITIONAL(USE_IVORBIS, true)
@@ -518,6 +527,7 @@ ext/Makefile
 ext/directfb/Makefile
 ext/faac/Makefile
 ext/faad/Makefile
+ext/wavpack/Makefile
 ext/ivorbis/Makefile
 ext/gsm/Makefile
 ext/musepack/Makefile
index 651664c..f6fe9c8 100644 (file)
@@ -76,6 +76,12 @@ endif
 HERMES_DIR=
 # endif
 
+if USE_WAVPACK
+WAVPACK_DIR=wavpack
+else
+WAVPACK_DIR=
+endif
+
 if USE_IVORBIS
  IVORBIS_DIR=ivorbis
 else
@@ -231,4 +237,6 @@ DIST_SUBDIRS= \
        musepack \
        sdl \
        directfb \
+       musepack \
+       wavpack \
        ivorbis
index b2ca835..6660a72 100644 (file)
@@ -1,10 +1,10 @@
 
 plugin_LTLIBRARIES = libgstwavpack.la
 
-libgstwavpack_la_SOURCES = gstwavpack.c \
-                                                                                                        gstwavpackcommon.c \
-                                                                                                        gstwavpackparse.c \
-                                                                                                        gstwavpackdec.c
+libgstwavpack_la_SOURCES =     gstwavpack.c \
+                               gstwavpackcommon.c \
+                               gstwavpackparse.c \
+                               gstwavpackdec.c
 
 libgstwavpack_la_CFLAGS = $(GST_CFLAGS) $(WAVPACK_CFLAGS)
 libgstwavpack_la_LIBADD = $(WAVPACK_LIBS)
index d9fa074..de7e87f 100644 (file)
@@ -76,20 +76,20 @@ static void gst_wavpack_dec_class_init (GstWavpackDecClass * klass);
 static void gst_wavpack_dec_base_init (GstWavpackDecClass * klass);
 static void gst_wavpack_dec_init (GstWavpackDec * wavpackdec);
 
-static void gst_wavpack_dec_loop (GstElement * element);
+static GstFlowReturn gst_wavpack_dec_chain (GstPad * pad, GstBuffer * buffer);
 
 static GstElementClass *parent = NULL;
 
 static GstPadLinkReturn
-gst_wavpack_dec_link (GstPad * pad, const GstCaps * caps)
+gst_wavpack_dec_link (GstPad * pad, GstPad * peer)
 {
   GstWavpackDec *wavpackdec = GST_WAVPACK_DEC (gst_pad_get_parent (pad));
-  GstStructure *structure = gst_caps_get_structure (caps, 0);
+  GstStructure *structure = gst_caps_get_structure (GST_PAD_CAPS (peer), 0);
   GstCaps *srccaps;
   gint bits;
 
-  if (!gst_caps_is_fixed (caps))
-    return GST_PAD_LINK_DELAYED;
+  if (!gst_caps_is_fixed (GST_PAD_CAPS (peer)))
+    return GST_PAD_LINK_REFUSED;
 
   gst_structure_get_int (structure, "rate",
       (gint32 *) & wavpackdec->samplerate);
@@ -114,24 +114,22 @@ gst_wavpack_dec_link (GstPad * pad, const GstCaps * caps)
         "endianness", G_TYPE_INT, LITTLE_ENDIAN,
         "buffer-frames", G_TYPE_INT, 0, NULL);
   }
+  gst_pad_set_caps (wavpackdec->srcpad, srccaps);
+  gst_pad_use_fixed_caps (wavpackdec->srcpad);
 
-  gst_pad_set_explicit_caps (wavpackdec->srcpad, srccaps);
-
-  // blocks are usually 0.5 seconds long, assume that's always the case for now
-  wavpackdec->decodebuf =
-      (int32_t *) g_malloc ((wavpackdec->samplerate / 2) *
-      wavpackdec->channels * sizeof (int32_t));
   return GST_PAD_LINK_OK;
 }
 
+#if 0
 static GstPadLinkReturn
-gst_wavpack_dec_wvclink (GstPad * pad, const GstCaps * caps)
+gst_wavpack_dec_wvclink (GstPad * pad, GstPad * peer)
 {
-  if (!gst_caps_is_fixed (caps))
-    return GST_PAD_LINK_DELAYED;
+  if (!gst_caps_is_fixed (GST_PAD_CAPS (peer)))
+    return GST_PAD_LINK_REFUSED;
 
   return GST_PAD_LINK_OK;
 }
+#endif
 
 GType
 gst_wavpack_dec_get_type (void)
@@ -201,10 +199,9 @@ gst_wavpack_dec_class_init (GstWavpackDecClass * klass)
 }
 
 static gboolean
-gst_wavpack_dec_src_query (GstPad * pad, GstQueryType type,
-    GstFormat * format, gint64 * value)
+gst_wavpack_dec_src_query (GstPad * pad, GstQuery * query)
 {
-  return gst_pad_query_default (pad, type, format, value);
+  return gst_pad_query_default (pad, query);
 }
 
 static void
@@ -215,27 +212,31 @@ gst_wavpack_dec_init (GstWavpackDec * wavpackdec)
   wavpackdec->sinkpad =
       gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
           "sink"), "sink");
+  gst_element_add_pad (GST_ELEMENT (wavpackdec), wavpackdec->sinkpad);
+
+  gst_pad_set_chain_function (wavpackdec->sinkpad, gst_wavpack_dec_chain);
   gst_pad_set_link_function (wavpackdec->sinkpad, gst_wavpack_dec_link);
 
+#if 0
   wavpackdec->wvcsinkpad =
       gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
           "wvcsink"), "wvcsink");
   gst_pad_set_link_function (wavpackdec->wvcsinkpad, gst_wavpack_dec_wvclink);
+  gst_element_add_pad (GST_ELEMENT (wavpackdec), wavpackdec->wvcsinkpad);
+#endif
+
 
   wavpackdec->srcpad =
       gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
           "src"), "src");
-  gst_pad_use_explicit_caps (wavpackdec->srcpad);
+  gst_pad_use_fixed_caps (wavpackdec->srcpad);
 
   gst_pad_set_query_function (wavpackdec->srcpad, gst_wavpack_dec_src_query);
 
-  gst_element_add_pad (GST_ELEMENT (wavpackdec), wavpackdec->sinkpad);
   gst_element_add_pad (GST_ELEMENT (wavpackdec), wavpackdec->srcpad);
-  gst_element_add_pad (GST_ELEMENT (wavpackdec), wavpackdec->wvcsinkpad);
-  gst_element_set_loop_function (GST_ELEMENT (wavpackdec),
-      gst_wavpack_dec_loop);
 
   wavpackdec->decodebuf = NULL;
+  wavpackdec->decodebuf_size = 0;
   wavpackdec->stream = (WavpackStream *) g_malloc0 (sizeof (WavpackStream));
   wavpackdec->context = (WavpackContext *) g_malloc0 (sizeof (WavpackContext));
 }
@@ -246,6 +247,7 @@ gst_wavpack_dec_setup_context (GstWavpackDec * wavpackdec, guchar * data,
 {
   WavpackContext *context = wavpackdec->context;
   WavpackStream *stream = wavpackdec->stream;
+  guint buffer_size;
 
   memset (context, 0, sizeof (context));
 
@@ -267,6 +269,14 @@ gst_wavpack_dec_setup_context (GstWavpackDec * wavpackdec, guchar * data,
     context->wvc_flag = FALSE;
   }
 
+  buffer_size =
+      stream->wphdr.block_samples * wavpackdec->channels * sizeof (int32_t);
+  if (wavpackdec->decodebuf_size < buffer_size) {
+    wavpackdec->decodebuf =
+        (int32_t *) g_realloc (wavpackdec->decodebuf, buffer_size);
+    wavpackdec->decodebuf_size = buffer_size;
+  }
+
   unpack_init (context);
 }
 
@@ -317,71 +327,25 @@ gst_wavpack_dec_format_samples (GstWavpackDec * wavpackdec, int32_t * samples,
   return buf;
 }
 
-
-static void
-gst_wavpack_dec_loop (GstElement * element)
+static GstFlowReturn
+gst_wavpack_dec_chain (GstPad * pad, GstBuffer * buf)
 {
-  GstWavpackDec *wavpackdec = GST_WAVPACK_DEC (element);
-  GstData *data, *cdata = NULL;
-  GstBuffer *buf, *outbuf, *cbuf = NULL;
-
-  gboolean got_event = FALSE;
-
-  if (!gst_pad_is_linked (wavpackdec->sinkpad)) {
-    return;
-  }
 
-  /*
-     if (!gst_pad_is_linked (wavpackdec->wvcsinkpad)) {
-     return;
-     }
-   */
-
-  data = gst_pad_pull (wavpackdec->sinkpad);
-
-  if (GST_IS_EVENT (data)) {
-    GstEvent *event = GST_EVENT (data);
-
-    switch (GST_EVENT_TYPE (event)) {
-      case GST_EVENT_EOS:
-        gst_event_unref (event);
-        gst_pad_push (wavpackdec->srcpad,
-            GST_DATA (gst_event_new (GST_EVENT_EOS)));
-        gst_element_set_eos (element);
-        break;
-      default:
-        gst_pad_event_default (wavpackdec->srcpad, event);
-        break;
-    }
-    got_event = TRUE;
-  }
+  GstWavpackDec *wavpackdec = GST_WAVPACK_DEC (gst_pad_get_parent (pad));
+  GstBuffer *outbuf, *cbuf = NULL;
+  GstFlowReturn ret = GST_FLOW_OK;
 
+#if 0
   if (gst_pad_is_linked (wavpackdec->wvcsinkpad)) {
-    cdata = gst_pad_pull (wavpackdec->wvcsinkpad);
-    if (GST_IS_EVENT (cdata)) {
-      GstEvent *event = GST_EVENT (cdata);
-
-      switch (GST_EVENT_TYPE (event)) {
-        case GST_EVENT_EOS:
-          gst_event_unref (event);
-          gst_pad_push (wavpackdec->srcpad,
-              GST_DATA (gst_event_new (GST_EVENT_EOS)));
-          gst_element_set_eos (element);
-          break;
-        default:
-          gst_pad_event_default (wavpackdec->srcpad, event);
-          break;
-      }
-      got_event = TRUE;
+    if (GST_FLOW_OK != gst_pad_pull_range (wavpackdec->wvcsinkpad,
+            wavpackdec->wvcflushed_bytes, -1, &cbuf)) {
+      cbuf = NULL;
     } else {
-      cbuf = GST_BUFFER (cdata);
+      wavpackdec->wvcflushed_bytes += GST_BUFFER_SIZE (cbuf);
     }
-  }
-
-  if (got_event)
-    return;
 
-  buf = GST_BUFFER (data);
+  }
+#endif
 
   gst_wavpack_dec_setup_context (wavpackdec, GST_BUFFER_DATA (buf),
       cbuf ? GST_BUFFER_DATA (cbuf) : NULL);
@@ -393,9 +357,19 @@ gst_wavpack_dec_loop (GstElement * element)
 
   GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf);
   GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buf);
+
   gst_buffer_unref (buf);
+  if (cbuf) {
+    gst_buffer_unref (cbuf);
+  }
+
+  gst_buffer_set_caps (outbuf, GST_PAD_CAPS (wavpackdec->srcpad));
+  if (GST_FLOW_OK != (ret = gst_pad_push (wavpackdec->srcpad, outbuf))) {
+    gst_buffer_unref (outbuf);
+  }
+
+  return ret;
 
-  gst_pad_push (wavpackdec->srcpad, GST_DATA (outbuf));
 }
 
 gboolean
index 32fc48d..1f4a383 100644 (file)
@@ -48,11 +48,14 @@ struct _GstWavpackDec
   GstElement element;
 
   GstPad *sinkpad, *srcpad;
+#if 0
   GstPad *wvcsinkpad;
+#endif
 
   WavpackContext *context;
 
   int32_t *decodebuf;
+  guint decodebuf_size;
 
   WavpackStream *stream;
 
@@ -61,6 +64,10 @@ struct _GstWavpackDec
   guint width;
   long frame_length;
 
+  guint64 wvcflushed_bytes;
+  guint64 duration;
+  guint64 wvcduration;
+
   guchar *decdata;
   long *cache;
 };
index 31468e2..4ba0bf5 100644 (file)
@@ -69,10 +69,15 @@ static void gst_wavpack_parse_class_init (GstWavpackParseClass * klass);
 static void gst_wavpack_parse_base_init (GstWavpackParseClass * klass);
 static void gst_wavpack_parse_init (GstWavpackParse * wavpackparse);
 
-static void gst_wavpack_parse_handle_event (GstElement * element);
+static gboolean gst_wavepack_parse_sink_activate (GstPad * sinkpad);
+static gboolean
+gst_wavepack_parse_sink_activate_pull (GstPad * sinkpad, gboolean active);
+
+static gboolean gst_wavpack_parse_sink_event (GstPad * pad, GstEvent * event);
+
 static void gst_wavpack_parse_loop (GstElement * element);
-static GstElementStateReturn gst_wavpack_parse_change_state (GstElement *
-    element);
+static GstStateChangeReturn gst_wavpack_parse_change_state (GstElement *
+    element, GstStateChange transition);
 
 static GstElementClass *parent = NULL;
 
@@ -141,61 +146,97 @@ gst_wavpack_parse_class_init (GstWavpackParseClass * klass)
 }
 
 static gboolean
-gst_wavpack_parse_src_query (GstPad * pad, GstQueryType type,
-    GstFormat * format, gint64 * value)
+gst_wavpack_parse_src_query (GstPad * pad, GstQuery * query)
 {
   GstWavpackParse *wavpackparse = GST_WAVPACK_PARSE (gst_pad_get_parent (pad));
-
-  if ((type == GST_QUERY_TOTAL) && (*format == GST_FORMAT_TIME)) {
-    if (wavpackparse->total_samples == 0) {
-      *value = 0;
-      return FALSE;
-    }
-    *value =
-        ((gdouble) wavpackparse->total_samples /
-        (gdouble) wavpackparse->samplerate) * GST_SECOND;
-    return TRUE;
-  } else if ((type == GST_QUERY_POSITION) && (*format == GST_FORMAT_TIME)) {
-    *value = wavpackparse->timestamp;
-    return TRUE;
-  } else {
-    return gst_pad_query_default (pad, type, format, value);
+  GstFormat format = GST_FORMAT_DEFAULT;
+  gint64 value;
+  gboolean ret = FALSE;
+
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_POSITION:
+      gst_query_parse_position (query, &format, &value);
+      if (format == GST_FORMAT_TIME) {
+        value = wavpackparse->timestamp;
+        gst_query_set_duration (query, format, value);
+        g_object_unref (wavpackparse);
+        ret = TRUE;
+        break;
+      }
+      break;
+    case GST_QUERY_DURATION:
+      gst_query_parse_duration (query, &format, &value);
+
+      if (format == GST_FORMAT_TIME) {
+        if (wavpackparse->total_samples == 0) {
+          value = 0;
+          gst_query_set_duration (query, format, value);
+          g_object_unref (wavpackparse);
+          ret = FALSE;
+          break;
+        }
+        value = ((gdouble) wavpackparse->total_samples /
+            (gdouble) wavpackparse->samplerate) * GST_SECOND;
+        gst_query_set_duration (query, format, value);
+        g_object_unref (wavpackparse);
+        ret = TRUE;
+        break;
+      }
+      break;
+    default:
+      g_object_unref (wavpackparse);
+      ret = gst_pad_query_default (pad, query);
+      break;
   }
-  return FALSE;
+
+  return ret;
+
 }
 
 static gboolean
 gst_wavpack_parse_src_event (GstPad * pad, GstEvent * event)
 {
   GstWavpackParse *wavpackparse;
-  GstSeekType method;
+  GstSeekType type;
   GstFormat format;
   gboolean need_flush;
   gint64 offset, dest;
+  GstSeekFlags flags;
+  gboolean ret = TRUE;
 
   wavpackparse = GST_WAVPACK_PARSE (gst_pad_get_parent (pad));
 
   if (GST_EVENT_TYPE (event) != GST_EVENT_SEEK) {
-    return gst_pad_send_event (GST_PAD_PEER (wavpackparse->sinkpad), event);
+    GstPad *peer;
+
+    if (!(peer = gst_pad_get_peer (wavpackparse->sinkpad))) {
+      ret = FALSE;
+      goto done;
+    }
+    ret = gst_pad_send_event (peer, event);
+    gst_object_unref (peer);
+    goto done;
   }
 
-  format = GST_EVENT_SEEK_FORMAT (event);
-  offset = GST_EVENT_SEEK_OFFSET (event);
-  method = GST_EVENT_SEEK_METHOD (event);
-  need_flush = GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH;
+  gst_event_parse_seek (event, NULL, &format, &flags, &type, &offset, NULL,
+      NULL);
+
+  need_flush = flags & GST_SEEK_FLAG_FLUSH;
 
-  gst_data_unref (GST_DATA (event));
-  event = NULL;
 
-  if (offset < 0 || method != GST_SEEK_METHOD_SET)
-    return FALSE;
+
+  if (offset < 0 || type != GST_SEEK_TYPE_SET) {
+    ret = FALSE;
+    goto done;
+  }
 
   if (format == GST_FORMAT_TIME) {
     dest = offset * wavpackparse->samplerate / GST_SECOND;
   } else if (format == GST_FORMAT_DEFAULT) {
     dest = offset;
   } else {
-    return FALSE;
+    ret = FALSE;
+    goto done;
   }
 
   wavpackparse->need_discont = TRUE;
@@ -204,50 +245,65 @@ gst_wavpack_parse_src_event (GstPad * pad, GstEvent * event)
   wavpackparse->seek_pending = TRUE;
   wavpackparse->seek_offset = dest;
 
-  return TRUE;
+done:
+  gst_event_unref (event);
+  gst_object_unref (wavpackparse);
+  return ret;
 }
 
 #define BUFSIZE 4096
 
 static guint64
-find_header (GstByteStream * bs, guint64 filepos, WavpackHeader * wphdr)
+find_header (GstWavpackParse * wavpackparse, guint64 filepos,
+    WavpackHeader * wphdr)
 {
   guint64 pos = filepos;
+  gint read = 0;
+  GstBuffer *buf = NULL;
 
-  gst_bytestream_seek (bs, filepos, GST_SEEK_METHOD_SET);
+  while (TRUE) {
+    guint8 *cur;
 
-  while (1) {
-    guint8 *data, *cur;
-    gint read;
-
-    read = gst_bytestream_peek_bytes (bs, &data, BUFSIZE);
-    while (read != BUFSIZE) {
-      guint remaining;
-      GstEvent *event = NULL;
-
-      gst_bytestream_get_status (bs, &remaining, &event);
-      if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
-        gst_event_unref (event);
-        return gst_bytestream_length (bs);
-      }
-      gst_event_unref (event);
-      read = gst_bytestream_peek_bytes (bs, &data, BUFSIZE);
-      continue;
+    if (GST_FLOW_OK != gst_pad_pull_range (wavpackparse->sinkpad,
+            wavpackparse->flushed_bytes + filepos, BUFSIZE, &buf)) {
+      wavpackparse->eos = TRUE;
+      gst_pad_push_event (wavpackparse->srcpad, gst_event_new_eos ());
+      return 0;
+    }
+    read = GST_BUFFER_SIZE (buf);
+
+    if (read == 0) {
+      wavpackparse->eos = TRUE;
+      gst_pad_push_event (wavpackparse->srcpad, gst_event_new_eos ());
+      gst_buffer_unref (buf);
+      return 0;
     }
-    cur = data;
+
+    cur = GST_BUFFER_DATA (buf);
     do {
       if (cur[0] == 'w' && cur[1] == 'v' && cur[2] == 'p' && cur[3] == 'k') {
         gst_wavpack_read_header (wphdr, cur);
-        return pos + (cur - data);
+        pos += (cur - GST_BUFFER_DATA (buf));
+        gst_buffer_unref (buf);
+        buf = NULL;
+        return pos;
       }
       cur++;
-    } while ((cur - data) < (BUFSIZE - sizeof (WavpackHeader)));
-    gst_bytestream_flush_fast (bs, BUFSIZE - sizeof (WavpackHeader));
+    } while ((cur - GST_BUFFER_DATA (buf)) <
+        (BUFSIZE - sizeof (WavpackHeader)));
+
+    wavpackparse->flushed_bytes += BUFSIZE - sizeof (WavpackHeader);
+
     pos += BUFSIZE - sizeof (WavpackHeader);
   }
 
   /* never reached */
-  return gst_bytestream_length (bs);
+
+  if (buf) {
+    gst_buffer_unref (buf);
+    buf = NULL;
+  }
+  return wavpackparse->duration - wavpackparse->flushed_bytes;
 }
 
 /* find the position of sample in the input bytestream, adapted from the
@@ -256,13 +312,14 @@ static guint64
 find_sample (GstWavpackParse * wavpackparse, guint32 sample)
 {
   WavpackHeader wphdr;
-  guint64 file_pos1 = 0, file_pos2 = gst_bytestream_length (wavpackparse->bs);
+  guint64 file_pos1 = 0;
+  guint64 file_pos2 = wavpackparse->duration - wavpackparse->flushed_bytes;
   guint64 sample_pos1 = 0, sample_pos2 = wavpackparse->total_samples;
   double ratio = 0.96;
   int file_skip = 0;
 
   if (sample >= wavpackparse->total_samples) {
-    return gst_bytestream_length (wavpackparse->bs);
+    return wavpackparse->duration - wavpackparse->flushed_bytes;
   }
 
   while (1) {
@@ -273,15 +330,15 @@ find_sample (GstWavpackParse * wavpackparse, guint32 sample)
     bytes_per_sample /= sample_pos2 - sample_pos1;
     seek_pos = file_pos1 + (file_skip ? 32 : 0);
     seek_pos += (guint64) (bytes_per_sample * (sample - sample_pos1) * ratio);
-    seek_pos = find_header (wavpackparse->bs, seek_pos, &wphdr);
+    seek_pos = find_header (wavpackparse, seek_pos, &wphdr);
 
-    if (seek_pos == gst_bytestream_length (wavpackparse->bs)
+    if (seek_pos == wavpackparse->duration - wavpackparse->flushed_bytes
         || seek_pos >= file_pos2) {
       if (ratio > 0.0) {
         if ((ratio -= 0.24) < 0.0)
           ratio = 0.0;
       } else {
-        return gst_bytestream_length (wavpackparse->bs);
+        return wavpackparse->duration - wavpackparse->flushed_bytes;
       }
     } else if (wphdr.block_index > sample) {
       sample_pos2 = wphdr.block_index;
@@ -303,16 +360,13 @@ find_sample (GstWavpackParse * wavpackparse, guint32 sample)
 static void
 gst_wavpack_parse_seek (GstWavpackParse * wavpackparse)
 {
-  guint8 *data;
+  GstBuffer *buf;
   gint num;
-  guint remaining;
   WavpackHeader *header = g_malloc (sizeof (WavpackHeader));
 
   guint64 offset = find_sample (wavpackparse, wavpackparse->seek_offset);
 
-  gst_bytestream_seek (wavpackparse->bs, offset, GST_SEEK_METHOD_SET);
-
-  if (offset == gst_bytestream_length (wavpackparse->bs)) {
+  if (offset >= wavpackparse->duration - wavpackparse->flushed_bytes) {
     /* seek failed or went beyond the end, go EOS */
     wavpackparse->timestamp =
         ((gdouble) wavpackparse->total_samples /
@@ -320,29 +374,26 @@ gst_wavpack_parse_seek (GstWavpackParse * wavpackparse)
     return;
   }
 
-  num =
-      gst_bytestream_peek_bytes (wavpackparse->bs, &data,
-      sizeof (WavpackHeader));
-  while (num != sizeof (WavpackHeader)) {
-    GstEvent *event = NULL;
+  if (GST_FLOW_OK != gst_pad_pull_range (wavpackparse->sinkpad,
+          wavpackparse->flushed_bytes + offset, sizeof (WavpackHeader), &buf)) {
+    wavpackparse->eos = TRUE;
+    gst_pad_push_event (wavpackparse->srcpad, gst_event_new_eos ());
+    return;
+  }
+  num = GST_BUFFER_SIZE (buf);
 
-    gst_bytestream_get_status (wavpackparse->bs, &remaining, &event);
-    if (!event) {
-      return;
-    }
-    gst_event_unref (event);
-    num =
-        gst_bytestream_peek_bytes (wavpackparse->bs, &data,
-        sizeof (WavpackHeader));
-    continue;
+  if (num != sizeof (WavpackHeader)) {
+    wavpackparse->eos = TRUE;
+    gst_pad_push_event (wavpackparse->srcpad, gst_event_new_eos ());
+    return;
   }
-  gst_wavpack_read_header (header, data);
 
-  if (wavpackparse->need_flush) {
-    GstEvent *flush = gst_event_new (GST_EVENT_FLUSH);
+  gst_wavpack_read_header (header, GST_BUFFER_DATA (buf));
+  gst_buffer_unref (buf);
 
-    gst_pad_push (wavpackparse->srcpad, GST_DATA (flush));
+  if (wavpackparse->need_flush) {
     wavpackparse->need_flush = FALSE;
+    gst_pad_push_event (wavpackparse->srcpad, gst_event_new_flush_start ());
   }
 
   wavpackparse->need_discont = TRUE;
@@ -356,53 +407,62 @@ gst_wavpack_parse_init (GstWavpackParse * wavpackparse)
 {
   GstElementClass *klass = GST_ELEMENT_GET_CLASS (wavpackparse);
 
+  wavpackparse->duration = -1;
+  wavpackparse->flushed_bytes = -1;
+  wavpackparse->eos = FALSE;
+
   wavpackparse->sinkpad =
       gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
           "sink"), "sink");
 
+  gst_pad_set_event_function (wavpackparse->sinkpad,
+      gst_wavpack_parse_sink_event);
+
   gst_element_add_pad (GST_ELEMENT (wavpackparse), wavpackparse->sinkpad);
-  gst_element_set_loop_function (GST_ELEMENT (wavpackparse),
-      gst_wavpack_parse_loop);
 
-  GST_FLAG_SET (wavpackparse, GST_ELEMENT_EVENT_AWARE);
+  gst_pad_set_activate_function (wavpackparse->sinkpad,
+      gst_wavepack_parse_sink_activate);
+
+  gst_pad_set_activatepull_function (wavpackparse->sinkpad,
+      gst_wavepack_parse_sink_activate_pull);
+
+  wavpackparse->srcpad = NULL;
+
 }
 
-static void
-gst_wavpack_parse_handle_event (GstElement * element)
+static gboolean
+gst_wavpack_parse_sink_event (GstPad * pad, GstEvent * event)
 {
-  GstWavpackParse *wavpackparse = GST_WAVPACK_PARSE (element);
-  GstEvent *event = NULL;
-  guint remaining;
-
-  gst_bytestream_get_status (wavpackparse->bs, &remaining, &event);
-  if (event) {
-    if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
-      if (GST_IS_PAD (wavpackparse->srcpad)
-          && gst_pad_is_active (wavpackparse->srcpad))
-        gst_pad_push (wavpackparse->srcpad, GST_DATA (event));
-      gst_element_set_eos (element);
-    } else if (GST_EVENT_TYPE (event) == GST_EVENT_DISCONTINUOUS) {
-      if (GST_IS_PAD (wavpackparse->srcpad)
-          && gst_pad_is_active (wavpackparse->srcpad))
-        gst_pad_event_default (wavpackparse->srcpad, event);
-    } else {
-      gst_event_unref (event);
-    }
-  } else {
-    GST_ELEMENT_ERROR (element, STREAM, DEMUX, ("couldn't read wavpack header"),
-        (NULL));
+  GstWavpackParse *wavpackparse = GST_WAVPACK_PARSE (gst_pad_get_parent (pad));
+  gboolean res = TRUE;
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_EOS:
+      wavpackparse->eos = TRUE;
+      /* fall through */
+    default:
+      res = gst_pad_event_default (pad, event);
+      gst_object_unref (wavpackparse);
+      return res;
+      break;
   }
+
 }
 
 static void
 gst_wavpack_parse_loop (GstElement * element)
 {
   GstWavpackParse *wavpackparse = GST_WAVPACK_PARSE (element);
-  guint8 *data;
   gint num;
   GstBuffer *buf;
   WavpackHeader *header = g_malloc (sizeof (WavpackHeader));
 
+  GST_PAD_STREAM_LOCK (wavpackparse->sinkpad);
+
+  if (wavpackparse->eos) {
+    goto done;
+  }
+
   if (wavpackparse->seek_pending) {
     gst_wavpack_parse_seek (wavpackparse);
     wavpackparse->need_discont = TRUE;
@@ -410,45 +470,68 @@ gst_wavpack_parse_loop (GstElement * element)
   }
 
   if (wavpackparse->need_discont) {
-    if (GST_IS_PAD (wavpackparse->srcpad)
-        && gst_pad_is_active (wavpackparse->srcpad))
-      gst_pad_push (wavpackparse->srcpad,
-          GST_DATA (gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME,
-                  wavpackparse->timestamp, GST_FORMAT_UNDEFINED)));
-    wavpackparse->need_discont = FALSE;
+    if (GST_IS_PAD (wavpackparse->srcpad)) {
+      gst_pad_push_event (wavpackparse->srcpad,
+          gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
+              wavpackparse->timestamp, GST_CLOCK_TIME_NONE, 0));
+
+      wavpackparse->need_discont = FALSE;
+    }
+  }
+
+  if (GST_FLOW_OK != gst_pad_pull_range (wavpackparse->sinkpad,
+          wavpackparse->flushed_bytes, sizeof (WavpackHeader), &buf)) {
+    wavpackparse->eos = TRUE;
+    gst_pad_push_event (wavpackparse->srcpad, gst_event_new_eos ());
+    goto done;
   }
+  num = GST_BUFFER_SIZE (buf);
 
-  num =
-      gst_bytestream_peek_bytes (wavpackparse->bs, &data,
-      sizeof (WavpackHeader));
   if (num != sizeof (WavpackHeader)) {
-    gst_wavpack_parse_handle_event (element);
-    return;
+    gst_buffer_unref (buf);
+    wavpackparse->eos = TRUE;
+    gst_pad_push_event (wavpackparse->srcpad, gst_event_new_eos ());
+    goto done;
   }
-  gst_wavpack_read_header (header, data);
 
-  num = gst_bytestream_peek_bytes (wavpackparse->bs, &data, header->ckSize + 8);
+  gst_wavpack_read_header (header, GST_BUFFER_DATA (buf));
+  gst_buffer_unref (buf);
+
+  if (GST_FLOW_OK != gst_pad_pull_range (wavpackparse->sinkpad,
+          wavpackparse->flushed_bytes, header->ckSize + 8, &buf)) {
+    wavpackparse->eos = TRUE;
+    gst_pad_push_event (wavpackparse->srcpad, gst_event_new_eos ());
+    goto done;
+  }
+  num = GST_BUFFER_SIZE (buf);
+
   if (num != header->ckSize + 8) {
-    gst_wavpack_parse_handle_event (element);
-    return;
+    gst_buffer_unref (buf);
+    wavpackparse->eos = TRUE;
+    gst_pad_push_event (wavpackparse->srcpad, gst_event_new_eos ());
+    goto done;
   }
 
   if (!GST_IS_PAD (wavpackparse->srcpad)) {
-    guchar *bufptr = data + sizeof (WavpackHeader);
+
+    guchar *bufptr = GST_BUFFER_DATA (buf) + sizeof (WavpackHeader);
     GstCaps *caps = NULL;
     WavpackMetadata meta;
 
-    while (read_metadata_buff (&meta, data, &bufptr)) {
+    while (read_metadata_buff (&meta, GST_BUFFER_DATA (buf), &bufptr)) {
       if (meta.id == ID_WVC_BITSTREAM) {
         caps = gst_caps_new_simple ("audio/x-wavpack-correction",
             "framed", G_TYPE_BOOLEAN, TRUE, NULL);
+        if (GST_IS_PAD (wavpackparse->srcpad)) {
+          gst_object_unref (wavpackparse->srcpad);
+        }
         wavpackparse->srcpad =
             gst_pad_new_from_template (gst_element_class_get_pad_template
             (GST_ELEMENT_GET_CLASS (wavpackparse), "wvcsrc"), "wvcsrc");
       } else if (meta.id == ID_RIFF_HEADER) {
         WaveHeader *wheader = g_malloc (sizeof (WaveHeader));
 
-        // skip RiffChunkHeader and ChunkHeader
+        /* skip RiffChunkHeader and ChunkHeader */
         g_memmove (wheader, meta.data + 20, sizeof (WaveHeader));
         little_endian_to_native (wheader, WaveHeaderFormat);
         wavpackparse->samplerate = wheader->SampleRate;
@@ -459,24 +542,44 @@ gst_wavpack_parse_loop (GstElement * element)
             "channels", G_TYPE_INT, wavpackparse->channels,
             "rate", G_TYPE_INT, wavpackparse->samplerate,
             "framed", G_TYPE_BOOLEAN, TRUE, NULL);
+        if (GST_IS_PAD (wavpackparse->srcpad)) {
+          gst_object_unref (wavpackparse->srcpad);
+        }
         wavpackparse->srcpad =
             gst_pad_new_from_template (gst_element_class_get_pad_template
             (GST_ELEMENT_GET_CLASS (wavpackparse), "src"), "src");
       }
     }
-    gst_pad_use_explicit_caps (wavpackparse->srcpad);
+
+    if (!(caps && GST_IS_PAD (wavpackparse->srcpad))) {
+      gst_buffer_unref (buf);
+      goto done;
+    }
+
     gst_pad_set_query_function (wavpackparse->srcpad,
         gst_wavpack_parse_src_query);
     gst_pad_set_event_function (wavpackparse->srcpad,
         gst_wavpack_parse_src_event);
+
+    gst_pad_set_caps (wavpackparse->srcpad, caps);
+    gst_pad_use_fixed_caps (wavpackparse->srcpad);
+
     gst_element_add_pad (GST_ELEMENT (wavpackparse), wavpackparse->srcpad);
 
-    gst_pad_set_explicit_caps (wavpackparse->srcpad, caps);
   }
 
-  buf = gst_buffer_new_and_alloc (header->ckSize + 8);
-  memcpy (GST_BUFFER_DATA (buf), data, header->ckSize + 8);
-  gst_bytestream_flush_fast (wavpackparse->bs, header->ckSize + 8);
+  if (wavpackparse->need_discont) {
+    if (GST_IS_PAD (wavpackparse->srcpad)) {
+      gst_pad_push_event (wavpackparse->srcpad,
+          gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
+              wavpackparse->timestamp, GST_CLOCK_TIME_NONE, 0));
+
+      wavpackparse->need_discont = FALSE;
+    }
+  }
+
+  wavpackparse->flushed_bytes += header->ckSize + 8;
+
   wavpackparse->timestamp =
       ((gdouble) header->block_index / (gdouble) wavpackparse->samplerate) *
       GST_SECOND;
@@ -484,38 +587,107 @@ gst_wavpack_parse_loop (GstElement * element)
   GST_BUFFER_DURATION (buf) =
       ((gdouble) header->block_samples / (gdouble) wavpackparse->samplerate) *
       GST_SECOND;
-  gst_pad_push (wavpackparse->srcpad, GST_DATA (buf));
+  gst_buffer_set_caps (buf, GST_PAD_CAPS (wavpackparse->srcpad));
+
+  if (GST_FLOW_OK != gst_pad_push (wavpackparse->srcpad, buf)) {
+    gst_buffer_unref (buf);
+  }
+
+done:
+  GST_PAD_STREAM_UNLOCK (wavpackparse->sinkpad);
+  return;
+
 }
 
-static GstElementStateReturn
-gst_wavpack_parse_change_state (GstElement * element)
+static GstStateChangeReturn
+gst_wavpack_parse_change_state (GstElement * element, GstStateChange transition)
 {
   GstWavpackParse *wavpackparse = GST_WAVPACK_PARSE (element);
+  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
 
-  switch (GST_STATE_TRANSITION (element)) {
-    case GST_STATE_READY_TO_PAUSED:
+  switch (transition) {
+    case GST_STATE_CHANGE_READY_TO_PAUSED:
+      wavpackparse->flushed_bytes = 0;
       wavpackparse->need_discont = TRUE;
-      wavpackparse->bs = gst_bytestream_new (wavpackparse->sinkpad);
+      wavpackparse->eos = FALSE;
       break;
-    case GST_STATE_PAUSED_TO_READY:
-      gst_bytestream_destroy (wavpackparse->bs);
-      wavpackparse->seek_pending = FALSE;
+    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+    {
+      GstQuery *query;
+      GstFormat format = GST_FORMAT_BYTES;
+
+      query = gst_query_new_duration (GST_FORMAT_BYTES);
+      if (gst_pad_query (GST_PAD_PEER (wavpackparse->sinkpad), query)) {
+
+        gst_query_parse_duration (query, &format,
+            (gint64 *) & wavpackparse->duration);
+
+        if (format != GST_FORMAT_BYTES) {
+          wavpackparse->duration = -1;
+          ret = GST_STATE_CHANGE_FAILURE;
+        }
+
+      } else {
+        wavpackparse->duration = -1;
+        ret = GST_STATE_CHANGE_FAILURE;
+      }
+      gst_query_unref (query);
+    }
       break;
     default:
       break;
   }
 
   if (GST_ELEMENT_CLASS (parent)->change_state)
-    return GST_ELEMENT_CLASS (parent)->change_state (element);
+    ret = GST_ELEMENT_CLASS (parent)->change_state (element, transition);
+
+  switch (transition) {
+    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+      break;
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      wavpackparse->seek_pending = FALSE;
+      break;
+    default:
+      break;
+  }
+
+  return ret;
+}
+
+
+static gboolean
+gst_wavepack_parse_sink_activate (GstPad * sinkpad)
+{
+
+  if (gst_pad_check_pull_range (sinkpad)) {
+    return gst_pad_activate_pull (sinkpad, TRUE);
+  } else {
+    return FALSE;
+  }
+}
+
+static gboolean
+gst_wavepack_parse_sink_activate_pull (GstPad * sinkpad, gboolean active)
+{
+
+  gboolean result;
 
-  return GST_STATE_SUCCESS;
+  if (active) {
+
+    result = gst_pad_start_task (sinkpad,
+        (GstTaskFunction) gst_wavpack_parse_loop, GST_PAD_PARENT (sinkpad));
+  } else {
+    result = gst_pad_stop_task (sinkpad);
+  }
+
+  return result;
+
+  return TRUE;
 }
 
 gboolean
 gst_wavpack_parse_plugin_init (GstPlugin * plugin)
 {
-  if (!gst_library_load ("gstbytestream"))
-    return FALSE;
 
   if (!gst_element_register (plugin, "wavpackparse",
           GST_RANK_PRIMARY, GST_TYPE_WAVPACK_PARSE)) {
index ef76ba0..41bfe49 100644 (file)
@@ -23,7 +23,6 @@
 #define __GST_WAVPACK_PARSE_H__
 
 #include <gst/gst.h>
-#include <gst/bytestream/bytestream.h>
 
 G_BEGIN_DECLS
 
@@ -48,17 +47,19 @@ struct _GstWavpackParse
 
   GstPad *sinkpad, *srcpad;
   
-  GstByteStream* bs;
-
   guint32 samplerate;
   guint32 channels;
   guint32 total_samples;
   guint64 timestamp;
 
+  guint64 flushed_bytes;
+  guint64 duration;
+
   guint64 seek_offset;
   gboolean seek_pending;
   gboolean need_discont;
   gboolean need_flush;
+  gboolean eos;
 };
 
 struct _GstWavpackParseClass