From: Owen Fraser-Green Date: Mon, 27 Jun 2005 09:16:09 +0000 (+0000) Subject: Rewrote to use gstadapter and extract properties from header packets to pass downstre... X-Git-Tag: 1.19.3~505^2~2354 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6482bb020bd93c324d16512447c18ef0ba1864d9;p=platform%2Fupstream%2Fgstreamer.git Rewrote to use gstadapter and extract properties from header packets to pass downstream to decoders. Original commit message from CVS: Rewrote to use gstadapter and extract properties from header packets to pass downstream to decoders. --- diff --git a/ChangeLog b/ChangeLog index af61341..76364bd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2005-06-27 Owen Fraser-Green + + * gst/realmedia/rmdemux.c: Rewrote to use gstadapter. Also parses + audio and video header packets for known properties. + 2005-06-23 Wim Taymans * gst/rtsp/gstrtspsrc.c: (gst_rtsp_proto_get_type), diff --git a/configure.ac b/configure.ac index 405c945..3b10028 100644 --- a/configure.ac +++ b/configure.ac @@ -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 diff --git a/gst/realmedia/Makefile.am b/gst/realmedia/Makefile.am index f4186a5..07c5aa8 100644 --- a/gst/realmedia/Makefile.am +++ b/gst/realmedia/Makefile.am @@ -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 diff --git a/gst/realmedia/rmdemux.c b/gst/realmedia/rmdemux.c index cbd2e26..1cc8bef 100644 --- a/gst/realmedia/rmdemux.c +++ b/gst/realmedia/rmdemux.c @@ -2,6 +2,7 @@ * Copyright (C) <1999> Erik Walthinsen * Copyright (C) <2003> David A. Schleef * Copyright (C) <2004> Stephane Loeuillet + * Copyright (C) <2005> Owen Fraser-Green * * 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 @@ -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); + } } diff --git a/gst/realmedia/rmdemux.h b/gst/realmedia/rmdemux.h index 28d9755..aee0715 100644 --- a/gst/realmedia/rmdemux.h +++ b/gst/realmedia/rmdemux.h @@ -22,7 +22,7 @@ #define __GST_RMDEMUX_H__ #include -#include +#include #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 */