* 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
*/
#ifdef HAVE_CONFIG_H
-#include "config.h"
+# include "config.h"
#endif
+
#include "rmdemux.h"
#include <string.h>
{
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
{
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
};
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);
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);
}
"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
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;
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 *
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
(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,
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;
}
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;
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;
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;
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);
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) {
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);
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:
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) */
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--;
}
}
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;
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);
}
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);
+ }
}