Rewrote to use gstadapter and extract properties from header packets to pass downstre...
authorOwen Fraser-Green <owen@discobabe.net>
Mon, 27 Jun 2005 09:16:09 +0000 (09:16 +0000)
committerOwen Fraser-Green <owen@discobabe.net>
Mon, 27 Jun 2005 09:16:09 +0000 (09:16 +0000)
Original commit message from CVS:
Rewrote to use gstadapter and extract properties from header packets to pass downstream to decoders.

ChangeLog
configure.ac
gst/realmedia/Makefile.am
gst/realmedia/rmdemux.c
gst/realmedia/rmdemux.h

index af61341..76364bd 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2005-06-27  Owen Fraser-Green  <owen@discobabe.net>
+
+       * gst/realmedia/rmdemux.c: Rewrote to use gstadapter. Also parses
+       audio and video header packets for known properties.
+
 2005-06-23  Wim Taymans  <wim@fluendo.com>
 
        * gst/rtsp/gstrtspsrc.c: (gst_rtsp_proto_get_type),
index 405c945..3b10028 100644 (file)
@@ -310,6 +310,7 @@ GST_PLUGINS_ALL="\
                effectv \
                goom \
                law \
+               realmedia \
                rtp     \
                rtsp    \
                smpte   \
@@ -494,6 +495,7 @@ gst/alpha/Makefile
 gst/effectv/Makefile
 gst/goom/Makefile
 gst/law/Makefile
+gst/realmedia/Makefile
 gst/rtp/Makefile
 gst/rtsp/Makefile
 gst/smpte/Makefile
index f4186a5..07c5aa8 100644 (file)
@@ -4,7 +4,7 @@ plugin_LTLIBRARIES = libgstrmdemux.la
 libgstrmdemux_la_SOURCES = rmdemux.c
 
 libgstrmdemux_la_CFLAGS = $(GST_CFLAGS)
-libgstrmdemux_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+libgstrmdemux_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) $(GST_BASE_LIBS)
 
 noinst_HEADERS = rmdemux.h
 
index cbd2e26..1cc8bef 100644 (file)
@@ -2,6 +2,7 @@
  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
  * Copyright (C) <2004> Stephane Loeuillet <gstreamer@leroutier.net>
+ * Copyright (C) <2005> Owen Fraser-Green <owen@discobabe.net>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -20,8 +21,9 @@
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#  include "config.h"
 #endif
+
 #include "rmdemux.h"
 
 #include <string.h>
@@ -37,21 +39,30 @@ struct _GstRMDemuxStream
 {
   guint32 subtype;
   guint32 fourcc;
-  guint32 subid;
+  guint32 subformat;
+  guint32 format;
+
   int id;
   GstCaps *caps;
   GstPad *pad;
-  int n_samples;
   int timescale;
 
   int sample_index;
   GstRMDemuxIndex *index;
   int index_length;
-
-  int width;
-  int height;
-  double rate;
-  int n_channels;
+  double frame_rate;
+
+  guint16 width;
+  guint16 height;
+  guint16 flavor;
+  guint16 rate;                 // samplerate
+  guint16 n_channels;           // channels
+  guint16 sample_width;         // bits_per_sample
+  guint16 leaf_size;            // subpacket_size
+  guint32 packet_size;          // coded_frame_size
+  guint16 version;
+  guint32 extra_data_size;      // codec_data_length
+  guint8 *extra_data;           // extras
 };
 
 struct _GstRMDemuxIndex
@@ -66,9 +77,16 @@ enum GstRMDemuxState
 {
   RMDEMUX_STATE_NULL,
   RMDEMUX_STATE_HEADER,
+  RMDEMUX_STATE_HEADER_UNKNOWN,
+  RMDEMUX_STATE_HEADER_RMF,
+  RMDEMUX_STATE_HEADER_PROP,
+  RMDEMUX_STATE_HEADER_MDPR,
+  RMDEMUX_STATE_HEADER_INDX,
+  RMDEMUX_STATE_HEADER_DATA,
+  RMDEMUX_STATE_HEADER_CONT,
   RMDEMUX_STATE_HEADER_SEEKING,
   RMDEMUX_STATE_SEEKING,
-  RMDEMUX_STATE_PLAYING,
+  RMDEMUX_STATE_DATA_PACKET,
   RMDEMUX_STATE_SEEKING_EOS,
   RMDEMUX_STATE_EOS
 };
@@ -125,38 +143,25 @@ static GstElementClass *parent_class = NULL;
 static void gst_rmdemux_class_init (GstRMDemuxClass * klass);
 static void gst_rmdemux_base_init (GstRMDemuxClass * klass);
 static void gst_rmdemux_init (GstRMDemux * rmdemux);
+static void gst_rmdemux_dispose (GObject * object);
 static GstElementStateReturn gst_rmdemux_change_state (GstElement * element);
-static void gst_rmdemux_loop (GstElement * element);
-static gboolean gst_rmdemux_handle_sink_event (GstRMDemux * rmdemux);
-
-//static GstCaps *gst_rmdemux_video_caps(GstRMDemux *rmdemux, guint32 fourcc);
-//static GstCaps *gst_rmdemux_audio_caps(GstRMDemux *rmdemux, guint32 fourcc);
-
-static void gst_rmdemux_parse__rmf (GstRMDemux * rmdemux, void *data,
-    int length);
-static void gst_rmdemux_parse_prop (GstRMDemux * rmdemux, void *data,
-    int length);
-static void gst_rmdemux_parse_mdpr (GstRMDemux * rmdemux, void *data,
-    int length);
-static void gst_rmdemux_parse_indx (GstRMDemux * rmdemux, void *data,
-    int length);
-static void gst_rmdemux_parse_data (GstRMDemux * rmdemux, void *data,
-    int length);
-static void gst_rmdemux_parse_cont (GstRMDemux * rmdemux, void *data,
-    int length);
+static GstFlowReturn gst_rmdemux_chain (GstPad * pad, GstBuffer * buffer);
+static gboolean gst_rmdemux_sink_event (GstPad * pad, GstEvent * event);
 
-static void gst_rmdemux_dump__rmf (GstRMDemux * rmdemux, void *data,
+static void gst_rmdemux_parse__rmf (GstRMDemux * rmdemux, const void *data,
     int length);
-static void gst_rmdemux_dump_prop (GstRMDemux * rmdemux, void *data,
+static void gst_rmdemux_parse_prop (GstRMDemux * rmdemux, const void *data,
     int length);
-static void gst_rmdemux_dump_mdpr (GstRMDemux * rmdemux, void *data,
+static void gst_rmdemux_parse_mdpr (GstRMDemux * rmdemux, const void *data,
     int length);
-static void gst_rmdemux_dump_indx (GstRMDemux * rmdemux, void *data,
+static void gst_rmdemux_parse_indx (GstRMDemux * rmdemux, const void *data,
     int length);
-static void gst_rmdemux_dump_data (GstRMDemux * rmdemux, void *data,
+static void gst_rmdemux_parse_data (GstRMDemux * rmdemux, const void *data,
     int length);
-static void gst_rmdemux_dump_cont (GstRMDemux * rmdemux, void *data,
+static void gst_rmdemux_parse_cont (GstRMDemux * rmdemux, const void *data,
     int length);
+static void gst_rmdemux_parse_packet (GstRMDemux * rmdemux, const void *data,
+    guint16 version, guint16 length);
 
 static GstRMDemuxStream *gst_rmdemux_get_stream_by_id (GstRMDemux * rmdemux,
     int id);
@@ -211,26 +216,39 @@ gst_rmdemux_class_init (GstRMDemuxClass * klass)
 
   GST_DEBUG_CATEGORY_INIT (rmdemux_debug, "rmdemux",
       0, "Demuxer for Realmedia streams");
+
+  gobject_class->dispose = gst_rmdemux_dispose;
 }
 
 static void
-gst_rmdemux_init (GstRMDemux * rmdemux)
+gst_rmdemux_dispose (GObject * object)
 {
-  GST_FLAG_SET (rmdemux, GST_ELEMENT_EVENT_AWARE);
+  GstRMDemux *rmdemux = GST_RMDEMUX (object);
+
+  if (rmdemux->adapter) {
+    g_object_unref (rmdemux->adapter);
+    rmdemux->adapter = NULL;
+  }
 
+  GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
+}
+
+static void
+gst_rmdemux_init (GstRMDemux * rmdemux)
+{
   rmdemux->sinkpad =
       gst_pad_new_from_template (gst_static_pad_template_get
       (&gst_rmdemux_sink_template), "sink");
-  gst_element_set_loop_function (GST_ELEMENT (rmdemux), gst_rmdemux_loop);
+  gst_pad_set_event_function (rmdemux->sinkpad, gst_rmdemux_sink_event);
+  gst_pad_set_chain_function (rmdemux->sinkpad, gst_rmdemux_chain);
   gst_element_add_pad (GST_ELEMENT (rmdemux), rmdemux->sinkpad);
+
+  rmdemux->adapter = gst_adapter_new ();
 }
 
 static gboolean
 plugin_init (GstPlugin * plugin)
 {
-  if (!gst_library_load ("gstbytestream"))
-    return FALSE;
-
   return gst_element_register (plugin, "rmdemux",
       GST_RANK_PRIMARY, GST_TYPE_RMDEMUX);
 }
@@ -241,37 +259,25 @@ GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
     "Realmedia stream demuxer",
     plugin_init, VERSION, "LGPL", GST_PACKAGE, GST_ORIGIN)
 
-     static gboolean gst_rmdemux_handle_sink_event (GstRMDemux * rmdemux)
+     static gboolean gst_rmdemux_sink_event (GstPad * pad, GstEvent * event)
 {
-  guint32 remaining;
-  GstEvent *event;
-  GstEventType type;
+  gboolean ret = TRUE;
 
-  gst_bytestream_get_status (rmdemux->bs, &remaining, &event);
+  GstRMDemux *rmdemux = GST_RMDEMUX (GST_PAD_PARENT (pad));
 
-  type = event ? GST_EVENT_TYPE (event) : GST_EVENT_UNKNOWN;
-  GST_DEBUG ("rmdemux: event %p %d", event, type);
+  GST_LOG_OBJECT (rmdemux, "handling event");
 
-  switch (type) {
-    case GST_EVENT_EOS:
-      gst_pad_event_default (rmdemux->sinkpad, event);
-      return FALSE;
-    case GST_EVENT_INTERRUPT:
-      gst_event_unref (event);
-      return FALSE;
-    case GST_EVENT_FLUSH:
-      break;
+  switch (GST_EVENT_TYPE (event)) {
     case GST_EVENT_DISCONTINUOUS:
-      GST_DEBUG ("discontinuous event");
-      //gst_bytestream_flush_fast(rmdemux->bs, remaining);
+      GST_DEBUG_OBJECT (rmdemux, "discontinuous event");
+      gst_event_unref (event);
       break;
     default:
-      GST_WARNING ("unhandled event %d", type);
+      ret = gst_pad_event_default (rmdemux->sinkpad, event);
       break;
   }
 
-  gst_event_unref (event);
-  return TRUE;
+  return ret;
 }
 
 static GstElementStateReturn
@@ -283,16 +289,14 @@ gst_rmdemux_change_state (GstElement * element)
     case GST_STATE_NULL_TO_READY:
       break;
     case GST_STATE_READY_TO_PAUSED:
-      rmdemux->bs = gst_bytestream_new (rmdemux->sinkpad);
       rmdemux->state = RMDEMUX_STATE_HEADER;
-      /* FIXME */
       break;
     case GST_STATE_PAUSED_TO_PLAYING:
       break;
     case GST_STATE_PLAYING_TO_PAUSED:
       break;
     case GST_STATE_PAUSED_TO_READY:
-      gst_bytestream_destroy (rmdemux->bs);
+      gst_adapter_clear (rmdemux->adapter);
       break;
     case GST_STATE_READY_TO_NULL:
       break;
@@ -300,191 +304,205 @@ gst_rmdemux_change_state (GstElement * element)
       break;
   }
 
-  return GST_ELEMENT_CLASS (parent_class)->change_state (element);
+  if (GST_ELEMENT_CLASS (parent_class)->change_state)
+    return GST_ELEMENT_CLASS (parent_class)->change_state (element);
+
+  return GST_STATE_SUCCESS;
 }
 
-static void
-gst_rmdemux_loop (GstElement * element)
+static GstFlowReturn
+gst_rmdemux_chain (GstPad * pad, GstBuffer * buffer)
 {
-  GstRMDemux *rmdemux = GST_RMDEMUX (element);
-  guint8 *data;
-  guint32 length;
-  guint32 fourcc;
-  GstBuffer *buf;
+  GstFlowReturn ret = GST_FLOW_OK;
+  const guint8 *data;
+  guint16 version;
 
-  //int offset;
-  int cur_offset;
+  GstRMDemux *rmdemux = GST_RMDEMUX (GST_PAD_PARENT (pad));
 
-  //int size;
-  int ret;
-  int rlen;
+  GST_STREAM_LOCK (pad);
 
-  /* FIXME _tell gets the offset wrong */
-  //cur_offset = gst_bytestream_tell(rmdemux->bs);
+  gst_adapter_push (rmdemux->adapter, buffer);
 
-  cur_offset = rmdemux->offset;
-  GST_DEBUG ("loop at position %d, state %d", cur_offset, rmdemux->state);
+  while (TRUE) {
+    switch (rmdemux->state) {
+      case RMDEMUX_STATE_HEADER:
+      {
+        if (gst_adapter_available (rmdemux->adapter) < 10)
+          goto unlock;
 
-  if (rmdemux->length == 0) {
-    rmdemux->length = gst_bytestream_length (rmdemux->bs);
-  }
+        data = gst_adapter_peek (rmdemux->adapter, 10);
 
-  switch (rmdemux->state) {
-    case RMDEMUX_STATE_HEADER:
-    {
-      do {
-        ret = gst_bytestream_peek_bytes (rmdemux->bs, &data, 16);
-        if (ret < 16) {
-          if (!gst_rmdemux_handle_sink_event (rmdemux)) {
-            return;
-          }
-        } else {
-          break;
-        }
-      } while (1);
+        rmdemux->object_id = RMDEMUX_FOURCC_GET (data + 0);
+        rmdemux->size = RMDEMUX_GUINT32_GET (data + 4) - 10;
+        rmdemux->object_version = RMDEMUX_GUINT16_GET (data + 8);
 
-      fourcc = RMDEMUX_FOURCC_GET (data + 0);
-      length = RMDEMUX_GUINT32_GET (data + 4);
+        GST_LOG_OBJECT (rmdemux, "header found with object_id="
+            GST_FOURCC_FORMAT
+            " size=%08x object_version=%d",
+            GST_FOURCC_ARGS (rmdemux->object_id), rmdemux->size,
+            rmdemux->object_version);
 
-      GST_LOG ("fourcc " GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
-      GST_LOG ("length %08x", length);
+        gst_adapter_flush (rmdemux->adapter, 10);
 
-      rlen = MIN (length, 4096) - 8;
-
-      switch (fourcc) {
-        case GST_MAKE_FOURCC ('.', 'R', 'M', 'F'):
-          gst_bytestream_read (rmdemux->bs, &buf, length);
-          data = GST_BUFFER_DATA (buf);
-          gst_rmdemux_dump__rmf (rmdemux, data + 8, rlen);
-          gst_rmdemux_parse__rmf (rmdemux, data + 8, rlen);
-          break;
-        case GST_MAKE_FOURCC ('P', 'R', 'O', 'P'):
-          gst_bytestream_read (rmdemux->bs, &buf, length);
-          data = GST_BUFFER_DATA (buf);
-          gst_rmdemux_dump_prop (rmdemux, data + 8, rlen);
-          gst_rmdemux_parse_prop (rmdemux, data + 8, rlen);
-          break;
-        case GST_MAKE_FOURCC ('M', 'D', 'P', 'R'):
-          gst_bytestream_read (rmdemux->bs, &buf, length);
-          data = GST_BUFFER_DATA (buf);
-          gst_rmdemux_dump_mdpr (rmdemux, data + 8, rlen);
-          gst_rmdemux_parse_mdpr (rmdemux, data + 8, rlen);
-          break;
-        case GST_MAKE_FOURCC ('I', 'N', 'D', 'X'):
-          gst_bytestream_read (rmdemux->bs, &buf, length);
-          data = GST_BUFFER_DATA (buf);
-          gst_rmdemux_dump_indx (rmdemux, data + 8, rlen);
-          gst_rmdemux_parse_indx (rmdemux, data + 8, rlen);
-          break;
-        case GST_MAKE_FOURCC ('D', 'A', 'T', 'A'):
-          rmdemux->data_offset = rmdemux->offset + 10;
-          gst_rmdemux_dump_data (rmdemux, data + 8, rlen);
-          gst_rmdemux_parse_data (rmdemux, data + 8, rlen);
-          break;
-        case GST_MAKE_FOURCC ('C', 'O', 'N', 'T'):
-          gst_bytestream_read (rmdemux->bs, &buf, length);
-          data = GST_BUFFER_DATA (buf);
-          gst_rmdemux_dump_cont (rmdemux, data + 8, rlen);
-          gst_rmdemux_parse_cont (rmdemux, data + 8, rlen);
-          break;
-        default:
-          GST_WARNING ("unknown fourcc " GST_FOURCC_FORMAT,
-              GST_FOURCC_ARGS (fourcc));
-          break;
+        switch (rmdemux->object_id) {
+          case GST_MAKE_FOURCC ('.', 'R', 'M', 'F'):
+            rmdemux->state = RMDEMUX_STATE_HEADER_RMF;
+            break;
+          case GST_MAKE_FOURCC ('P', 'R', 'O', 'P'):
+            rmdemux->state = RMDEMUX_STATE_HEADER_PROP;
+            break;
+          case GST_MAKE_FOURCC ('M', 'D', 'P', 'R'):
+            rmdemux->state = RMDEMUX_STATE_HEADER_MDPR;
+            break;
+          case GST_MAKE_FOURCC ('I', 'N', 'D', 'X'):
+            rmdemux->state = RMDEMUX_STATE_HEADER_INDX;
+            break;
+          case GST_MAKE_FOURCC ('D', 'A', 'T', 'A'):
+            rmdemux->state = RMDEMUX_STATE_HEADER_DATA;
+            break;
+          case GST_MAKE_FOURCC ('C', 'O', 'N', 'T'):
+            rmdemux->state = RMDEMUX_STATE_HEADER_CONT;
+            break;
+          default:
+            rmdemux->state = RMDEMUX_STATE_HEADER_UNKNOWN;
+            break;
+        }
+        break;
       }
+      case RMDEMUX_STATE_HEADER_UNKNOWN:
+      {
+        if (gst_adapter_available (rmdemux->adapter) < rmdemux->size)
+          goto unlock;
 
-      rmdemux->offset += length ? length : 8;
-      if (rmdemux->offset < rmdemux->length) {
-        ret = gst_bytestream_seek (rmdemux->bs, rmdemux->offset,
-            GST_SEEK_METHOD_SET);
-      } else {
-        rmdemux->offset = rmdemux->data_offset + 8;
-        rmdemux->state = RMDEMUX_STATE_PLAYING;
-        ret = gst_bytestream_seek (rmdemux->bs, rmdemux->offset,
-            GST_SEEK_METHOD_SET);
+        GST_WARNING_OBJECT (rmdemux, "Unknown object_id " GST_FOURCC_FORMAT,
+            GST_FOURCC_ARGS (rmdemux->object_id));
 
-        GST_DEBUG ("no more pads to come");
-        gst_element_no_more_pads (element);
+        gst_adapter_flush (rmdemux->adapter, rmdemux->size);
+        rmdemux->state = RMDEMUX_STATE_HEADER;
+        break;
       }
-      break;
-    }
-    case RMDEMUX_STATE_SEEKING_EOS:
-    {
-      guint8 *data;
+      case RMDEMUX_STATE_HEADER_RMF:
+      {
+        if (gst_adapter_available (rmdemux->adapter) < rmdemux->size)
+          goto unlock;
 
-      for (;;) {
-        ret = gst_bytestream_peek_bytes (rmdemux->bs, &data, 1);
-        if (ret < 1) {
-          if (!gst_rmdemux_handle_sink_event (rmdemux))
-            break;
-        } else {
-          /* didn't expect this */
-          GST_WARNING ("expected EOS event");
-          break;
+        if ((rmdemux->object_version == 0) || (rmdemux->object_version == 1)) {
+          data = gst_adapter_peek (rmdemux->adapter, rmdemux->size);
+
+          gst_rmdemux_parse__rmf (rmdemux, data, rmdemux->size);
         }
+
+        gst_adapter_flush (rmdemux->adapter, rmdemux->size);
+        rmdemux->state = RMDEMUX_STATE_HEADER;
+        break;
       }
+      case RMDEMUX_STATE_HEADER_PROP:
+      {
+        if (gst_adapter_available (rmdemux->adapter) < rmdemux->size)
+          goto unlock;
+        data = gst_adapter_peek (rmdemux->adapter, rmdemux->size);
 
-      rmdemux->state = RMDEMUX_STATE_EOS;
-      return;
-    }
-    case RMDEMUX_STATE_EOS:
-      g_warning ("spinning in EOS");
-      return;
-    case RMDEMUX_STATE_PLAYING:
-    {
-      int id, timestamp, unknown1;
-      GstRMDemuxStream *stream;
-      GstBuffer *buffer;
+        gst_rmdemux_parse_prop (rmdemux, data, rmdemux->size);
 
-      do {
-        ret = gst_bytestream_peek_bytes (rmdemux->bs, &data, 10);
-        if (ret < 10) {
-          if (!gst_rmdemux_handle_sink_event (rmdemux)) {
-            return;
-          }
-        } else {
-          break;
-        }
-      } while (1);
+        gst_adapter_flush (rmdemux->adapter, rmdemux->size);
+        rmdemux->state = RMDEMUX_STATE_HEADER;
+        break;
+      }
+      case RMDEMUX_STATE_HEADER_MDPR:
+      {
+        if (gst_adapter_available (rmdemux->adapter) < rmdemux->size)
+          goto unlock;
+        data = gst_adapter_peek (rmdemux->adapter, rmdemux->size);
 
-      length = RMDEMUX_GUINT32_GET (data + 0);
-      id = RMDEMUX_GUINT16_GET (data + 4);
-      timestamp = RMDEMUX_GUINT32_GET (data + 6);
-      unknown1 = RMDEMUX_GUINT16_GET (data + 10);
-      GST_DEBUG ("length %d stream id %d timestamp %d unknown %d",
-          length, id, timestamp, unknown1);
+        gst_rmdemux_parse_mdpr (rmdemux, data, rmdemux->size);
 
-      gst_bytestream_flush (rmdemux->bs, 12);
+        gst_adapter_flush (rmdemux->adapter, rmdemux->size);
+        rmdemux->state = RMDEMUX_STATE_HEADER;
+        break;
+      }
+      case RMDEMUX_STATE_HEADER_CONT:
+      {
+        if (gst_adapter_available (rmdemux->adapter) < rmdemux->size)
+          goto unlock;
+        data = gst_adapter_peek (rmdemux->adapter, rmdemux->size);
 
-      gst_bytestream_read (rmdemux->bs, &buffer, length - 12);
-      stream = gst_rmdemux_get_stream_by_id (rmdemux, id);
+        gst_rmdemux_parse_cont (rmdemux, data, rmdemux->size);
 
-      if (stream && stream->pad && GST_PAD_IS_USABLE (stream->pad)) {
-        gst_pad_push (stream->pad, GST_DATA (buffer));
-      } else {
-        gst_buffer_unref (buffer);
+        gst_adapter_flush (rmdemux->adapter, rmdemux->size);
+        rmdemux->state = RMDEMUX_STATE_HEADER;
+        break;
       }
+      case RMDEMUX_STATE_HEADER_DATA:
+      {
+        /* The actual header is only 8 bytes */
+        rmdemux->size = 8;
+        if (gst_adapter_available (rmdemux->adapter) < rmdemux->size)
+          goto unlock;
 
-      rmdemux->chunk_index++;
-      GST_DEBUG ("chunk_index %d n_chunks %d", rmdemux->chunk_index,
-          rmdemux->n_chunks);
-      if (rmdemux->chunk_index < rmdemux->n_chunks) {
-        rmdemux->offset += length;
-        ret = gst_bytestream_seek (rmdemux->bs, rmdemux->offset,
-            GST_SEEK_METHOD_SET);
-      } else {
-        ret = gst_bytestream_seek (rmdemux->bs, 0, GST_SEEK_METHOD_END);
-        GST_DEBUG ("seek to end returned %d", ret);
-        rmdemux->state = RMDEMUX_STATE_SEEKING_EOS;
+        data = gst_adapter_peek (rmdemux->adapter, rmdemux->size);
+
+        gst_rmdemux_parse_data (rmdemux, data, rmdemux->size);
+
+        gst_adapter_flush (rmdemux->adapter, rmdemux->size);
+        rmdemux->state = RMDEMUX_STATE_DATA_PACKET;
+        break;
       }
+      case RMDEMUX_STATE_HEADER_INDX:
+      {
+        if (gst_adapter_available (rmdemux->adapter) < rmdemux->size)
+          goto unlock;
+        data = gst_adapter_peek (rmdemux->adapter, rmdemux->size);
 
-      break;
+        gst_rmdemux_parse_indx (rmdemux, data, rmdemux->size);
+
+        gst_adapter_flush (rmdemux->adapter, rmdemux->size);
+        rmdemux->state = RMDEMUX_STATE_HEADER;
+        break;
+      }
+      case RMDEMUX_STATE_DATA_PACKET:
+      {
+        if (gst_adapter_available (rmdemux->adapter) < 2)
+          goto unlock;
+
+        data = gst_adapter_peek (rmdemux->adapter, 2);
+        version = RMDEMUX_GUINT16_GET (data);
+        GST_DEBUG_OBJECT (rmdemux, "Data packet with version=%d", version);
+
+        if (version == 0 || version == 1) {
+          guint16 length;
+
+          if (gst_adapter_available (rmdemux->adapter) < 4)
+            goto unlock;
+          data = gst_adapter_peek (rmdemux->adapter, 4);
+
+          length = RMDEMUX_GUINT16_GET (data + 2);
+          if (length == 0) {
+            gst_adapter_flush (rmdemux->adapter, 2);
+          } else {
+            if (gst_adapter_available (rmdemux->adapter) < length)
+              goto unlock;
+            data = gst_adapter_peek (rmdemux->adapter, length);
+
+            gst_rmdemux_parse_packet (rmdemux, data + 4, version, length);
+            rmdemux->chunk_index++;
+
+            gst_adapter_flush (rmdemux->adapter, length);
+          }
+
+          if (rmdemux->chunk_index == rmdemux->n_chunks || length == 0)
+            rmdemux->state = RMDEMUX_STATE_HEADER;
+        } else {
+          /* Stream done */
+          gst_adapter_flush (rmdemux->adapter, 2);
+          rmdemux->state = RMDEMUX_STATE_HEADER;
+        }
+      }
     }
-    default:
-      /* unreached */
-      g_assert (0);
   }
 
+unlock:
+  GST_STREAM_UNLOCK (pad);
+  return ret;
 }
 
 static GstRMDemuxStream *
@@ -527,20 +545,26 @@ gst_rmdemux_add_stream (GstRMDemux * rmdemux, GstRMDemuxStream * stream)
         version = 4;
         break;
       default:
-        GST_WARNING ("Unknown video FOURCC code");
+        GST_WARNING_OBJECT (rmdemux, "Unknown video FOURCC code");
     }
+
     if (version) {
       stream->caps =
           gst_caps_new_simple ("video/x-pn-realvideo", "rmversion", G_TYPE_INT,
-          (int) version, "rmsubid", GST_TYPE_FOURCC, stream->subid, NULL);
+          (int) version,
+          "format", G_TYPE_INT,
+          (int) stream->format,
+          "subformat", G_TYPE_INT, (int) stream->subformat, NULL);
     }
 
     if (stream->caps) {
       gst_caps_set_simple (stream->caps,
           "width", G_TYPE_INT, stream->width,
-          "height", G_TYPE_INT, stream->height, NULL);
+          "height", G_TYPE_INT, stream->height,
+          "framerate", G_TYPE_DOUBLE, stream->frame_rate, NULL);
     }
     rmdemux->n_video_streams++;
+
   } else if (stream->subtype == GST_RMDEMUX_STREAM_AUDIO) {
     stream->pad =
         gst_pad_new_from_template (gst_static_pad_template_get
@@ -563,8 +587,12 @@ gst_rmdemux_add_stream (GstRMDemux * rmdemux, GstRMDemuxStream * stream)
             (int) stream->rate, NULL);
         break;
 
-        /* MPEG-4 based */
+        /* RealAudio 10 (AAC) */
       case GST_RM_AUD_RAAC:
+        version = 10;
+        break;
+
+        /* MPEG-4 based */
       case GST_RM_AUD_RACP:
         stream->caps =
             gst_caps_new_simple ("audio/mpeg", "mpegversion", G_TYPE_INT,
@@ -576,19 +604,24 @@ gst_rmdemux_add_stream (GstRMDemux * rmdemux, GstRMDemuxStream * stream)
         stream->caps = gst_caps_new_simple ("audio/x-vnd.sony.atrac3", NULL);
         break;
 
-        /* RealAudio audio/RALF is lossless */
+        /* RealAudio G2 audio */
       case GST_RM_AUD_COOK:
+        version = 8;
+        break;
+
+        /* RALF is lossless */
       case GST_RM_AUD_RALF:
+        stream->caps = gst_caps_new_simple ("audio/x-ralf-mpeg4-generic", NULL);
+        break;
 
-        /* Sipro/ACELP-NET Voice Codec */
+        /* Sipro/ACELP.NET Voice Codec (MIME unknown) */
       case GST_RM_AUD_SIPR:
-
-        GST_WARNING ("Nothing known to decode this audio FOURCC code");
+        stream->caps = gst_caps_new_simple ("audio/x-sipro", NULL);
         break;
 
       default:
-        GST_WARNING ("Unknown audio FOURCC code " GST_FOURCC_FORMAT,
-            stream->fourcc);
+        GST_WARNING_OBJECT (rmdemux,
+            "Unknown audio FOURCC code " GST_FOURCC_FORMAT, stream->fourcc);
         break;
     }
 
@@ -600,54 +633,64 @@ gst_rmdemux_add_stream (GstRMDemux * rmdemux, GstRMDemuxStream * stream)
 
     if (stream->caps) {
       gst_caps_set_simple (stream->caps,
+          "flavor", G_TYPE_INT, (int) stream->flavor,
           "rate", G_TYPE_INT, (int) stream->rate,
-          "channels", G_TYPE_INT, stream->n_channels, NULL);
+          "channels", G_TYPE_INT, (int) stream->n_channels,
+          "width", G_TYPE_INT, (int) stream->sample_width,
+          "leaf_size", G_TYPE_INT, (int) stream->leaf_size,
+          "packet_size", G_TYPE_INT, (int) stream->packet_size,
+          "height", G_TYPE_INT, (int) stream->height, NULL);
     }
     rmdemux->n_audio_streams++;
+
+
   } else {
-    GST_WARNING ("not adding stream of type %d", stream->subtype);
+    GST_WARNING_OBJECT (rmdemux, "not adding stream of type %d",
+        stream->subtype);
     return;
   }
 
   GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
   rmdemux->streams[rmdemux->n_streams] = stream;
   rmdemux->n_streams++;
-  GST_LOG ("n_streams is now %d", rmdemux->n_streams);
+  GST_LOG_OBJECT (rmdemux, "n_streams is now %d", rmdemux->n_streams);
 
   if (stream->pad) {
-    gst_pad_use_explicit_caps (stream->pad);
+    GST_DEBUG_OBJECT (rmdemux, "setting caps: %p", stream->caps);
 
-    GST_DEBUG ("setting caps: " GST_PTR_FORMAT, stream->caps);
+    gst_pad_set_caps (stream->pad, stream->caps);
+    gst_caps_unref (stream->caps);
 
-    gst_pad_set_explicit_caps (stream->pad, stream->caps);
-
-    GST_DEBUG ("adding pad %p to rmdemux %p", stream->pad, rmdemux);
+    GST_DEBUG_OBJECT (rmdemux, "adding pad %p to rmdemux %p", stream->pad,
+        rmdemux);
     gst_element_add_pad (GST_ELEMENT (rmdemux), stream->pad);
-  }
-}
 
+    /* If there's some extra data then send it as the first packet */
+    if (stream->extra_data_size > 0) {
+      GstBuffer *buffer;
 
-#if 0
+      if (gst_pad_alloc_buffer (stream->pad, GST_BUFFER_OFFSET_NONE,
+              stream->extra_data_size, stream->caps, &buffer) != GST_FLOW_OK) {
+        GST_WARNING_OBJECT (rmdemux, "failed to alloc src buffer for stream %d",
+            stream->id);
+        return;
+      }
 
-static GstCaps *
-gst_rmdemux_video_caps (GstRMDemux * rmdemux, guint32 fourcc)
-{
-  return NULL;
-}
+      memcpy (GST_BUFFER_DATA (buffer), stream->extra_data,
+          stream->extra_data_size);
 
-static GstCaps *
-gst_rmdemux_audio_caps (GstRMDemux * rmdemux, guint32 fourcc)
-{
-  return NULL;
+      if (GST_PAD_IS_USABLE (stream->pad)) {
+        GST_DEBUG_OBJECT (rmdemux, "Pushing extra_data of size %d to pad",
+            stream->extra_data_size);
+        gst_pad_push (stream->pad, buffer);
+      }
+    }
+  }
 }
 
-#endif
-
-
 static void
 re_hexdump_bytes (guint8 * ptr, int len, int offset)
 {
-#if 0
   guint8 *end = ptr + len;
   int i;
 
@@ -673,31 +716,19 @@ re_hexdump_bytes (guint8 * ptr, int len, int offset)
     ptr += 16;
     offset += 16;
   }
-#endif
-}
-
-static int
-re_dump_pascal_string (guint8 * ptr)
-{
-  int length;
-
-  length = ptr[0];
-  GST_DEBUG ("string: %.*s", length, (char *) ptr + 1);
-
-  return length + 1;
 }
 
 static char *
-re_get_pascal_string (guint8 * ptr)
+re_get_pascal_string (const guint8 * ptr)
 {
   int length;
 
   length = ptr[0];
-  return g_strndup (ptr + 1, length);
+  return g_strndup ((char *) ptr + 1, length);
 }
 
 static int
-re_skip_pascal_string (guint8 * ptr)
+re_skip_pascal_string (const guint8 * ptr)
 {
   int length;
 
@@ -706,47 +737,39 @@ re_skip_pascal_string (guint8 * ptr)
   return length + 1;
 }
 
-
 static void
-gst_rmdemux_parse__rmf (GstRMDemux * rmdemux, void *data, int length)
+gst_rmdemux_parse__rmf (GstRMDemux * rmdemux, const void *data, int length)
 {
-
+  GST_LOG_OBJECT (rmdemux, "file_version: %d", RMDEMUX_GUINT32_GET (data));
+  GST_LOG_OBJECT (rmdemux, "num_headers: %d", RMDEMUX_GUINT32_GET (data + 4));
 }
 
 static void
-gst_rmdemux_dump__rmf (GstRMDemux * rmdemux, void *data, int length)
-{
-  GST_LOG ("version: %d", RMDEMUX_GUINT16_GET (data + 0));
-  GST_LOG ("unknown: %d", RMDEMUX_GUINT32_GET (data + 2));
-  GST_LOG ("unknown: %d", RMDEMUX_GUINT32_GET (data + 6));
-}
-
-static void
-gst_rmdemux_parse_prop (GstRMDemux * rmdemux, void *data, int length)
-{
-
-  rmdemux->duration = RMDEMUX_GUINT32_GET (data + 22);
+gst_rmdemux_parse_prop (GstRMDemux * rmdemux, const void *data, int length)
+{
+  GST_LOG_OBJECT (rmdemux, "max bitrate: %d", RMDEMUX_GUINT32_GET (data));
+  GST_LOG_OBJECT (rmdemux, "avg bitrate: %d", RMDEMUX_GUINT32_GET (data + 4));
+  GST_LOG_OBJECT (rmdemux, "max packet size: %d",
+      RMDEMUX_GUINT32_GET (data + 8));
+  GST_LOG_OBJECT (rmdemux, "avg packet size: %d",
+      RMDEMUX_GUINT32_GET (data + 12));
+  GST_LOG_OBJECT (rmdemux, "number of packets: %d",
+      RMDEMUX_GUINT32_GET (data + 16));
+
+  GST_LOG_OBJECT (rmdemux, "duration: %d", RMDEMUX_GUINT32_GET (data + 20));
+  rmdemux->duration = RMDEMUX_GUINT32_GET (data + 20);
+
+  GST_LOG_OBJECT (rmdemux, "preroll: %d", RMDEMUX_GUINT32_GET (data + 24));
+  GST_LOG_OBJECT (rmdemux, "offset of INDX section: 0x%08x",
+      RMDEMUX_GUINT32_GET (data + 28));
+  GST_LOG_OBJECT (rmdemux, "offset of DATA section: 0x%08x",
+      RMDEMUX_GUINT32_GET (data + 32));
+  GST_LOG_OBJECT (rmdemux, "n streams: %d", RMDEMUX_GUINT16_GET (data + 36));
+  GST_LOG_OBJECT (rmdemux, "flags: 0x%04x", RMDEMUX_GUINT16_GET (data + 38));
 }
 
 static void
-gst_rmdemux_dump_prop (GstRMDemux * rmdemux, void *data, int length)
-{
-  GST_LOG ("version: %d", RMDEMUX_GUINT16_GET (data + 0));
-  GST_LOG ("max bitrate: %d", RMDEMUX_GUINT32_GET (data + 2));
-  GST_LOG ("avg bitrate: %d", RMDEMUX_GUINT32_GET (data + 6));
-  GST_LOG ("max packet size: %d", RMDEMUX_GUINT32_GET (data + 10));
-  GST_LOG ("avg packet size: %d", RMDEMUX_GUINT32_GET (data + 14));
-  GST_LOG ("number of packets: %d", RMDEMUX_GUINT32_GET (data + 18));
-  GST_LOG ("duration: %d", RMDEMUX_GUINT32_GET (data + 22));
-  GST_LOG ("preroll: %d", RMDEMUX_GUINT32_GET (data + 26));
-  GST_LOG ("offset of INDX section: 0x%08x", RMDEMUX_GUINT32_GET (data + 30));
-  GST_LOG ("offset of DATA section: 0x%08x", RMDEMUX_GUINT32_GET (data + 34));
-  GST_LOG ("n streams: %d", RMDEMUX_GUINT16_GET (data + 38));
-  GST_LOG ("flags: 0x%04x", RMDEMUX_GUINT16_GET (data + 40));
-}
-
-static void
-gst_rmdemux_parse_mdpr (GstRMDemux * rmdemux, void *data, int length)
+gst_rmdemux_parse_mdpr (GstRMDemux * rmdemux, const void *data, int length)
 {
   GstRMDemuxStream *stream;
   char *stream1_type_string;
@@ -754,11 +777,14 @@ gst_rmdemux_parse_mdpr (GstRMDemux * rmdemux, void *data, int length)
   int stream_type;
   int offset;
 
+  //re_hexdump_bytes ((guint8 *) data, length, 0);
+
   stream = g_new0 (GstRMDemuxStream, 1);
 
-  stream->id = RMDEMUX_GUINT16_GET (data + 2);
+  stream->id = RMDEMUX_GUINT16_GET (data);
+  GST_LOG_OBJECT (rmdemux, "stream_number=%d", stream->id);
 
-  offset = 32;
+  offset = 30;
   stream_type = GST_RMDEMUX_STREAM_UNKNOWN;
   stream1_type_string = re_get_pascal_string (data + offset);
   offset += re_skip_pascal_string (data + offset);
@@ -773,6 +799,9 @@ gst_rmdemux_parse_mdpr (GstRMDemux * rmdemux, void *data, int length)
      so, we should not rely on it to know which stream type it is
    */
 
+  GST_LOG_OBJECT (rmdemux, "stream type: %s", stream1_type_string);
+  GST_LOG_OBJECT (rmdemux, "MIME type=%s", stream2_type_string);
+
   if (strcmp (stream2_type_string, "video/x-pn-realvideo") == 0) {
     stream_type = GST_RMDEMUX_STREAM_VIDEO;
   } else if (strcmp (stream2_type_string, "audio/x-pn-realaudio") == 0) {
@@ -782,8 +811,8 @@ gst_rmdemux_parse_mdpr (GstRMDemux * rmdemux, void *data, int length)
     stream_type = GST_RMDEMUX_STREAM_FILEINFO;
   } else {
     stream_type = GST_RMDEMUX_STREAM_UNKNOWN;
-    GST_WARNING ("unknown stream type \"%s\",\"%s\"", stream1_type_string,
-        stream2_type_string);
+    GST_WARNING_OBJECT (rmdemux, "unknown stream type \"%s\",\"%s\"",
+        stream1_type_string, stream2_type_string);
   }
   g_free (stream1_type_string);
   g_free (stream2_type_string);
@@ -796,34 +825,54 @@ gst_rmdemux_parse_mdpr (GstRMDemux * rmdemux, void *data, int length)
     case GST_RMDEMUX_STREAM_VIDEO:
       /* RV10/RV20/RV30/RV40 => video/x-pn-realvideo, version=1,2,3,4 */
       stream->fourcc = RMDEMUX_FOURCC_GET (data + offset + 8);
-
       stream->width = RMDEMUX_GUINT16_GET (data + offset + 12);
       stream->height = RMDEMUX_GUINT16_GET (data + offset + 14);
       stream->rate = RMDEMUX_GUINT16_GET (data + offset + 16);
-      stream->subid = RMDEMUX_GUINT32_GET (data + offset + 30);
+      stream->subformat = RMDEMUX_GUINT32_GET (data + offset + 26);
+      stream->format = RMDEMUX_GUINT32_GET (data + offset + 30);
+      stream->extra_data_size = length - (offset + 34);
+      stream->extra_data = (guint8 *) data + offset + 34;
+      stream->frame_rate = (double) RMDEMUX_GUINT16_GET (data + offset + 22) +
+          ((double) RMDEMUX_GUINT16_GET (data + offset + 24) / 65536.0);
+
+      GST_DEBUG_OBJECT (rmdemux,
+          "Video stream with fourcc=" GST_FOURCC_FORMAT
+          " width=%d height=%d rate=%d frame_rate=%f subformat=%x format=%x extra_data_size=%d",
+          GST_FOURCC_ARGS (stream->fourcc), stream->width, stream->height,
+          stream->rate, stream->frame_rate, stream->subformat, stream->format,
+          stream->extra_data_size);
       break;
     case GST_RMDEMUX_STREAM_AUDIO:{
-      int audio_fourcc_offset;
-
-      /* .ra4/.ra5 */
-      stream->fourcc = RMDEMUX_FOURCC_GET (data + offset + 8);
-
-      stream->rate = RMDEMUX_GUINT32_GET (data + offset + 48);
-
-      switch (stream->fourcc) {
-        case GST_RM_AUD_xRA4:
-          audio_fourcc_offset = 62;
+      stream->version = RMDEMUX_GUINT16_GET (data + offset + 4);
+      stream->flavor = RMDEMUX_GUINT16_GET (data + offset + 22);
+      stream->packet_size = RMDEMUX_GUINT32_GET (data + offset + 24);
+      stream->leaf_size = RMDEMUX_GUINT16_GET (data + offset + 44);
+      stream->height = RMDEMUX_GUINT16_GET (data + offset + 40);
+
+      switch (stream->version) {
+        case 4:
+          stream->rate = RMDEMUX_GUINT16_GET (data + offset + 48);
+          stream->sample_width = RMDEMUX_GUINT16_GET (data + offset + 52);
+          stream->n_channels = RMDEMUX_GUINT16_GET (data + offset + 54);
+          stream->fourcc = RMDEMUX_FOURCC_GET (data + offset + 62);
+          stream->extra_data_size = 16;
+          stream->extra_data = (guint8 *) data + offset + 71;
           break;
-        case GST_RM_AUD_xRA5:
-          audio_fourcc_offset = 66;
+        case 5:
+          stream->rate = RMDEMUX_GUINT16_GET (data + offset + 54);
+          stream->sample_width = RMDEMUX_GUINT16_GET (data + offset + 58);
+          stream->n_channels = RMDEMUX_GUINT16_GET (data + offset + 60);
+          stream->fourcc = RMDEMUX_FOURCC_GET (data + offset + 66);
+          stream->extra_data_size = RMDEMUX_GUINT32_GET (data + offset + 74);
+          stream->extra_data = (guint8 *) data + offset + 78;
           break;
-        default:
-          audio_fourcc_offset = 0;
-          GST_WARNING ("Unknown audio stream format");
       }
 
       /*  14_4, 28_8, cook, dnet, sipr, raac, racp, ralf, atrc */
-      stream->fourcc = RMDEMUX_FOURCC_GET (data + offset + audio_fourcc_offset);
+      GST_DEBUG_OBJECT (rmdemux,
+          "Audio stream with rate=%d sample_width=%d n_channels=%d",
+          stream->rate, stream->sample_width, stream->n_channels);
+
       break;
     }
     case GST_RMDEMUX_STREAM_FILEINFO:
@@ -831,11 +880,11 @@ gst_rmdemux_parse_mdpr (GstRMDemux * rmdemux, void *data, int length)
       int element_nb;
 
       /* Length of this section */
-      GST_DEBUG ("length2: 0x%08x", RMDEMUX_GUINT32_GET (data + offset));
+      GST_DEBUG_OBJECT (rmdemux, "length2: 0x%08x",
+          RMDEMUX_GUINT32_GET (data + offset));
       offset += 4;
 
       /* Unknown : 00 00 00 00 */
-      re_hexdump_bytes (data + offset, 4, offset);
       offset += 4;
 
       /* Number of variables that would follow (loop iterations) */
@@ -844,20 +893,18 @@ gst_rmdemux_parse_mdpr (GstRMDemux * rmdemux, void *data, int length)
 
       while (element_nb) {
         /* Category Id : 00 00 00 XX 00 00 */
-        re_hexdump_bytes (data + offset, 6, offset);
         offset += 6;
 
         /* Variable Name */
-        offset += re_dump_pascal_string (data + offset);
+        offset += re_skip_pascal_string (data + offset);
 
         /* Variable Value Type */
         /*   00 00 00 00 00 => integer/boolean, preceded by length */
         /*   00 00 00 02 00 => pascal string, preceded by length, no trailing \0 */
-        re_hexdump_bytes (data + offset, 5, offset);
         offset += 5;
 
         /* Variable Value */
-        offset += re_dump_pascal_string (data + offset);
+        offset += re_skip_pascal_string (data + offset);
 
         element_nb--;
       }
@@ -872,93 +919,7 @@ gst_rmdemux_parse_mdpr (GstRMDemux * rmdemux, void *data, int length)
 }
 
 static void
-gst_rmdemux_dump_mdpr (GstRMDemux * rmdemux, void *data, int length)
-{
-  int offset = 0;
-  char *stream_type;
-  guint32 fourcc;
-
-  GST_LOG ("version: %d", RMDEMUX_GUINT16_GET (data + 0));
-  GST_LOG ("stream id: %d", RMDEMUX_GUINT16_GET (data + 2));
-  GST_LOG ("max bitrate: %d", RMDEMUX_GUINT32_GET (data + 4));
-  GST_LOG ("avg bitrate: %d", RMDEMUX_GUINT32_GET (data + 8));
-  GST_LOG ("max packet size: %d", RMDEMUX_GUINT32_GET (data + 12));
-  GST_LOG ("avg packet size: %d", RMDEMUX_GUINT32_GET (data + 16));
-  GST_LOG ("start time: %d", RMDEMUX_GUINT32_GET (data + 20));
-  GST_LOG ("preroll: %d", RMDEMUX_GUINT32_GET (data + 24));
-  GST_LOG ("duration: %d", RMDEMUX_GUINT32_GET (data + 28));
-
-  offset = 32;
-  stream_type = re_get_pascal_string (data + offset);
-  offset += re_dump_pascal_string (data + offset);
-  offset += re_dump_pascal_string (data + offset);
-  GST_LOG ("length: 0x%08x", RMDEMUX_GUINT32_GET (data + offset));
-  offset += 4;
-
-  if (strstr (stream_type, "Video Stream")) {
-    GST_LOG ("unknown: 0x%08x", RMDEMUX_GUINT32_GET (data + offset + 0));
-    GST_LOG ("unknown: 0x%08x", RMDEMUX_GUINT32_GET (data + offset + 4));
-    fourcc = RMDEMUX_FOURCC_GET (data + offset + 8);
-    GST_LOG ("fourcc: " GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
-    GST_LOG ("width: %d", RMDEMUX_GUINT16_GET (data + offset + 12));
-    GST_LOG ("height: %d", RMDEMUX_GUINT16_GET (data + offset + 14));
-    GST_LOG ("rate: %d", RMDEMUX_GUINT16_GET (data + offset + 16));
-    GST_LOG ("subid: 0x%08x", RMDEMUX_GUINT32_GET (data + offset + 30));
-    offset += 18;
-  } else if (strstr (stream_type, "Audio Stream")) {
-    GST_LOG ("unknown: 0x%08x", RMDEMUX_GUINT32_GET (data + offset + 0));
-    GST_LOG ("unknown: 0x%08x", RMDEMUX_GUINT32_GET (data + offset + 4));
-    fourcc = RMDEMUX_FOURCC_GET (data + offset + 8);
-    GST_LOG ("fourcc: " GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
-    re_hexdump_bytes (data + offset + 12, 14, offset + 12);
-    GST_LOG ("packet size 1: %d", RMDEMUX_GUINT16_GET (data + offset + 26));
-    re_hexdump_bytes (data + offset + 28, 14, offset + 28);
-    GST_LOG ("packet size 2: %d", RMDEMUX_GUINT16_GET (data + offset + 42));
-    GST_LOG ("unknown: 0x%08x", RMDEMUX_GUINT32_GET (data + offset + 44));
-    GST_LOG ("rate1: %d", RMDEMUX_GUINT32_GET (data + offset + 48));
-    GST_LOG ("rate2: %d", RMDEMUX_GUINT32_GET (data + offset + 52));
-    offset += 56;
-  } else if (strcmp (stream_type, "") == 0) {
-
-    int element_nb;
-
-    /* Length of this section */
-    GST_LOG ("length2: 0x%08x", RMDEMUX_GUINT32_GET (data + offset));
-    offset += 4;
-
-    /* Unknown : 00 00 00 00 */
-    re_hexdump_bytes (data + offset, 4, offset);
-    offset += 4;
-
-    /* Number of variables that would follow (loop iterations) */
-    element_nb = RMDEMUX_GUINT32_GET (data + offset);
-    offset += 4;
-
-    while (element_nb) {
-      /* Category Id : 00 00 00 XX 00 00 */
-      re_hexdump_bytes (data + offset, 6, offset);
-      offset += 6;
-
-      /* Variable Name */
-      offset += re_dump_pascal_string (data + offset);
-
-      /* Variable Value Type */
-      /*   00 00 00 00 00 => integer/boolean, preceded by length */
-      /*   00 00 00 02 00 => pascal string, preceded by length, no trailing \0 */
-      re_hexdump_bytes (data + offset, 5, offset);
-      offset += 5;
-
-      /* Variable Value */
-      offset += re_dump_pascal_string (data + offset);
-
-      element_nb--;
-    }
-  }
-  re_hexdump_bytes (data + offset, length - offset, offset);
-}
-
-static void
-gst_rmdemux_parse_indx (GstRMDemux * rmdemux, void *data, int length)
+gst_rmdemux_parse_indx (GstRMDemux * rmdemux, const void *data, int length)
 {
   int offset;
   int n;
@@ -967,17 +928,18 @@ gst_rmdemux_parse_indx (GstRMDemux * rmdemux, void *data, int length)
   GstRMDemuxIndex *index;
   GstRMDemuxStream *stream;
 
-  n = RMDEMUX_GUINT16_GET (data + 4);
-  id = RMDEMUX_GUINT16_GET (data + 6);
+  n = RMDEMUX_GUINT32_GET (data);
+  id = RMDEMUX_GUINT16_GET (data + 4);
 
   stream = gst_rmdemux_get_stream_by_id (rmdemux, id);
-  g_return_if_fail (stream != NULL);
+  if (stream == NULL)
+    return;
 
   index = g_malloc (sizeof (GstRMDemuxIndex) * n);
   stream->index = index;
   stream->index_length = n;
 
-  offset = 12;
+  offset = 8;
   for (i = 0; i < n; i++) {
     index[i].unknown = RMDEMUX_GUINT16_GET (data + offset + 0);
     index[i].offset = RMDEMUX_GUINT32_GET (data + offset + 2);
@@ -990,69 +952,61 @@ gst_rmdemux_parse_indx (GstRMDemux * rmdemux, void *data, int length)
 }
 
 static void
-gst_rmdemux_dump_indx (GstRMDemux * rmdemux, void *data, int length)
+gst_rmdemux_parse_data (GstRMDemux * rmdemux, const void *data, int length)
 {
-  int offset = 0;
-  int n;
-  int i;
-
-  re_hexdump_bytes (data + 0, 4, 0);
-  n = RMDEMUX_GUINT16_GET (data + 4);
-  GST_LOG ("n_entries: %d, stream_id: %d, offset to next INDX: 0x%08x",
-      n, RMDEMUX_GUINT16_GET (data + 6), RMDEMUX_GUINT32_GET (data + 8));
-  offset = 12;
-  for (i = 0; i < n; i++) {
-    GST_DEBUG
-        ("unknown: 0x%04x, offset: 0x%08x, timestamp: %d, frame index: %d",
-        RMDEMUX_GUINT16_GET (data + offset + 0),
-        RMDEMUX_GUINT32_GET (data + offset + 2),
-        RMDEMUX_GUINT32_GET (data + offset + 6),
-        RMDEMUX_GUINT32_GET (data + offset + 10));
-    offset += 14;
-  }
+  rmdemux->n_chunks = RMDEMUX_GUINT32_GET (data);
+  rmdemux->chunk_index = 0;
+  GST_DEBUG_OBJECT (rmdemux, "Data chunk found with %d packets",
+      rmdemux->n_chunks);
 }
 
 static void
-gst_rmdemux_parse_data (GstRMDemux * rmdemux, void *data, int length)
+gst_rmdemux_parse_cont (GstRMDemux * rmdemux, const void *data, int length)
 {
-  rmdemux->n_chunks = RMDEMUX_GUINT32_GET (data + 2);
+  gchar *title = (gchar *) re_get_pascal_string (data);
+
+  GST_DEBUG_OBJECT (rmdemux, "File Content : (CONT) %s", title);
+  g_free (title);
 }
 
 static void
-gst_rmdemux_dump_data (GstRMDemux * rmdemux, void *data, int length)
+gst_rmdemux_parse_packet (GstRMDemux * rmdemux, const void *data,
+    guint16 version, guint16 length)
 {
-  int offset = 0;
-  int n;
+  guint16 id;
+  guint32 timestamp;
+  GstRMDemuxStream *stream;
+  GstBuffer *buffer;
+  guint16 packet_size;
+
+  id = RMDEMUX_GUINT16_GET (data);
+  timestamp = RMDEMUX_GUINT32_GET (data + 2);
+
+  GST_DEBUG_OBJECT (rmdemux, "Parsing a packet for stream %d timestamp %d", id,
+      timestamp);
 
-  GST_LOG ("version: %d, n_chunks: %d, unknown: 0x%08x",
-      RMDEMUX_GUINT16_GET (data + 0), RMDEMUX_GUINT32_GET (data + offset + 2),
-      RMDEMUX_GUINT32_GET (data + offset + 6));
-
-  re_hexdump_bytes (data + offset, 10, offset);
-  offset += 10;
-  while (offset < length) {
-    n = RMDEMUX_GUINT32_GET (data + offset);
-    GST_LOG ("length: %d, unknown: 0x%08x, unknown: %08x",
-        n, RMDEMUX_GUINT32_GET (data + offset + 4),
-        RMDEMUX_GUINT32_GET (data + offset + 8));
-    offset += 12;
-    re_hexdump_bytes (data + offset, n - 12, offset);
-    offset += n - 12;
+  if (version == 0) {
+    data += 8;
+    packet_size = length - 12;
+  } else {
+    data += 9;
+    packet_size = length - 13;
   }
-  g_print ("\n");
-}
 
-static void
-gst_rmdemux_parse_cont (GstRMDemux * rmdemux, void *data, int length)
-{
-  int offset = 0;
+  stream = gst_rmdemux_get_stream_by_id (rmdemux, id);
 
-  GST_DEBUG ("File Content : (CONT)");
-  offset += re_dump_pascal_string (data + offset + 3);
-}
+  if (gst_pad_alloc_buffer (stream->pad, GST_BUFFER_OFFSET_NONE,
+          packet_size, stream->caps, &buffer) != GST_FLOW_OK) {
+    GST_WARNING_OBJECT (rmdemux, "failed to alloc src buffer for stream %d",
+        id);
+    return;
+  }
 
-static void
-gst_rmdemux_dump_cont (GstRMDemux * rmdemux, void *data, int length)
-{
+  memcpy (GST_BUFFER_DATA (buffer), (guint8 *) data, packet_size);
+  GST_BUFFER_TIMESTAMP (buffer) = GST_SECOND * timestamp / 1000;
 
+  if (stream && stream->pad && GST_PAD_IS_USABLE (stream->pad)) {
+    GST_DEBUG_OBJECT (rmdemux, "Pushing buffer of size %d to pad", packet_size);
+    gst_pad_push (stream->pad, buffer);
+  }
 }
index 28d9755..aee0715 100644 (file)
@@ -22,7 +22,7 @@
 #define __GST_RMDEMUX_H__
 
 #include <gst/gst.h>
-#include <gst/bytestream/bytestream.h>
+#include <gst/base/gstadapter.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -57,7 +57,7 @@ struct _GstRMDemux {
   int n_video_streams;
   int n_audio_streams;
 
-  GstByteStream *bs;
+  GstAdapter *adapter;
 
   GNode *moov_node;
   GNode *moov_node_compressed;
@@ -75,6 +75,9 @@ struct _GstRMDemux {
 
   guint64 length;
 
+  guint32 object_id;
+  guint32 size;
+  guint16 object_version;
 };
 
 struct _GstRMDemuxClass {
@@ -92,7 +95,7 @@ struct _GstRMDemuxClass {
 #define GST_RM_AUD_28_8 GST_MAKE_FOURCC('2','8','_','8') // 28.8 Audio Codec
 #define GST_RM_AUD_COOK GST_MAKE_FOURCC('c','o','o','k') // Cooker G2 Audio Codec
 #define GST_RM_AUD_DNET GST_MAKE_FOURCC('d','n','e','t') // DolbyNet Audio Codec (low bitrate Dolby AC3)
-#define GST_RM_AUD_SIPR GST_MAKE_FOURCC('s','i','p','r') // Sipro/ACELP-NET Voice Codec
+#define GST_RM_AUD_SIPR GST_MAKE_FOURCC('s','i','p','r') // Sipro/ACELP.NET Voice Codec
 #define GST_RM_AUD_RAAC GST_MAKE_FOURCC('r','a','a','c') // LE-AAC Audio Codec
 #define GST_RM_AUD_RACP GST_MAKE_FOURCC('r','a','c','p') // HE-AAC Audio Codec
 #define GST_RM_AUD_RALF GST_MAKE_FOURCC('r','a','l','f') // RealAudio Lossless
@@ -101,29 +104,6 @@ struct _GstRMDemuxClass {
 #define GST_RM_AUD_xRA4 GST_MAKE_FOURCC('.','r','a','4') // Not a real audio codec
 #define GST_RM_AUD_xRA5 GST_MAKE_FOURCC('.','r','a','5') // Not a real audio codec
 
-/*
-
-enum GstRMVideoCodecs {
-  GST_RM_VDO_RV10,
-  GST_RM_VDO_RV20,
-  GST_RM_VDO_RV30,
-  GST_RM_VDO_RV40
-};
-
-enum GstRMAudioCodecs {
-  GST_RM_AUD_14_4,
-  GST_RM_AUD_28_8,
-  GST_RM_AUD_COOK,
-  GST_RM_AUD_DNET,
-  GST_RM_AUD_SIPR,
-  GST_RM_AUD_RAAC,
-  GST_RM_AUD_RACP,
-  GST_RM_AUD_RALF,
-  GST_RM_AUD_ATRC
-};
-
-*/
-
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */