gst/realmedia/rmdemux.c: Do fragment collection in the demuxer so that we can now...
[platform/upstream/gstreamer.git] / gst / realmedia / rmdemux.c
1 /* GStreamer RealMedia demuxer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2004> Stephane Loeuillet <gstreamer@leroutier.net>
5  * Copyright (C) <2005> Owen Fraser-Green <owen@discobabe.net>
6  * Copyright (C) <2005> Michael Smith <fluendo.com>
7  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
8  * Copyright (C) <2006> Tim-Philipp Müller <tim centricular net>
9  * Copyright (C) <2007> Wim Taymans <wim.taymans@gmail.com>
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Library General Public
13  * License as published by the Free Software Foundation; either
14  * version 2 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Library General Public License for more details.
20  *
21  * You should have received a copy of the GNU Library General Public
22  * License along with this library; if not, write to the
23  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24  * Boston, MA 02111-1307, USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 #  include "config.h"
29 #endif
30
31 #include "rmdemux.h"
32 #include "rdtdepay.h"
33 #include "rdtmanager.h"
34 #include "rtspreal.h"
35 #include "rmutils.h"
36 #include "rademux.h"
37
38 #include <string.h>
39 #include <ctype.h>
40
41 #define RMDEMUX_GUINT32_GET(a)  GST_READ_UINT32_BE(a)
42 #define RMDEMUX_GUINT16_GET(a)  GST_READ_UINT16_BE(a)
43 #define RMDEMUX_FOURCC_GET(a)   GST_READ_UINT32_LE(a)
44 #define HEADER_SIZE 10
45 #define DATA_SIZE 8
46
47 #define MAX_FRAGS 256
48
49 typedef struct _GstRMDemuxIndex GstRMDemuxIndex;
50
51 struct _GstRMDemuxStream
52 {
53   guint32 subtype;
54   guint32 fourcc;
55   guint32 subformat;
56   guint32 format;
57
58   int id;
59   GstPad *pad;
60   GstFlowReturn last_flow;
61   int timescale;
62
63   int sample_index;
64   GstRMDemuxIndex *index;
65   int index_length;
66   gint framerate_numerator;
67   gint framerate_denominator;
68   guint32 seek_offset;
69
70   guint16 width;
71   guint16 height;
72   guint16 flavor;
73   guint16 rate;                 /* samplerate         */
74   guint16 n_channels;           /* channels           */
75   guint16 sample_width;         /* bits_per_sample    */
76   guint16 leaf_size;            /* subpacket_size     */
77   guint32 packet_size;          /* coded_frame_size   */
78   guint16 version;
79   guint32 extra_data_size;      /* codec_data_length  */
80   guint8 *extra_data;           /* extras             */
81
82   gboolean needs_descrambling;
83   guint subpackets_needed;      /* subpackets needed for descrambling    */
84   GPtrArray *subpackets;        /* array containing subpacket GstBuffers */
85
86   gint frag_seqnum;
87   gint frag_subseq;
88   guint frag_length;
89   guint frag_current;
90   guint frag_count;
91   guint frag_offset[MAX_FRAGS];
92   GstAdapter *adapter;
93
94   GstTagList *pending_tags;
95 };
96
97 struct _GstRMDemuxIndex
98 {
99   guint32 offset;
100   GstClockTime timestamp;
101 };
102
103 static GstElementDetails gst_rmdemux_details = {
104   "RealMedia Demuxer",
105   "Codec/Demuxer",
106   "Demultiplex a RealMedia file into audio and video streams",
107   "David Schleef <ds@schleef.org>"
108 };
109
110 static GstStaticPadTemplate gst_rmdemux_sink_template =
111 GST_STATIC_PAD_TEMPLATE ("sink",
112     GST_PAD_SINK,
113     GST_PAD_ALWAYS,
114     GST_STATIC_CAPS ("application/vnd.rn-realmedia")
115     );
116
117 static GstStaticPadTemplate gst_rmdemux_videosrc_template =
118 GST_STATIC_PAD_TEMPLATE ("video_%02d",
119     GST_PAD_SRC,
120     GST_PAD_SOMETIMES,
121     GST_STATIC_CAPS_ANY);
122
123 static GstStaticPadTemplate gst_rmdemux_audiosrc_template =
124 GST_STATIC_PAD_TEMPLATE ("audio_%02d",
125     GST_PAD_SRC,
126     GST_PAD_SOMETIMES,
127     GST_STATIC_CAPS_ANY);
128
129 GST_DEBUG_CATEGORY_STATIC (rmdemux_debug);
130 #define GST_CAT_DEFAULT rmdemux_debug
131
132 static GstElementClass *parent_class = NULL;
133
134 static void gst_rmdemux_class_init (GstRMDemuxClass * klass);
135 static void gst_rmdemux_base_init (GstRMDemuxClass * klass);
136 static void gst_rmdemux_init (GstRMDemux * rmdemux);
137 static void gst_rmdemux_finalize (GObject * object);
138 static GstStateChangeReturn gst_rmdemux_change_state (GstElement * element,
139     GstStateChange transition);
140 static GstFlowReturn gst_rmdemux_chain (GstPad * pad, GstBuffer * buffer);
141 static void gst_rmdemux_loop (GstPad * pad);
142 static gboolean gst_rmdemux_sink_activate (GstPad * sinkpad);
143 static gboolean gst_rmdemux_sink_activate_push (GstPad * sinkpad,
144     gboolean active);
145 static gboolean gst_rmdemux_sink_activate_pull (GstPad * sinkpad,
146     gboolean active);
147 static gboolean gst_rmdemux_sink_event (GstPad * pad, GstEvent * event);
148 static gboolean gst_rmdemux_src_event (GstPad * pad, GstEvent * event);
149 static void gst_rmdemux_send_event (GstRMDemux * rmdemux, GstEvent * event);
150 static const GstQueryType *gst_rmdemux_src_query_types (GstPad * pad);
151 static gboolean gst_rmdemux_src_query (GstPad * pad, GstQuery * query);
152 static gboolean gst_rmdemux_perform_seek (GstRMDemux * rmdemux,
153     GstEvent * event);
154
155 static void gst_rmdemux_parse__rmf (GstRMDemux * rmdemux, const guint8 * data,
156     int length);
157 static void gst_rmdemux_parse_prop (GstRMDemux * rmdemux, const guint8 * data,
158     int length);
159 static void gst_rmdemux_parse_mdpr (GstRMDemux * rmdemux,
160     const guint8 * data, int length);
161 static guint gst_rmdemux_parse_indx (GstRMDemux * rmdemux, const guint8 * data,
162     int length);
163 static void gst_rmdemux_parse_data (GstRMDemux * rmdemux, const guint8 * data,
164     int length);
165 static void gst_rmdemux_parse_cont (GstRMDemux * rmdemux, const guint8 * data,
166     int length);
167 static GstFlowReturn gst_rmdemux_parse_packet (GstRMDemux * rmdemux,
168     GstBuffer * in, guint16 version);
169 static void gst_rmdemux_parse_indx_data (GstRMDemux * rmdemux,
170     const guint8 * data, int length);
171 static void gst_rmdemux_stream_clear_cached_subpackets (GstRMDemux * rmdemux,
172     GstRMDemuxStream * stream);
173 static GstRMDemuxStream *gst_rmdemux_get_stream_by_id (GstRMDemux * rmdemux,
174     int id);
175
176 static GType
177 gst_rmdemux_get_type (void)
178 {
179   static GType rmdemux_type = 0;
180
181   if (!rmdemux_type) {
182     static const GTypeInfo rmdemux_info = {
183       sizeof (GstRMDemuxClass),
184       (GBaseInitFunc) gst_rmdemux_base_init, NULL,
185       (GClassInitFunc) gst_rmdemux_class_init,
186       NULL, NULL, sizeof (GstRMDemux), 0,
187       (GInstanceInitFunc) gst_rmdemux_init,
188     };
189
190     rmdemux_type =
191         g_type_register_static (GST_TYPE_ELEMENT, "GstRMDemux", &rmdemux_info,
192         0);
193   }
194   return rmdemux_type;
195 }
196
197 static void
198 gst_rmdemux_base_init (GstRMDemuxClass * klass)
199 {
200   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
201
202   gst_element_class_add_pad_template (element_class,
203       gst_static_pad_template_get (&gst_rmdemux_sink_template));
204   gst_element_class_add_pad_template (element_class,
205       gst_static_pad_template_get (&gst_rmdemux_videosrc_template));
206   gst_element_class_add_pad_template (element_class,
207       gst_static_pad_template_get (&gst_rmdemux_audiosrc_template));
208   gst_element_class_set_details (element_class, &gst_rmdemux_details);
209 }
210
211 static void
212 gst_rmdemux_class_init (GstRMDemuxClass * klass)
213 {
214   GObjectClass *gobject_class;
215   GstElementClass *gstelement_class;
216
217   gobject_class = (GObjectClass *) klass;
218   gstelement_class = (GstElementClass *) klass;
219
220   parent_class = g_type_class_peek_parent (klass);
221
222   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_rmdemux_change_state);
223
224   GST_DEBUG_CATEGORY_INIT (rmdemux_debug, "rmdemux",
225       0, "Demuxer for Realmedia streams");
226
227   gobject_class->finalize = gst_rmdemux_finalize;
228 }
229
230 static void
231 gst_rmdemux_finalize (GObject * object)
232 {
233   GstRMDemux *rmdemux = GST_RMDEMUX (object);
234
235   if (rmdemux->adapter) {
236     g_object_unref (rmdemux->adapter);
237     rmdemux->adapter = NULL;
238   }
239
240   GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
241 }
242
243 static void
244 gst_rmdemux_init (GstRMDemux * rmdemux)
245 {
246   rmdemux->sinkpad =
247       gst_pad_new_from_static_template (&gst_rmdemux_sink_template, "sink");
248   gst_pad_set_event_function (rmdemux->sinkpad,
249       GST_DEBUG_FUNCPTR (gst_rmdemux_sink_event));
250   gst_pad_set_chain_function (rmdemux->sinkpad,
251       GST_DEBUG_FUNCPTR (gst_rmdemux_chain));
252   gst_pad_set_activate_function (rmdemux->sinkpad,
253       GST_DEBUG_FUNCPTR (gst_rmdemux_sink_activate));
254   gst_pad_set_activatepull_function (rmdemux->sinkpad,
255       GST_DEBUG_FUNCPTR (gst_rmdemux_sink_activate_pull));
256   gst_pad_set_activatepush_function (rmdemux->sinkpad,
257       GST_DEBUG_FUNCPTR (gst_rmdemux_sink_activate_push));
258
259   gst_element_add_pad (GST_ELEMENT (rmdemux), rmdemux->sinkpad);
260
261   rmdemux->adapter = gst_adapter_new ();
262   rmdemux->first_ts = GST_CLOCK_TIME_NONE;
263   rmdemux->need_newsegment = TRUE;
264 }
265
266 static gboolean
267 gst_rmdemux_sink_event (GstPad * pad, GstEvent * event)
268 {
269   GstRMDemux *rmdemux;
270   gboolean ret;
271
272   rmdemux = GST_RMDEMUX (gst_pad_get_parent (pad));
273
274   GST_LOG_OBJECT (pad, "%s event", GST_EVENT_TYPE_NAME (event));
275
276   switch (GST_EVENT_TYPE (event)) {
277     case GST_EVENT_NEWSEGMENT:
278       gst_event_unref (event);
279       ret = TRUE;
280       break;
281     default:
282       ret = gst_pad_event_default (pad, event);
283       break;
284   }
285
286   gst_object_unref (rmdemux);
287   return ret;
288 }
289
290 static gboolean
291 gst_rmdemux_src_event (GstPad * pad, GstEvent * event)
292 {
293   gboolean ret = TRUE;
294
295   GstRMDemux *rmdemux = GST_RMDEMUX (GST_PAD_PARENT (pad));
296
297   GST_LOG_OBJECT (rmdemux, "handling src event");
298
299   switch (GST_EVENT_TYPE (event)) {
300     case GST_EVENT_SEEK:
301     {
302       gboolean running;
303
304       GST_LOG_OBJECT (rmdemux, "Event on src: SEEK");
305       /* can't seek if we are not seekable, FIXME could pass the
306        * seek query upstream after converting it to bytes using
307        * the average bitrate of the stream. */
308       if (!rmdemux->seekable) {
309         ret = FALSE;
310         GST_DEBUG ("seek on non seekable stream");
311         goto done_unref;
312       }
313
314       GST_OBJECT_LOCK (rmdemux);
315       /* check if we can do the seek now */
316       running = rmdemux->running;
317       GST_OBJECT_UNLOCK (rmdemux);
318
319       /* now do the seek */
320       if (running) {
321         ret = gst_rmdemux_perform_seek (rmdemux, event);
322       } else
323         ret = TRUE;
324
325       gst_event_unref (event);
326       break;
327     }
328     default:
329       GST_LOG_OBJECT (rmdemux, "Event on src: type=%d", GST_EVENT_TYPE (event));
330       ret = gst_pad_event_default (pad, event);
331       break;
332   }
333
334   return ret;
335
336 done_unref:
337   GST_DEBUG ("error handling event");
338   gst_event_unref (event);
339   return ret;
340 }
341
342 /* Validate that this looks like a reasonable point to seek to */
343 static gboolean
344 gst_rmdemux_validate_offset (GstRMDemux * rmdemux)
345 {
346   GstBuffer *buffer;
347   GstFlowReturn flowret;
348   guint16 version, length;
349   gboolean ret = TRUE;
350
351   flowret = gst_pad_pull_range (rmdemux->sinkpad, rmdemux->offset, 4, &buffer);
352
353   if (flowret != GST_FLOW_OK) {
354     GST_DEBUG_OBJECT (rmdemux, "Failed to pull data at offset %d",
355         rmdemux->offset);
356     return FALSE;
357   }
358   /* TODO: Can we also be seeking to a 'DATA' chunk header? Check this.
359    * Also, for the case we currently handle, can we check any more? It's pretty
360    * sucky to not be validating a little more heavily than this... */
361   /* This should now be the start of a data packet header. That begins with
362    * a 2-byte 'version' field, which has to be 0 or 1, then a length. I'm not
363    * certain what values are valid for length, but it must always be at least
364    * 4 bytes, and we can check that it won't take us past our known total size
365    */
366
367   version = RMDEMUX_GUINT16_GET (GST_BUFFER_DATA (buffer));
368   if (version != 0 && version != 1) {
369     GST_DEBUG_OBJECT (rmdemux, "Expected version 0 or 1, got %d",
370         (int) version);
371     ret = FALSE;
372   }
373
374   length = RMDEMUX_GUINT16_GET (GST_BUFFER_DATA (buffer) + 2);
375   /* TODO: Also check against total stream length */
376   if (length < 4) {
377     GST_DEBUG_OBJECT (rmdemux, "Expected length >= 4, got %d", (int) length);
378     ret = FALSE;
379   }
380
381   if (ret) {
382     rmdemux->offset += 4;
383     gst_adapter_clear (rmdemux->adapter);
384     gst_adapter_push (rmdemux->adapter, buffer);
385   } else {
386     GST_WARNING_OBJECT (rmdemux, "Failed to validate seek offset at %d",
387         rmdemux->offset);
388   }
389
390   return ret;
391 }
392
393 static gboolean
394 find_seek_offset_bytes (GstRMDemux * rmdemux, guint target)
395 {
396   int i;
397   GSList *cur;
398   gboolean ret = FALSE;
399
400   if (target < 0)
401     return FALSE;
402
403   for (cur = rmdemux->streams; cur; cur = cur->next) {
404     GstRMDemuxStream *stream = cur->data;
405
406     /* Search backwards through this stream's index until we find the first
407      * timestamp before our target time */
408     for (i = stream->index_length - 1; i >= 0; i--) {
409       if (stream->index[i].offset <= target) {
410         /* Set the seek_offset for the stream so we don't bother parsing it
411          * until we've passed that point */
412         stream->seek_offset = stream->index[i].offset;
413         rmdemux->offset = stream->index[i].offset;
414         ret = TRUE;
415         break;
416       }
417     }
418   }
419   return ret;
420 }
421
422 static gboolean
423 find_seek_offset_time (GstRMDemux * rmdemux, GstClockTime time)
424 {
425   int i, n_stream;
426   gboolean ret = FALSE;
427   GSList *cur;
428   GstClockTime earliest = GST_CLOCK_TIME_NONE;
429
430   n_stream = 0;
431   for (cur = rmdemux->streams; cur; cur = cur->next, n_stream++) {
432     GstRMDemuxStream *stream = cur->data;
433
434     /* Search backwards through this stream's index until we find the first
435      * timestamp before our target time */
436     for (i = stream->index_length - 1; i >= 0; i--) {
437       if (stream->index[i].timestamp <= time) {
438         /* Set the seek_offset for the stream so we don't bother parsing it
439          * until we've passed that point */
440         stream->seek_offset = stream->index[i].offset;
441
442         /* If it's also the earliest timestamp we've seen of all streams, then
443          * that's our target!
444          */
445         if (earliest == GST_CLOCK_TIME_NONE ||
446             stream->index[i].timestamp < earliest) {
447           earliest = stream->index[i].timestamp;
448           rmdemux->offset = stream->index[i].offset;
449           GST_DEBUG_OBJECT (rmdemux,
450               "We're looking for %" GST_TIME_FORMAT
451               " and we found that stream %d has the latest index at %"
452               GST_TIME_FORMAT, GST_TIME_ARGS (rmdemux->segment.start), n_stream,
453               GST_TIME_ARGS (earliest));
454         }
455
456         ret = TRUE;
457
458         break;
459       }
460     }
461   }
462   return ret;
463 }
464
465 static gboolean
466 gst_rmdemux_perform_seek (GstRMDemux * rmdemux, GstEvent * event)
467 {
468   gboolean validated;
469   gboolean ret = TRUE;
470   gboolean flush, accurate;
471   GstFormat format;
472   gdouble rate;
473   GstSeekFlags flags;
474   GstSeekType cur_type, stop_type;
475   gint64 cur, stop;
476   gboolean update;
477
478   if (event) {
479     GST_DEBUG_OBJECT (rmdemux, "seek with event");
480
481     gst_event_parse_seek (event, &rate, &format, &flags,
482         &cur_type, &cur, &stop_type, &stop);
483
484     /* we can only seek on time */
485     if (format != GST_FORMAT_TIME) {
486       GST_DEBUG_OBJECT (rmdemux, "can only seek on TIME");
487       goto error;
488     }
489     /* cannot yet do backwards playback */
490     if (rate <= 0.0) {
491       GST_DEBUG_OBJECT (rmdemux, "can only seek with positive rate, not %lf",
492           rate);
493       goto error;
494     }
495   } else {
496     GST_DEBUG_OBJECT (rmdemux, "seek without event");
497
498     flags = 0;
499     rate = 1.0;
500   }
501
502   GST_DEBUG_OBJECT (rmdemux, "seek, rate %g", rate);
503
504   flush = flags & GST_SEEK_FLAG_FLUSH;
505   accurate = flags & GST_SEEK_FLAG_ACCURATE;
506
507   /* first step is to unlock the streaming thread if it is
508    * blocked in a chain call, we do this by starting the flush. */
509   if (flush) {
510     gst_pad_push_event (rmdemux->sinkpad, gst_event_new_flush_start ());
511     gst_rmdemux_send_event (rmdemux, gst_event_new_flush_start ());
512   } else {
513     gst_pad_pause_task (rmdemux->sinkpad);
514   }
515
516   GST_LOG_OBJECT (rmdemux, "Done starting flushes");
517
518   /* now grab the stream lock so that streaming cannot continue, for
519    * non flushing seeks when the element is in PAUSED this could block
520    * forever. */
521   GST_PAD_STREAM_LOCK (rmdemux->sinkpad);
522
523   GST_LOG_OBJECT (rmdemux, "Took streamlock");
524
525   /* close current segment first */
526   if (rmdemux->segment_running && !flush) {
527     GstEvent *newseg;
528
529     newseg = gst_event_new_new_segment (TRUE, rmdemux->segment.rate,
530         GST_FORMAT_TIME, rmdemux->segment.start,
531         rmdemux->segment.last_stop, rmdemux->segment.time);
532
533     gst_rmdemux_send_event (rmdemux, newseg);
534   }
535
536   if (event) {
537     gst_segment_set_seek (&rmdemux->segment, rate, format, flags,
538         cur_type, cur, stop_type, stop, &update);
539   }
540
541   GST_DEBUG_OBJECT (rmdemux, "segment positions set to %" GST_TIME_FORMAT "-%"
542       GST_TIME_FORMAT, GST_TIME_ARGS (rmdemux->segment.start),
543       GST_TIME_ARGS (rmdemux->segment.stop));
544
545   /* we need to stop flushing on the sinkpad as we're going to use it
546    * next. We can do this as we have the STREAM lock now. */
547   gst_pad_push_event (rmdemux->sinkpad, gst_event_new_flush_stop ());
548
549   GST_LOG_OBJECT (rmdemux, "Pushed FLUSH_STOP event");
550
551   /* For each stream, find the first index offset equal to or before our seek 
552    * target. Of these, find the smallest offset. That's where we seek to.
553    *
554    * Then we pull 4 bytes from that offset, and validate that we've seeked to a
555    * what looks like a plausible packet.
556    * If that fails, restart, with the seek target set to one less than the
557    * offset we just tried. If we run out of places to try, treat that as a fatal
558    * error.
559    */
560   if (!find_seek_offset_time (rmdemux, rmdemux->segment.last_stop)) {
561     GST_LOG_OBJECT (rmdemux, "Failed to find seek offset by time");
562     ret = FALSE;
563     goto done;
564   }
565
566   GST_LOG_OBJECT (rmdemux, "Validating offset %u", rmdemux->offset);
567   validated = gst_rmdemux_validate_offset (rmdemux);
568   while (!validated) {
569     GST_INFO_OBJECT (rmdemux, "Failed to validate offset at %u",
570         rmdemux->offset);
571     if (!find_seek_offset_bytes (rmdemux, rmdemux->offset - 1)) {
572       ret = FALSE;
573       goto done;
574     }
575     validated = gst_rmdemux_validate_offset (rmdemux);
576   }
577
578   GST_LOG_OBJECT (rmdemux, "Found final offset. Excellent!");
579
580   /* now we have a new position, prepare for streaming again */
581   {
582     /* Reset the demuxer state */
583     rmdemux->state = RMDEMUX_STATE_DATA_PACKET;
584
585     if (flush)
586       gst_rmdemux_send_event (rmdemux, gst_event_new_flush_stop ());
587
588     /* must send newsegment event from streaming thread, so just set flag */
589     rmdemux->need_newsegment = TRUE;
590
591     /* notify start of new segment */
592     if (rmdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
593       gst_element_post_message (GST_ELEMENT_CAST (rmdemux),
594           gst_message_new_segment_start (GST_OBJECT_CAST (rmdemux),
595               GST_FORMAT_TIME, rmdemux->segment.last_stop));
596     }
597
598     /* restart our task since it might have been stopped when we did the 
599      * flush. */
600     gst_pad_start_task (rmdemux->sinkpad, (GstTaskFunction) gst_rmdemux_loop,
601         rmdemux->sinkpad);
602   }
603
604 done:
605   /* streaming can continue now */
606   GST_PAD_STREAM_UNLOCK (rmdemux->sinkpad);
607
608   return TRUE;
609
610 error:
611   {
612     GST_DEBUG_OBJECT (rmdemux, "seek failed");
613     return FALSE;
614   }
615 }
616
617
618 static gboolean
619 gst_rmdemux_src_query (GstPad * pad, GstQuery * query)
620 {
621   gboolean res = FALSE;
622   GstRMDemux *rmdemux;
623
624   rmdemux = GST_RMDEMUX (gst_pad_get_parent (pad));
625
626   switch (GST_QUERY_TYPE (query)) {
627     case GST_QUERY_POSITION:
628       GST_DEBUG_OBJECT (rmdemux, "Position query: no idea from demuxer!");
629       break;
630     case GST_QUERY_DURATION:{
631       GstFormat fmt;
632
633       gst_query_parse_duration (query, &fmt, NULL);
634       if (fmt == GST_FORMAT_TIME) {
635         GST_OBJECT_LOCK (rmdemux);
636         if (G_LIKELY (rmdemux->running)) {
637           gst_query_set_duration (query, GST_FORMAT_TIME, rmdemux->duration);
638           GST_DEBUG_OBJECT (rmdemux, "duration set to %" GST_TIME_FORMAT,
639               GST_TIME_ARGS (rmdemux->duration));
640           res = TRUE;
641         }
642         GST_OBJECT_UNLOCK (rmdemux);
643       }
644       break;
645     }
646     case GST_QUERY_SEEKING:{
647       GstFormat fmt;
648
649       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
650       if (fmt == GST_FORMAT_TIME) {
651         GST_OBJECT_LOCK (rmdemux);
652         if (G_LIKELY (rmdemux->running)) {
653           gst_query_set_seeking (query, GST_FORMAT_TIME, rmdemux->seekable,
654               0, rmdemux->duration);
655           res = TRUE;
656         }
657         GST_OBJECT_UNLOCK (rmdemux);
658       }
659       break;
660     }
661     default:
662       res = gst_pad_query_default (pad, query);
663       break;
664   }
665
666   gst_object_unref (rmdemux);
667   return res;
668 }
669
670 static const GstQueryType *
671 gst_rmdemux_src_query_types (GstPad * pad)
672 {
673   static const GstQueryType query_types[] = {
674     GST_QUERY_POSITION,
675     GST_QUERY_DURATION,
676     GST_QUERY_SEEKING,
677     0
678   };
679
680   return query_types;
681 }
682
683 static void
684 gst_rmdemux_reset (GstRMDemux * rmdemux)
685 {
686   GSList *cur;
687
688   GST_OBJECT_LOCK (rmdemux);
689   rmdemux->running = FALSE;
690   GST_OBJECT_UNLOCK (rmdemux);
691
692   for (cur = rmdemux->streams; cur; cur = cur->next) {
693     GstRMDemuxStream *stream = cur->data;
694
695     g_object_unref (stream->adapter);
696     gst_rmdemux_stream_clear_cached_subpackets (rmdemux, stream);
697     gst_element_remove_pad (GST_ELEMENT (rmdemux), stream->pad);
698     if (stream->pending_tags)
699       gst_tag_list_free (stream->pending_tags);
700     if (stream->subpackets)
701       g_ptr_array_free (stream->subpackets, TRUE);
702     g_free (stream->index);
703     g_free (stream);
704   }
705   g_slist_free (rmdemux->streams);
706   rmdemux->streams = NULL;
707   rmdemux->n_audio_streams = 0;
708   rmdemux->n_video_streams = 0;
709
710   gst_adapter_clear (rmdemux->adapter);
711   rmdemux->state = RMDEMUX_STATE_HEADER;
712   rmdemux->have_pads = FALSE;
713
714   gst_segment_init (&rmdemux->segment, GST_FORMAT_UNDEFINED);
715   rmdemux->first_ts = GST_CLOCK_TIME_NONE;
716   rmdemux->need_newsegment = TRUE;
717 }
718
719 static GstStateChangeReturn
720 gst_rmdemux_change_state (GstElement * element, GstStateChange transition)
721 {
722   GstRMDemux *rmdemux = GST_RMDEMUX (element);
723   GstStateChangeReturn res;
724
725   switch (transition) {
726     case GST_STATE_CHANGE_NULL_TO_READY:
727       break;
728     case GST_STATE_CHANGE_READY_TO_PAUSED:
729       rmdemux->state = RMDEMUX_STATE_HEADER;
730       rmdemux->have_pads = FALSE;
731       gst_segment_init (&rmdemux->segment, GST_FORMAT_TIME);
732       rmdemux->running = FALSE;
733       break;
734     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
735       break;
736     default:
737       break;
738   }
739
740   res = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
741
742   switch (transition) {
743     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
744       break;
745     case GST_STATE_CHANGE_PAUSED_TO_READY:{
746       gst_rmdemux_reset (rmdemux);
747       break;
748     }
749     case GST_STATE_CHANGE_READY_TO_NULL:
750       break;
751     default:
752       break;
753   }
754
755   return res;
756 }
757
758 /* this function is called when the pad is activated and should start
759  * processing data.
760  *
761  * We check if we can do random access to decide if we work push or
762  * pull based.
763  */
764 static gboolean
765 gst_rmdemux_sink_activate (GstPad * sinkpad)
766 {
767   if (gst_pad_check_pull_range (sinkpad)) {
768     return gst_pad_activate_pull (sinkpad, TRUE);
769   } else {
770     return gst_pad_activate_push (sinkpad, TRUE);
771   }
772 }
773
774 /* this function gets called when we activate ourselves in push mode.
775  * We cannot seek (ourselves) in the stream */
776 static gboolean
777 gst_rmdemux_sink_activate_push (GstPad * pad, gboolean active)
778 {
779   GstRMDemux *rmdemux;
780
781   rmdemux = GST_RMDEMUX (GST_PAD_PARENT (pad));
782
783   GST_DEBUG_OBJECT (rmdemux, "activate_push");
784
785   rmdemux->seekable = FALSE;
786
787   return TRUE;
788 }
789
790 /* this function gets called when we activate ourselves in pull mode.
791  * We can perform  random access to the resource and we start a task
792  * to start reading */
793 static gboolean
794 gst_rmdemux_sink_activate_pull (GstPad * pad, gboolean active)
795 {
796   GstRMDemux *rmdemux;
797
798   rmdemux = GST_RMDEMUX (GST_PAD_PARENT (pad));
799
800   GST_DEBUG_OBJECT (rmdemux, "activate_pull");
801
802   if (active) {
803     rmdemux->seekable = TRUE;
804     rmdemux->offset = 0;
805     rmdemux->loop_state = RMDEMUX_LOOP_STATE_HEADER;
806     rmdemux->data_offset = G_MAXUINT;
807
808     return gst_pad_start_task (pad, (GstTaskFunction) gst_rmdemux_loop, pad);
809   } else {
810     return gst_pad_stop_task (pad);
811   }
812 }
813
814 /* random access mode - just pass over to our chain function */
815 static void
816 gst_rmdemux_loop (GstPad * pad)
817 {
818   GstRMDemux *rmdemux;
819   GstBuffer *buffer;
820   GstFlowReturn ret = GST_FLOW_OK;
821   guint size;
822
823   rmdemux = GST_RMDEMUX (GST_PAD_PARENT (pad));
824
825   GST_LOG_OBJECT (rmdemux, "loop with state=%d and offset=0x%x",
826       rmdemux->loop_state, rmdemux->offset);
827
828   switch (rmdemux->state) {
829     case RMDEMUX_STATE_HEADER:
830       size = HEADER_SIZE;
831       break;
832     case RMDEMUX_STATE_HEADER_DATA:
833       size = DATA_SIZE;
834       break;
835     case RMDEMUX_STATE_DATA_PACKET:
836       size = rmdemux->avg_packet_size;
837       break;
838     case RMDEMUX_STATE_EOS:
839       GST_LOG_OBJECT (rmdemux, "At EOS, pausing task");
840       ret = GST_FLOW_UNEXPECTED;
841       goto need_pause;
842     default:
843       GST_LOG_OBJECT (rmdemux, "Default: requires %d bytes (state is %d)",
844           (int) rmdemux->size, rmdemux->state);
845       size = rmdemux->size;
846   }
847
848   ret = gst_pad_pull_range (pad, rmdemux->offset, size, &buffer);
849   if (ret != GST_FLOW_OK) {
850     if (rmdemux->offset == rmdemux->index_offset) {
851       /* The index isn't available so forget about it */
852       rmdemux->loop_state = RMDEMUX_LOOP_STATE_DATA;
853       rmdemux->offset = rmdemux->data_offset;
854       GST_OBJECT_LOCK (rmdemux);
855       rmdemux->running = TRUE;
856       rmdemux->seekable = FALSE;
857       GST_OBJECT_UNLOCK (rmdemux);
858       return;
859     } else {
860       GST_DEBUG_OBJECT (rmdemux, "Unable to pull %d bytes at offset 0x%08x "
861           "(pull_range returned flow %s, state is %d)", (gint) size,
862           rmdemux->offset, gst_flow_get_name (ret), GST_STATE (rmdemux));
863       goto need_pause;
864     }
865   }
866
867   size = GST_BUFFER_SIZE (buffer);
868
869   /* Defer to the chain function */
870   ret = gst_rmdemux_chain (pad, buffer);
871   if (ret != GST_FLOW_OK) {
872     GST_DEBUG_OBJECT (rmdemux, "Chain flow failed at offset 0x%08x",
873         rmdemux->offset);
874     goto need_pause;
875   }
876
877   rmdemux->offset += size;
878
879   switch (rmdemux->loop_state) {
880     case RMDEMUX_LOOP_STATE_HEADER:
881       if (rmdemux->offset >= rmdemux->data_offset) {
882         /* It's the end of the header */
883         rmdemux->loop_state = RMDEMUX_LOOP_STATE_INDEX;
884         rmdemux->offset = rmdemux->index_offset;
885       }
886       break;
887     case RMDEMUX_LOOP_STATE_INDEX:
888       if (rmdemux->state == RMDEMUX_STATE_HEADER) {
889         if (rmdemux->index_offset == 0) {
890           /* We've read the last index */
891           rmdemux->loop_state = RMDEMUX_LOOP_STATE_DATA;
892           rmdemux->offset = rmdemux->data_offset;
893           GST_OBJECT_LOCK (rmdemux);
894           rmdemux->running = TRUE;
895           GST_OBJECT_UNLOCK (rmdemux);
896         } else {
897           /* Get the next index */
898           rmdemux->offset = rmdemux->index_offset;
899         }
900       }
901       break;
902     case RMDEMUX_LOOP_STATE_DATA:
903       break;
904   }
905
906   return;
907
908   /* ERRORS */
909 need_pause:
910   {
911     const gchar *reason = gst_flow_get_name (ret);
912
913     GST_LOG_OBJECT (rmdemux, "pausing task, reason %s", reason);
914     rmdemux->segment_running = FALSE;
915     gst_pad_pause_task (rmdemux->sinkpad);
916
917     if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) {
918       if (ret == GST_FLOW_UNEXPECTED) {
919         /* perform EOS logic */
920         if (rmdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
921           gint64 stop;
922
923           /* for segment playback we need to post when (in stream time)
924            * we stopped, this is either stop (when set) or the duration. */
925           if ((stop = rmdemux->segment.stop) == -1)
926             stop = rmdemux->segment.duration;
927
928           GST_LOG_OBJECT (rmdemux, "Sending segment done, at end of segment");
929           gst_element_post_message (GST_ELEMENT (rmdemux),
930               gst_message_new_segment_done (GST_OBJECT (rmdemux),
931                   GST_FORMAT_TIME, stop));
932         } else {
933           /* normal playback, send EOS to all linked pads */
934           GST_LOG_OBJECT (rmdemux, "Sending EOS, at end of stream");
935           gst_rmdemux_send_event (rmdemux, gst_event_new_eos ());
936         }
937       } else {
938         GST_ELEMENT_ERROR (rmdemux, STREAM, FAILED,
939             (NULL), ("stream stopped, reason %s", reason));
940         gst_rmdemux_send_event (rmdemux, gst_event_new_eos ());
941       }
942     }
943     return;
944   }
945 }
946
947 static gboolean
948 gst_rmdemux_fourcc_isplausible (guint32 fourcc)
949 {
950   int i;
951
952   for (i = 0; i < 4; i++) {
953     if (!isprint ((int) ((unsigned char *) (&fourcc))[i])) {
954       return FALSE;
955     }
956   }
957   return TRUE;
958 }
959
960 static GstFlowReturn
961 gst_rmdemux_chain (GstPad * pad, GstBuffer * buffer)
962 {
963   GstFlowReturn ret = GST_FLOW_OK;
964   const guint8 *data;
965   guint16 version;
966   guint avail;
967
968   GstRMDemux *rmdemux = GST_RMDEMUX (GST_PAD_PARENT (pad));
969
970   gst_adapter_push (rmdemux->adapter, buffer);
971
972   GST_LOG_OBJECT (rmdemux, "Chaining buffer of size %d",
973       GST_BUFFER_SIZE (buffer));
974
975   while (TRUE) {
976     avail = gst_adapter_available (rmdemux->adapter);
977
978     GST_LOG_OBJECT (rmdemux, "looping in chain, avail %u", avail);
979     switch (rmdemux->state) {
980       case RMDEMUX_STATE_HEADER:
981       {
982         if (gst_adapter_available (rmdemux->adapter) < HEADER_SIZE)
983           goto unlock;
984
985         data = gst_adapter_peek (rmdemux->adapter, HEADER_SIZE);
986
987         rmdemux->object_id = RMDEMUX_FOURCC_GET (data + 0);
988         rmdemux->size = RMDEMUX_GUINT32_GET (data + 4) - HEADER_SIZE;
989         rmdemux->object_version = RMDEMUX_GUINT16_GET (data + 8);
990
991         /* Sanity-check. We assume that the FOURCC is printable ASCII */
992         if (!gst_rmdemux_fourcc_isplausible (rmdemux->object_id)) {
993           /* Failed. Remain in HEADER state, try again... We flush only 
994            * the actual FOURCC, not the entire header, because we could 
995            * need to resync anywhere at all... really, this should never 
996            * happen. */
997           GST_WARNING_OBJECT (rmdemux, "Bogus looking header, unprintable "
998               "FOURCC");
999           gst_adapter_flush (rmdemux->adapter, 4);
1000
1001           break;
1002         }
1003
1004         GST_LOG_OBJECT (rmdemux, "header found with object_id=%"
1005             GST_FOURCC_FORMAT
1006             " size=%08x object_version=%d",
1007             GST_FOURCC_ARGS (rmdemux->object_id), rmdemux->size,
1008             rmdemux->object_version);
1009
1010         gst_adapter_flush (rmdemux->adapter, HEADER_SIZE);
1011
1012         switch (rmdemux->object_id) {
1013           case GST_MAKE_FOURCC ('.', 'R', 'M', 'F'):
1014             rmdemux->state = RMDEMUX_STATE_HEADER_RMF;
1015             break;
1016           case GST_MAKE_FOURCC ('P', 'R', 'O', 'P'):
1017             rmdemux->state = RMDEMUX_STATE_HEADER_PROP;
1018             break;
1019           case GST_MAKE_FOURCC ('M', 'D', 'P', 'R'):
1020             rmdemux->state = RMDEMUX_STATE_HEADER_MDPR;
1021             break;
1022           case GST_MAKE_FOURCC ('I', 'N', 'D', 'X'):
1023             rmdemux->state = RMDEMUX_STATE_HEADER_INDX;
1024             break;
1025           case GST_MAKE_FOURCC ('D', 'A', 'T', 'A'):
1026             rmdemux->state = RMDEMUX_STATE_HEADER_DATA;
1027             break;
1028           case GST_MAKE_FOURCC ('C', 'O', 'N', 'T'):
1029             rmdemux->state = RMDEMUX_STATE_HEADER_CONT;
1030             break;
1031           default:
1032             rmdemux->state = RMDEMUX_STATE_HEADER_UNKNOWN;
1033             break;
1034         }
1035         break;
1036       }
1037       case RMDEMUX_STATE_HEADER_UNKNOWN:
1038       {
1039         if (gst_adapter_available (rmdemux->adapter) < rmdemux->size)
1040           goto unlock;
1041
1042         GST_WARNING_OBJECT (rmdemux, "Unknown object_id %" GST_FOURCC_FORMAT,
1043             GST_FOURCC_ARGS (rmdemux->object_id));
1044
1045         gst_adapter_flush (rmdemux->adapter, rmdemux->size);
1046         rmdemux->state = RMDEMUX_STATE_HEADER;
1047         break;
1048       }
1049       case RMDEMUX_STATE_HEADER_RMF:
1050       {
1051         if (gst_adapter_available (rmdemux->adapter) < rmdemux->size)
1052           goto unlock;
1053
1054         if ((rmdemux->object_version == 0) || (rmdemux->object_version == 1)) {
1055           data = gst_adapter_peek (rmdemux->adapter, rmdemux->size);
1056
1057           gst_rmdemux_parse__rmf (rmdemux, data, rmdemux->size);
1058         }
1059
1060         gst_adapter_flush (rmdemux->adapter, rmdemux->size);
1061         rmdemux->state = RMDEMUX_STATE_HEADER;
1062         break;
1063       }
1064       case RMDEMUX_STATE_HEADER_PROP:
1065       {
1066         if (gst_adapter_available (rmdemux->adapter) < rmdemux->size)
1067           goto unlock;
1068         data = gst_adapter_peek (rmdemux->adapter, rmdemux->size);
1069
1070         gst_rmdemux_parse_prop (rmdemux, data, rmdemux->size);
1071
1072         gst_adapter_flush (rmdemux->adapter, rmdemux->size);
1073         rmdemux->state = RMDEMUX_STATE_HEADER;
1074         break;
1075       }
1076       case RMDEMUX_STATE_HEADER_MDPR:
1077       {
1078         if (gst_adapter_available (rmdemux->adapter) < rmdemux->size)
1079           goto unlock;
1080         data = gst_adapter_peek (rmdemux->adapter, rmdemux->size);
1081
1082         gst_rmdemux_parse_mdpr (rmdemux, data, rmdemux->size);
1083
1084         gst_adapter_flush (rmdemux->adapter, rmdemux->size);
1085         rmdemux->state = RMDEMUX_STATE_HEADER;
1086         break;
1087       }
1088       case RMDEMUX_STATE_HEADER_CONT:
1089       {
1090         if (gst_adapter_available (rmdemux->adapter) < rmdemux->size)
1091           goto unlock;
1092         data = gst_adapter_peek (rmdemux->adapter, rmdemux->size);
1093
1094         gst_rmdemux_parse_cont (rmdemux, data, rmdemux->size);
1095
1096         gst_adapter_flush (rmdemux->adapter, rmdemux->size);
1097         rmdemux->state = RMDEMUX_STATE_HEADER;
1098         break;
1099       }
1100       case RMDEMUX_STATE_HEADER_DATA:
1101       {
1102         /* If we haven't already done so then signal there are no more pads */
1103         if (!rmdemux->have_pads) {
1104           GST_LOG_OBJECT (rmdemux, "no more pads");
1105           gst_element_no_more_pads (GST_ELEMENT (rmdemux));
1106           rmdemux->have_pads = TRUE;
1107         }
1108
1109         /* The actual header is only 8 bytes */
1110         rmdemux->size = DATA_SIZE;
1111         GST_LOG_OBJECT (rmdemux, "data available %d",
1112             gst_adapter_available (rmdemux->adapter));
1113         if (gst_adapter_available (rmdemux->adapter) < rmdemux->size)
1114           goto unlock;
1115
1116         data = gst_adapter_peek (rmdemux->adapter, rmdemux->size);
1117
1118         gst_rmdemux_parse_data (rmdemux, data, rmdemux->size);
1119
1120         gst_adapter_flush (rmdemux->adapter, rmdemux->size);
1121
1122         rmdemux->state = RMDEMUX_STATE_DATA_PACKET;
1123         break;
1124       }
1125       case RMDEMUX_STATE_HEADER_INDX:
1126       {
1127         if (gst_adapter_available (rmdemux->adapter) < rmdemux->size)
1128           goto unlock;
1129         data = gst_adapter_peek (rmdemux->adapter, rmdemux->size);
1130
1131         rmdemux->size = gst_rmdemux_parse_indx (rmdemux, data, rmdemux->size);
1132
1133         /* Only flush the header */
1134         gst_adapter_flush (rmdemux->adapter, HEADER_SIZE);
1135
1136         rmdemux->state = RMDEMUX_STATE_INDX_DATA;
1137         break;
1138       }
1139       case RMDEMUX_STATE_INDX_DATA:
1140       {
1141         /* There's not always an data to get... */
1142         if (rmdemux->size > 0) {
1143           if (gst_adapter_available (rmdemux->adapter) < rmdemux->size)
1144             goto unlock;
1145
1146           data = gst_adapter_peek (rmdemux->adapter, rmdemux->size);
1147
1148           gst_rmdemux_parse_indx_data (rmdemux, data, rmdemux->size);
1149
1150           gst_adapter_flush (rmdemux->adapter, rmdemux->size);
1151         }
1152
1153         rmdemux->state = RMDEMUX_STATE_HEADER;
1154         break;
1155       }
1156       case RMDEMUX_STATE_DATA_PACKET:
1157       {
1158         if (gst_adapter_available (rmdemux->adapter) < 2)
1159           goto unlock;
1160
1161         data = gst_adapter_peek (rmdemux->adapter, 2);
1162         version = RMDEMUX_GUINT16_GET (data);
1163         GST_LOG_OBJECT (rmdemux, "Data packet with version=%d", version);
1164
1165         if (version == 0 || version == 1) {
1166           guint16 length;
1167
1168           if (gst_adapter_available (rmdemux->adapter) < 4)
1169             goto unlock;
1170           data = gst_adapter_peek (rmdemux->adapter, 4);
1171
1172           length = RMDEMUX_GUINT16_GET (data + 2);
1173           GST_LOG_OBJECT (rmdemux, "Got length %d", length);
1174
1175           if (length < 4) {
1176             GST_LOG_OBJECT (rmdemux, "length too small, dropping");
1177             /* Invalid, just drop it */
1178             gst_adapter_flush (rmdemux->adapter, 4);
1179           } else {
1180             GstBuffer *buffer;
1181
1182             avail = gst_adapter_available (rmdemux->adapter);
1183             if (avail < length)
1184               goto unlock;
1185
1186             GST_LOG_OBJECT (rmdemux, "we have %u available and we needed %d",
1187                 avail, length);
1188
1189             /* flush version and length */
1190             gst_adapter_flush (rmdemux->adapter, 4);
1191             length -= 4;
1192
1193             buffer = gst_adapter_take_buffer (rmdemux->adapter, length);
1194
1195             ret = gst_rmdemux_parse_packet (rmdemux, buffer, version);
1196             rmdemux->chunk_index++;
1197           }
1198
1199           if (rmdemux->chunk_index == rmdemux->n_chunks || length == 0)
1200             rmdemux->state = RMDEMUX_STATE_HEADER;
1201         } else {
1202           /* Stream done */
1203           gst_adapter_flush (rmdemux->adapter, 2);
1204
1205           if (rmdemux->data_offset == 0) {
1206             GST_LOG_OBJECT (rmdemux,
1207                 "No further data, internal demux state EOS");
1208             rmdemux->state = RMDEMUX_STATE_EOS;
1209           } else
1210             rmdemux->state = RMDEMUX_STATE_HEADER;
1211         }
1212         break;
1213       }
1214       case RMDEMUX_STATE_EOS:
1215         gst_rmdemux_send_event (rmdemux, gst_event_new_eos ());
1216         goto unlock;
1217       default:
1218         GST_WARNING_OBJECT (rmdemux, "Unhandled state %d", rmdemux->state);
1219         goto unlock;
1220     }
1221   }
1222
1223 unlock:
1224   return ret;
1225 }
1226
1227 static GstRMDemuxStream *
1228 gst_rmdemux_get_stream_by_id (GstRMDemux * rmdemux, int id)
1229 {
1230   GSList *cur;
1231
1232   for (cur = rmdemux->streams; cur; cur = cur->next) {
1233     GstRMDemuxStream *stream = cur->data;
1234
1235     if (stream->id == id) {
1236       return stream;
1237     }
1238   }
1239
1240   return NULL;
1241 }
1242
1243 static void
1244 gst_rmdemux_send_event (GstRMDemux * rmdemux, GstEvent * event)
1245 {
1246   GSList *cur;
1247
1248   for (cur = rmdemux->streams; cur; cur = cur->next) {
1249     GstRMDemuxStream *stream = cur->data;
1250
1251     GST_DEBUG_OBJECT (rmdemux, "Pushing %s event on pad %s",
1252         GST_EVENT_TYPE_NAME (event), GST_PAD_NAME (stream->pad));
1253
1254     gst_event_ref (event);
1255     gst_pad_push_event (stream->pad, event);
1256   }
1257   gst_event_unref (event);
1258 }
1259
1260 static void
1261 gst_rmdemux_add_stream (GstRMDemux * rmdemux, GstRMDemuxStream * stream)
1262 {
1263   GstCaps *stream_caps = NULL;
1264   const gchar *codec_tag = NULL;
1265   const gchar *codec_name = NULL;
1266   int version = 0;
1267
1268   if (stream->subtype == GST_RMDEMUX_STREAM_VIDEO) {
1269     char *name = g_strdup_printf ("video_%02d", rmdemux->n_video_streams);
1270
1271     stream->pad =
1272         gst_pad_new_from_static_template (&gst_rmdemux_videosrc_template, name);
1273     g_free (name);
1274
1275     codec_tag = GST_TAG_VIDEO_CODEC;
1276
1277     switch (stream->fourcc) {
1278       case GST_RM_VDO_RV10:
1279         codec_name = "Real Video 1.0";
1280         version = 1;
1281         break;
1282       case GST_RM_VDO_RV20:
1283         codec_name = "Real Video 2.0";
1284         version = 2;
1285         break;
1286       case GST_RM_VDO_RV30:
1287         codec_name = "Real Video 3.0";
1288         version = 3;
1289         break;
1290       case GST_RM_VDO_RV40:
1291         codec_name = "Real Video 4.0";
1292         version = 4;
1293         break;
1294       default:
1295         stream_caps = gst_caps_new_simple ("video/x-unknown-fourcc",
1296             "fourcc", GST_TYPE_FOURCC, stream->fourcc, NULL);
1297         GST_WARNING_OBJECT (rmdemux,
1298             "Unknown video FOURCC code \"%" GST_FOURCC_FORMAT "\" (%08x)",
1299             GST_FOURCC_ARGS (stream->fourcc), stream->fourcc);
1300     }
1301
1302     if (version) {
1303       stream_caps =
1304           gst_caps_new_simple ("video/x-pn-realvideo", "rmversion", G_TYPE_INT,
1305           (int) version,
1306           "format", G_TYPE_INT,
1307           (int) stream->format,
1308           "subformat", G_TYPE_INT, (int) stream->subformat, NULL);
1309     }
1310
1311     if (stream_caps) {
1312       gst_caps_set_simple (stream_caps,
1313           "width", G_TYPE_INT, stream->width,
1314           "height", G_TYPE_INT, stream->height,
1315           "framerate", GST_TYPE_FRACTION, stream->framerate_numerator,
1316           stream->framerate_denominator, NULL);
1317     }
1318     rmdemux->n_video_streams++;
1319
1320   } else if (stream->subtype == GST_RMDEMUX_STREAM_AUDIO) {
1321     char *name = g_strdup_printf ("audio_%02d", rmdemux->n_audio_streams);
1322
1323     stream->pad =
1324         gst_pad_new_from_static_template (&gst_rmdemux_audiosrc_template, name);
1325     GST_LOG_OBJECT (rmdemux, "Created audio pad \"%s\"", name);
1326     g_free (name);
1327
1328     codec_tag = GST_TAG_AUDIO_CODEC;
1329
1330     switch (stream->fourcc) {
1331         /* Older RealAudio Codecs */
1332       case GST_RM_AUD_14_4:
1333         codec_name = "Real Audio 14.4kbps";
1334         version = 1;
1335         break;
1336
1337       case GST_RM_AUD_28_8:
1338         codec_name = "Real Audio 28.8kbps";
1339         version = 2;
1340         break;
1341
1342         /* DolbyNet (Dolby AC3, low bitrate) */
1343       case GST_RM_AUD_DNET:
1344         codec_name = "AC-3 audio";
1345         stream_caps =
1346             gst_caps_new_simple ("audio/x-ac3", "rate", G_TYPE_INT,
1347             (int) stream->rate, NULL);
1348         stream->needs_descrambling = TRUE;
1349         stream->subpackets_needed = 1;
1350         stream->subpackets = NULL;
1351         break;
1352
1353         /* RealAudio 10 (AAC) */
1354       case GST_RM_AUD_RAAC:
1355         codec_name = "Real Audio 10 (AAC)";
1356         version = 10;
1357         break;
1358
1359         /* MPEG-4 based */
1360       case GST_RM_AUD_RACP:
1361         /* FIXME: codec_name = */
1362         stream_caps =
1363             gst_caps_new_simple ("audio/mpeg", "mpegversion", G_TYPE_INT,
1364             (int) 4, NULL);
1365         break;
1366
1367         /* Sony ATRAC3 */
1368       case GST_RM_AUD_ATRC:
1369         codec_name = "Sony ATRAC3";
1370         stream_caps = gst_caps_new_simple ("audio/x-vnd.sony.atrac3", NULL);
1371         break;
1372
1373         /* RealAudio G2 audio */
1374       case GST_RM_AUD_COOK:
1375         codec_name = "Real Audio G2 (Cook)";
1376         version = 8;
1377         stream->needs_descrambling = TRUE;
1378         stream->subpackets_needed = stream->height;
1379         stream->subpackets = NULL;
1380         break;
1381
1382         /* RALF is lossless */
1383       case GST_RM_AUD_RALF:
1384         /* FIXME: codec_name = */
1385         GST_DEBUG_OBJECT (rmdemux, "RALF");
1386         stream_caps = gst_caps_new_simple ("audio/x-ralf-mpeg4-generic", NULL);
1387         break;
1388
1389         /* Sipro/ACELP.NET Voice Codec (MIME unknown) */
1390       case GST_RM_AUD_SIPR:
1391         /* FIXME: codec_name = */
1392         stream_caps = gst_caps_new_simple ("audio/x-sipro", NULL);
1393         break;
1394
1395       default:
1396         stream_caps = gst_caps_new_simple ("video/x-unknown-fourcc",
1397             "fourcc", GST_TYPE_FOURCC, stream->fourcc, NULL);
1398         GST_WARNING_OBJECT (rmdemux,
1399             "Unknown audio FOURCC code \"%" GST_FOURCC_FORMAT "\" (%08x)",
1400             GST_FOURCC_ARGS (stream->fourcc), stream->fourcc);
1401         break;
1402     }
1403
1404     if (version) {
1405       stream_caps =
1406           gst_caps_new_simple ("audio/x-pn-realaudio", "raversion", G_TYPE_INT,
1407           (int) version, NULL);
1408     }
1409
1410     if (stream_caps) {
1411       gst_caps_set_simple (stream_caps,
1412           "flavor", G_TYPE_INT, (int) stream->flavor,
1413           "rate", G_TYPE_INT, (int) stream->rate,
1414           "channels", G_TYPE_INT, (int) stream->n_channels,
1415           "width", G_TYPE_INT, (int) stream->sample_width,
1416           "leaf_size", G_TYPE_INT, (int) stream->leaf_size,
1417           "packet_size", G_TYPE_INT, (int) stream->packet_size,
1418           "height", G_TYPE_INT, (int) stream->height, NULL);
1419     }
1420     rmdemux->n_audio_streams++;
1421   } else {
1422     GST_WARNING_OBJECT (rmdemux, "not adding stream of type %d, freeing it",
1423         stream->subtype);
1424     g_free (stream);
1425     goto beach;
1426   }
1427
1428   GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
1429   rmdemux->streams = g_slist_append (rmdemux->streams, stream);
1430   GST_LOG_OBJECT (rmdemux, "n_streams is now %d",
1431       g_slist_length (rmdemux->streams));
1432
1433   GST_LOG ("stream->pad = %p, stream_caps = %" GST_PTR_FORMAT, stream->pad,
1434       stream_caps);
1435
1436   if (stream->pad && stream_caps) {
1437
1438     GST_LOG_OBJECT (rmdemux, "%d bytes of extra data for stream %s",
1439         stream->extra_data_size, GST_PAD_NAME (stream->pad));
1440
1441     /* add codec_data if there is any */
1442     if (stream->extra_data_size > 0) {
1443       GstBuffer *buffer;
1444
1445       buffer = gst_buffer_new_and_alloc (stream->extra_data_size);
1446       memcpy (GST_BUFFER_DATA (buffer), stream->extra_data,
1447           stream->extra_data_size);
1448
1449       gst_caps_set_simple (stream_caps, "codec_data", GST_TYPE_BUFFER,
1450           buffer, NULL);
1451
1452       gst_buffer_unref (buffer);
1453     }
1454
1455     gst_pad_use_fixed_caps (stream->pad);
1456
1457     gst_pad_set_caps (stream->pad, stream_caps);
1458     gst_pad_set_event_function (stream->pad,
1459         GST_DEBUG_FUNCPTR (gst_rmdemux_src_event));
1460     gst_pad_set_query_type_function (stream->pad,
1461         GST_DEBUG_FUNCPTR (gst_rmdemux_src_query_types));
1462     gst_pad_set_query_function (stream->pad,
1463         GST_DEBUG_FUNCPTR (gst_rmdemux_src_query));
1464
1465     GST_DEBUG_OBJECT (rmdemux, "adding pad %s with caps %" GST_PTR_FORMAT
1466         ", stream_id=%d", GST_PAD_NAME (stream->pad), stream_caps, stream->id);
1467     gst_pad_set_active (stream->pad, TRUE);
1468     gst_element_add_pad (GST_ELEMENT_CAST (rmdemux), stream->pad);
1469
1470     /* save for later, we must send the tags after the newsegment event */
1471     if (codec_name != NULL && codec_tag != NULL) {
1472       stream->pending_tags = gst_tag_list_new ();
1473       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_KEEP,
1474           codec_tag, codec_name, NULL);
1475     }
1476   }
1477
1478 beach:
1479
1480   if (stream_caps)
1481     gst_caps_unref (stream_caps);
1482 }
1483
1484 static int
1485 re_skip_pascal_string (const guint8 * ptr)
1486 {
1487   int length;
1488
1489   length = ptr[0];
1490
1491   return length + 1;
1492 }
1493
1494 static void
1495 gst_rmdemux_parse__rmf (GstRMDemux * rmdemux, const guint8 * data, int length)
1496 {
1497   GST_LOG_OBJECT (rmdemux, "file_version: %d", RMDEMUX_GUINT32_GET (data));
1498   GST_LOG_OBJECT (rmdemux, "num_headers: %d", RMDEMUX_GUINT32_GET (data + 4));
1499 }
1500
1501 static void
1502 gst_rmdemux_parse_prop (GstRMDemux * rmdemux, const guint8 * data, int length)
1503 {
1504   GST_LOG_OBJECT (rmdemux, "max bitrate: %d", RMDEMUX_GUINT32_GET (data));
1505   GST_LOG_OBJECT (rmdemux, "avg bitrate: %d", RMDEMUX_GUINT32_GET (data + 4));
1506   GST_LOG_OBJECT (rmdemux, "max packet size: %d",
1507       RMDEMUX_GUINT32_GET (data + 8));
1508   rmdemux->avg_packet_size = RMDEMUX_GUINT32_GET (data + 12);
1509   GST_LOG_OBJECT (rmdemux, "avg packet size: %d", rmdemux->avg_packet_size);
1510   rmdemux->num_packets = RMDEMUX_GUINT32_GET (data + 16);
1511   GST_LOG_OBJECT (rmdemux, "number of packets: %d", rmdemux->num_packets);
1512
1513   GST_LOG_OBJECT (rmdemux, "duration: %d", RMDEMUX_GUINT32_GET (data + 20));
1514   rmdemux->duration = RMDEMUX_GUINT32_GET (data + 20) * GST_MSECOND;
1515
1516   GST_LOG_OBJECT (rmdemux, "preroll: %d", RMDEMUX_GUINT32_GET (data + 24));
1517   rmdemux->index_offset = RMDEMUX_GUINT32_GET (data + 28);
1518   GST_LOG_OBJECT (rmdemux, "offset of INDX section: 0x%08x",
1519       rmdemux->index_offset);
1520   rmdemux->data_offset = RMDEMUX_GUINT32_GET (data + 32);
1521   GST_LOG_OBJECT (rmdemux, "offset of DATA section: 0x%08x",
1522       rmdemux->data_offset);
1523   GST_LOG_OBJECT (rmdemux, "n streams: %d", RMDEMUX_GUINT16_GET (data + 36));
1524   GST_LOG_OBJECT (rmdemux, "flags: 0x%04x", RMDEMUX_GUINT16_GET (data + 38));
1525 }
1526
1527 static void
1528 gst_rmdemux_parse_mdpr (GstRMDemux * rmdemux, const guint8 * data, int length)
1529 {
1530   GstRMDemuxStream *stream;
1531   char *stream1_type_string;
1532   char *stream2_type_string;
1533   guint str_len = 0;
1534   int stream_type;
1535   int offset;
1536
1537   stream = g_new0 (GstRMDemuxStream, 1);
1538
1539   stream->id = RMDEMUX_GUINT16_GET (data);
1540   stream->index = NULL;
1541   stream->seek_offset = 0;
1542   stream->last_flow = GST_FLOW_OK;
1543   stream->adapter = gst_adapter_new ();
1544   GST_LOG_OBJECT (rmdemux, "stream_number=%d", stream->id);
1545
1546   offset = 30;
1547   stream_type = GST_RMDEMUX_STREAM_UNKNOWN;
1548   stream1_type_string = gst_rm_utils_read_string8 (data + offset,
1549       length - offset, &str_len);
1550   offset += str_len;
1551   stream2_type_string = gst_rm_utils_read_string8 (data + offset,
1552       length - offset, &str_len);
1553   offset += str_len;
1554
1555   /* stream1_type_string for audio and video stream is a "put_whatever_you_want" field :
1556    * observed values :
1557    * - "[The ]Video/Audio Stream" (File produced by an official Real encoder)
1558    * - "RealVideoPremierePlugIn-VIDEO/AUDIO" (File produced by Abobe Premiere)
1559    *
1560    * so, we should not rely on it to know which stream type it is
1561    */
1562
1563   GST_LOG_OBJECT (rmdemux, "stream type: %s", stream1_type_string);
1564   GST_LOG_OBJECT (rmdemux, "MIME type=%s", stream2_type_string);
1565
1566   if (strcmp (stream2_type_string, "video/x-pn-realvideo") == 0) {
1567     stream_type = GST_RMDEMUX_STREAM_VIDEO;
1568   } else if (strcmp (stream2_type_string,
1569           "video/x-pn-multirate-realvideo") == 0) {
1570     stream_type = GST_RMDEMUX_STREAM_VIDEO;
1571   } else if (strcmp (stream2_type_string, "audio/x-pn-realaudio") == 0) {
1572     stream_type = GST_RMDEMUX_STREAM_AUDIO;
1573   } else if (strcmp (stream2_type_string,
1574           "audio/x-pn-multirate-realaudio") == 0) {
1575     stream_type = GST_RMDEMUX_STREAM_AUDIO;
1576   } else if (strcmp (stream2_type_string,
1577           "audio/x-pn-multirate-realaudio-live") == 0) {
1578     stream_type = GST_RMDEMUX_STREAM_AUDIO;
1579   } else if (strcmp (stream2_type_string, "audio/x-ralf-mpeg4-generic") == 0) {
1580     /* Another audio type found in the real testsuite */
1581     stream_type = GST_RMDEMUX_STREAM_AUDIO;
1582   } else if (strcmp (stream1_type_string, "") == 0 &&
1583       strcmp (stream2_type_string, "logical-fileinfo") == 0) {
1584     stream_type = GST_RMDEMUX_STREAM_FILEINFO;
1585   } else {
1586     stream_type = GST_RMDEMUX_STREAM_UNKNOWN;
1587     GST_WARNING_OBJECT (rmdemux, "unknown stream type \"%s\",\"%s\"",
1588         stream1_type_string, stream2_type_string);
1589   }
1590   g_free (stream1_type_string);
1591   g_free (stream2_type_string);
1592
1593   offset += 4;
1594
1595   stream->subtype = stream_type;
1596   switch (stream_type) {
1597
1598     case GST_RMDEMUX_STREAM_VIDEO:
1599       /* RV10/RV20/RV30/RV40 => video/x-pn-realvideo, version=1,2,3,4 */
1600       stream->fourcc = RMDEMUX_FOURCC_GET (data + offset + 8);
1601       stream->width = RMDEMUX_GUINT16_GET (data + offset + 12);
1602       stream->height = RMDEMUX_GUINT16_GET (data + offset + 14);
1603       stream->rate = RMDEMUX_GUINT16_GET (data + offset + 16);
1604       stream->subformat = RMDEMUX_GUINT32_GET (data + offset + 26);
1605       stream->format = RMDEMUX_GUINT32_GET (data + offset + 30);
1606       stream->extra_data_size = length - (offset + 26);
1607       stream->extra_data = (guint8 *) data + offset + 26;
1608       /* Natural way to represent framerates here requires unsigned 32 bit
1609        * numerator, which we don't have. For the nasty case, approximate...
1610        */
1611       {
1612         guint32 numerator = RMDEMUX_GUINT16_GET (data + offset + 22) * 65536 +
1613             RMDEMUX_GUINT16_GET (data + offset + 24);
1614         if (numerator > G_MAXINT) {
1615           stream->framerate_numerator = (gint) (numerator >> 1);
1616           stream->framerate_denominator = 32768;
1617         } else {
1618           stream->framerate_numerator = (gint) numerator;
1619           stream->framerate_denominator = 65536;
1620         }
1621       }
1622
1623       GST_DEBUG_OBJECT (rmdemux,
1624           "Video stream with fourcc=%" GST_FOURCC_FORMAT
1625           " width=%d height=%d rate=%d framerate=%d/%d subformat=%x format=%x extra_data_size=%d",
1626           GST_FOURCC_ARGS (stream->fourcc), stream->width, stream->height,
1627           stream->rate, stream->framerate_numerator,
1628           stream->framerate_denominator, stream->subformat, stream->format,
1629           stream->extra_data_size);
1630       break;
1631     case GST_RMDEMUX_STREAM_AUDIO:{
1632       stream->version = RMDEMUX_GUINT16_GET (data + offset + 4);
1633       GST_INFO ("stream version = %u", stream->version);
1634       switch (stream->version) {
1635         case 3:
1636           stream->fourcc = GST_RM_AUD_14_4;
1637           stream->packet_size = 20;
1638           stream->rate = 8000;
1639           stream->n_channels = 1;
1640           stream->sample_width = 16;
1641           stream->flavor = 1;
1642           stream->leaf_size = 0;
1643           stream->height = 0;
1644           break;
1645         case 4:
1646           stream->flavor = RMDEMUX_GUINT16_GET (data + offset + 22);
1647           stream->packet_size = RMDEMUX_GUINT32_GET (data + offset + 24);
1648           /* stream->frame_size = RMDEMUX_GUINT32_GET (data + offset + 42); */
1649           stream->leaf_size = RMDEMUX_GUINT16_GET (data + offset + 44);
1650           stream->height = RMDEMUX_GUINT16_GET (data + offset + 40);
1651           stream->rate = RMDEMUX_GUINT16_GET (data + offset + 48);
1652           stream->sample_width = RMDEMUX_GUINT16_GET (data + offset + 52);
1653           stream->n_channels = RMDEMUX_GUINT16_GET (data + offset + 54);
1654           stream->fourcc = RMDEMUX_FOURCC_GET (data + offset + 62);
1655           stream->extra_data_size = RMDEMUX_GUINT32_GET (data + offset + 69);
1656           GST_DEBUG_OBJECT (rmdemux, "%u bytes of extra codec data",
1657               stream->extra_data_size);
1658           if (length - (offset + 73) >= stream->extra_data_size) {
1659             stream->extra_data = (guint8 *) data + offset + 73;
1660           } else {
1661             GST_WARNING_OBJECT (rmdemux, "codec data runs beyond MDPR chunk");
1662             stream->extra_data_size = 0;
1663           }
1664           break;
1665         case 5:
1666           stream->flavor = RMDEMUX_GUINT16_GET (data + offset + 22);
1667           stream->packet_size = RMDEMUX_GUINT32_GET (data + offset + 24);
1668           /* stream->frame_size = RMDEMUX_GUINT32_GET (data + offset + 42); */
1669           stream->leaf_size = RMDEMUX_GUINT16_GET (data + offset + 44);
1670           stream->height = RMDEMUX_GUINT16_GET (data + offset + 40);
1671           stream->rate = RMDEMUX_GUINT16_GET (data + offset + 54);
1672           stream->sample_width = RMDEMUX_GUINT16_GET (data + offset + 58);
1673           stream->n_channels = RMDEMUX_GUINT16_GET (data + offset + 60);
1674           stream->fourcc = RMDEMUX_FOURCC_GET (data + offset + 66);
1675           stream->extra_data_size = RMDEMUX_GUINT32_GET (data + offset + 74);
1676           GST_DEBUG_OBJECT (rmdemux, "%u bytes of extra codec data",
1677               stream->extra_data_size);
1678           if (length - (offset + 78) >= stream->extra_data_size) {
1679             stream->extra_data = (guint8 *) data + offset + 78;
1680           } else {
1681             GST_WARNING_OBJECT (rmdemux, "codec data runs beyond MDPR chunk");
1682             stream->extra_data_size = 0;
1683           }
1684           break;
1685         default:{
1686           GST_WARNING_OBJECT (rmdemux, "Unhandled audio stream version %d",
1687               stream->version);
1688           break;
1689         }
1690       }
1691
1692       /*  14_4, 28_8, cook, dnet, sipr, raac, racp, ralf, atrc */
1693       GST_DEBUG_OBJECT (rmdemux,
1694           "Audio stream with rate=%d sample_width=%d n_channels=%d",
1695           stream->rate, stream->sample_width, stream->n_channels);
1696
1697       break;
1698     }
1699     case GST_RMDEMUX_STREAM_FILEINFO:
1700     {
1701       int element_nb;
1702
1703       /* Length of this section */
1704       GST_DEBUG_OBJECT (rmdemux, "length2: 0x%08x",
1705           RMDEMUX_GUINT32_GET (data + offset));
1706       offset += 4;
1707
1708       /* Unknown : 00 00 00 00 */
1709       offset += 4;
1710
1711       /* Number of variables that would follow (loop iterations) */
1712       element_nb = RMDEMUX_GUINT32_GET (data + offset);
1713       offset += 4;
1714
1715       while (element_nb) {
1716         /* Category Id : 00 00 00 XX 00 00 */
1717         offset += 6;
1718
1719         /* Variable Name */
1720         offset += re_skip_pascal_string (data + offset);
1721
1722         /* Variable Value Type */
1723         /*   00 00 00 00 00 => integer/boolean, preceded by length */
1724         /*   00 00 00 02 00 => pascal string, preceded by length, no trailing \0 */
1725         offset += 5;
1726
1727         /* Variable Value */
1728         offset += re_skip_pascal_string (data + offset);
1729
1730         element_nb--;
1731       }
1732     }
1733       break;
1734     case GST_RMDEMUX_STREAM_UNKNOWN:
1735     default:
1736       break;
1737   }
1738
1739   gst_rmdemux_add_stream (rmdemux, stream);
1740 }
1741
1742 static guint
1743 gst_rmdemux_parse_indx (GstRMDemux * rmdemux, const guint8 * data, int length)
1744 {
1745   int n;
1746   int id;
1747
1748   n = RMDEMUX_GUINT32_GET (data);
1749   id = RMDEMUX_GUINT16_GET (data + 4);
1750   rmdemux->index_offset = RMDEMUX_GUINT32_GET (data + 6);
1751
1752   GST_DEBUG_OBJECT (rmdemux, "Number of indices=%d Stream ID=%d length=%d", n,
1753       id, length);
1754
1755   /* Point to the next index_stream */
1756   rmdemux->index_stream = gst_rmdemux_get_stream_by_id (rmdemux, id);
1757
1758   /* Return the length of the index */
1759   return 14 * n;
1760 }
1761
1762 static void
1763 gst_rmdemux_parse_indx_data (GstRMDemux * rmdemux, const guint8 * data,
1764     int length)
1765 {
1766   int i;
1767   int n;
1768   GstRMDemuxIndex *index;
1769
1770   /* The number of index records */
1771   n = length / 14;
1772
1773   if (rmdemux->index_stream == NULL)
1774     return;
1775
1776   /* don't parse the index a second time when operating pull-based and
1777    * reaching the end of the file */
1778   if (rmdemux->index_stream->index_length > 0) {
1779     GST_DEBUG_OBJECT (rmdemux, "Already have an index for this stream");
1780     return;
1781   }
1782
1783   index = g_malloc (sizeof (GstRMDemuxIndex) * n);
1784   rmdemux->index_stream->index = index;
1785   rmdemux->index_stream->index_length = n;
1786
1787   for (i = 0; i < n; i++) {
1788     index[i].timestamp = RMDEMUX_GUINT32_GET (data + 2) * GST_MSECOND;
1789     index[i].offset = RMDEMUX_GUINT32_GET (data + 6);
1790
1791     GST_DEBUG_OBJECT (rmdemux, "Index found for timestamp=%f (at offset=%x)",
1792         gst_guint64_to_gdouble (index[i].timestamp) / GST_SECOND,
1793         index[i].offset);
1794     data += 14;
1795   }
1796 }
1797
1798 static void
1799 gst_rmdemux_parse_data (GstRMDemux * rmdemux, const guint8 * data, int length)
1800 {
1801   rmdemux->n_chunks = RMDEMUX_GUINT32_GET (data);
1802   rmdemux->data_offset = RMDEMUX_GUINT32_GET (data + 4);
1803   rmdemux->chunk_index = 0;
1804   GST_DEBUG_OBJECT (rmdemux, "Data chunk found with %d packets "
1805       "(next data at 0x%08x)", rmdemux->n_chunks, rmdemux->data_offset);
1806 }
1807
1808 static void
1809 gst_rmdemux_parse_cont (GstRMDemux * rmdemux, const guint8 * data, int length)
1810 {
1811   GstTagList *tags;
1812
1813   tags = gst_rm_utils_read_tags (data, length, gst_rm_utils_read_string16);
1814   if (tags) {
1815     gst_element_found_tags (GST_ELEMENT (rmdemux), tags);
1816   }
1817 }
1818
1819 static GstFlowReturn
1820 gst_rmdemux_combine_flows (GstRMDemux * rmdemux, GstRMDemuxStream * stream,
1821     GstFlowReturn ret)
1822 {
1823   GSList *cur;
1824
1825   /* store the value */
1826   stream->last_flow = ret;
1827
1828   /* if it's success we can return the value right away */
1829   if (GST_FLOW_IS_SUCCESS (ret))
1830     goto done;
1831
1832   /* any other error that is not-linked can be returned right
1833    * away */
1834   if (ret != GST_FLOW_NOT_LINKED)
1835     goto done;
1836
1837   for (cur = rmdemux->streams; cur; cur = cur->next) {
1838     GstRMDemuxStream *ostream = cur->data;
1839
1840     ret = ostream->last_flow;
1841     /* some other return value (must be SUCCESS but we can return
1842      * other values as well) */
1843     if (ret != GST_FLOW_NOT_LINKED)
1844       goto done;
1845   }
1846   /* if we get here, all other pads were unlinked and we return
1847    * NOT_LINKED then */
1848 done:
1849   return ret;
1850 }
1851
1852 static void
1853 gst_rmdemux_stream_clear_cached_subpackets (GstRMDemux * rmdemux,
1854     GstRMDemuxStream * stream)
1855 {
1856   if (stream->subpackets == NULL || stream->subpackets->len == 0)
1857     return;
1858
1859   GST_DEBUG_OBJECT (rmdemux, "discarding %u previously collected subpackets",
1860       stream->subpackets->len);
1861   g_ptr_array_foreach (stream->subpackets, (GFunc) gst_mini_object_unref, NULL);
1862   g_ptr_array_set_size (stream->subpackets, 0);
1863 }
1864
1865 static GstFlowReturn
1866 gst_rmdemux_descramble_cook_audio (GstRMDemux * rmdemux,
1867     GstRMDemuxStream * stream)
1868 {
1869   GstFlowReturn ret;
1870   GstBuffer *outbuf;
1871   guint packet_size = stream->packet_size;
1872   guint height = stream->subpackets->len;
1873   guint leaf_size = stream->leaf_size;
1874   guint p, x;
1875
1876   g_assert (stream->height == height);
1877
1878   GST_LOG ("packet_size = %u, leaf_size = %u, height= %u", packet_size,
1879       leaf_size, height);
1880
1881   ret = gst_pad_alloc_buffer_and_set_caps (stream->pad,
1882       GST_BUFFER_OFFSET_NONE, height * packet_size,
1883       GST_PAD_CAPS (stream->pad), &outbuf);
1884
1885   if (ret != GST_FLOW_OK)
1886     goto done;
1887
1888   for (p = 0; p < height; ++p) {
1889     GstBuffer *b = g_ptr_array_index (stream->subpackets, p);
1890     guint8 *b_data = GST_BUFFER_DATA (b);
1891
1892     if (p == 0)
1893       GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (b);
1894
1895     for (x = 0; x < packet_size / leaf_size; ++x) {
1896       guint idx;
1897
1898       idx = height * x + ((height + 1) / 2) * (p % 2) + (p / 2);
1899       /* GST_LOG ("%3u => %3u", (height * p) + x, idx); */
1900       memcpy (GST_BUFFER_DATA (outbuf) + leaf_size * idx, b_data, leaf_size);
1901       b_data += leaf_size;
1902     }
1903   }
1904
1905   /* some decoders, such as realaudiodec, need to be fed in packet units */
1906   for (p = 0; p < height; ++p) {
1907     GstBuffer *subbuf;
1908
1909     subbuf = gst_buffer_create_sub (outbuf, p * packet_size, packet_size);
1910     gst_buffer_set_caps (subbuf, GST_PAD_CAPS (stream->pad));
1911     ret = gst_pad_push (stream->pad, subbuf);
1912     if (ret != GST_FLOW_OK)
1913       break;
1914   }
1915
1916   gst_buffer_unref (outbuf);
1917
1918 done:
1919
1920   gst_rmdemux_stream_clear_cached_subpackets (rmdemux, stream);
1921
1922   return ret;
1923 }
1924
1925 static GstFlowReturn
1926 gst_rmdemux_descramble_dnet_audio (GstRMDemux * rmdemux,
1927     GstRMDemuxStream * stream)
1928 {
1929   GstBuffer *buf;
1930
1931   buf = g_ptr_array_index (stream->subpackets, 0);
1932   g_ptr_array_index (stream->subpackets, 0) = NULL;
1933   g_ptr_array_set_size (stream->subpackets, 0);
1934
1935   buf = gst_rm_utils_descramble_dnet_buffer (buf);
1936   return gst_pad_push (stream->pad, buf);
1937 }
1938
1939 static GstFlowReturn
1940 gst_rmdemux_handle_scrambled_packet (GstRMDemux * rmdemux,
1941     GstRMDemuxStream * stream, GstBuffer * buf, gboolean keyframe)
1942 {
1943   GstFlowReturn ret;
1944
1945   if (stream->subpackets == NULL)
1946     stream->subpackets = g_ptr_array_sized_new (stream->subpackets_needed);
1947
1948   GST_LOG ("Got subpacket %u/%u, len=%u, key=%d", stream->subpackets->len + 1,
1949       stream->subpackets_needed, GST_BUFFER_SIZE (buf), keyframe);
1950
1951   if (keyframe && stream->subpackets->len > 0) {
1952     gst_rmdemux_stream_clear_cached_subpackets (rmdemux, stream);
1953   }
1954
1955   g_ptr_array_add (stream->subpackets, buf);
1956
1957   if (stream->subpackets->len < stream->subpackets_needed)
1958     return GST_FLOW_OK;
1959
1960   g_assert (stream->subpackets->len >= 1);
1961
1962   switch (stream->fourcc) {
1963     case GST_RM_AUD_DNET:
1964       ret = gst_rmdemux_descramble_dnet_audio (rmdemux, stream);
1965       break;
1966     case GST_RM_AUD_COOK:
1967       ret = gst_rmdemux_descramble_cook_audio (rmdemux, stream);
1968       break;
1969     default:
1970       g_assert_not_reached ();
1971   }
1972
1973   return ret;
1974 }
1975
1976 #if 0
1977 static GstClockTime
1978 gst_rmdemux_fix_timestamp (GstRMDemux * rmdemux, GstClockTime timestamp)
1979 {
1980   GstFlowReturn ret;
1981   const guint8 *b;
1982   guint8 frame_type;
1983   guint16 seq;
1984   GstClockTime ts = timestamp;
1985
1986   GST_LOG_OBJECT (rmdemux, "timestamp %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1987
1988   /* Fix timestamp. */
1989   b = gst_adapter_peek (dec->adapter, 4);
1990   switch (dec->version) {
1991     case GST_REAL_VIDEO_DEC_VERSION_2:
1992     {
1993
1994       /*
1995        * Bit  1- 2: frame type
1996        * Bit  3- 9: ?
1997        * Bit 10-22: sequence number
1998        * Bit 23-32: ?
1999        */
2000       frame_type = (b[0] >> 6) & 0x03;
2001       seq = ((b[1] & 0x7f) << 6) + ((b[2] & 0xfc) >> 2);
2002       break;
2003     }
2004     case GST_REAL_VIDEO_DEC_VERSION_3:
2005     {
2006       /*
2007        * Bit  1- 2: ?
2008        * Bit     3: skip packet if 1
2009        * Bit  4- 5: frame type
2010        * Bit  6-12: ?
2011        * Bit 13-25: sequence number
2012        * Bit 26-32: ?
2013        */
2014       frame_type = (b[0] >> 3) & 0x03;
2015       seq = ((b[1] & 0x0f) << 9) + (b[2] << 1) + ((b[3] & 0x80) >> 7);
2016       break;
2017     }
2018     case GST_REAL_VIDEO_DEC_VERSION_4:
2019     {
2020       /*
2021        * Bit     1: skip packet if 1
2022        * Bit  2- 3: frame type
2023        * Bit  4-13: ?
2024        * Bit 14-26: sequence number
2025        * Bit 27-32: ?
2026        */
2027       frame_type = (b[0] >> 5) & 0x03;
2028       seq = ((b[1] & 0x07) << 10) + (b[2] << 2) + ((b[3] & 0xc0) >> 6);
2029       break;
2030     }
2031     default:
2032       goto unknown_version;
2033   }
2034
2035   GST_LOG_OBJECT (dec, "frame_type:%d", frame_type);
2036
2037   switch (frame_type) {
2038     case 0:
2039     case 1:
2040     {
2041       /* I frame */
2042       timestamp = dec->next_ts;
2043       dec->last_ts = dec->next_ts;
2044       dec->next_ts = ts;
2045       dec->last_seq = dec->next_seq;
2046       dec->next_seq = seq;
2047
2048       break;
2049     }
2050     case 2:
2051     {
2052       /* P frame */
2053       timestamp = dec->last_ts = dec->next_ts;
2054       if (seq < dec->next_seq)
2055         dec->next_ts += (seq + 0x2000 - dec->next_seq) * GST_MSECOND;
2056       else
2057         dec->next_ts += (seq - dec->next_seq) * GST_MSECOND;
2058       dec->last_seq = dec->next_seq;
2059       dec->next_seq = seq;
2060       break;
2061     }
2062     case 3:
2063     {
2064       /* B frame */
2065       if (seq < dec->last_seq) {
2066         timestamp = (seq + 0x2000 - dec->last_seq) * GST_MSECOND + dec->last_ts;
2067       } else {
2068         timestamp = (seq - dec->last_seq) * GST_MSECOND + dec->last_ts;
2069       }
2070
2071       break;
2072     }
2073     default:
2074       goto unknown_frame_type;
2075   }
2076   /* Errors */
2077 unknown_version:
2078   {
2079     GST_ELEMENT_ERROR (dec, STREAM, DECODE,
2080         ("Unknown version: %i.", dec->version), (NULL));
2081     return GST_FLOW_ERROR;
2082   }
2083
2084 unknown_frame_type:
2085   {
2086     GST_ELEMENT_ERROR (dec, STREAM, DECODE, ("Unknown frame type."), (NULL));
2087     return GST_FLOW_ERROR;
2088   }
2089 }
2090 #endif
2091
2092 #define PARSE_NUMBER(data, size, number, label) \
2093 G_STMT_START {                                  \
2094   if (size < 2)                                 \
2095     goto label;                                 \
2096   number = GST_READ_UINT16_BE (data);           \
2097   if (!(number & 0xc000)) {                     \
2098     if (size < 4)                               \
2099       goto label;                               \
2100     number = GST_READ_UINT32_BE (data);         \
2101     data += 4;                                  \
2102     size -= 4;                                  \
2103   } else {                                      \
2104     number &= 0x3fff;                           \
2105     data += 2;                                  \
2106     size -= 2;                                  \
2107   }                                             \
2108 } G_STMT_END
2109
2110 static GstFlowReturn
2111 gst_rmdemux_parse_video_packet (GstRMDemux * rmdemux, GstRMDemuxStream * stream,
2112     GstBuffer * in, guint offset, guint16 version,
2113     GstClockTime timestamp, gboolean key)
2114 {
2115   GstFlowReturn ret;
2116   const guint8 *data, *base;
2117   guint size;
2118
2119   base = GST_BUFFER_DATA (in);
2120   data = base + offset;
2121   size = GST_BUFFER_SIZE (in) - offset;
2122
2123   while (size > 2) {
2124     guint8 pkg_header;
2125     guint pkg_offset;
2126     guint pkg_length;
2127     guint pkg_subseq = 0, pkg_seqnum = -1;
2128     guint fragment_size;
2129     GstBuffer *fragment;
2130
2131     pkg_header = *data++;
2132     size--;
2133
2134     /* packet header
2135      * bit 7: 1=last block in block chain
2136      * bit 6: 1=short header (only one block?)
2137      */
2138     if ((pkg_header & 0xc0) == 0x40) {
2139       /* skip unknown byte */
2140       data++;
2141       size--;
2142       pkg_offset = 0;
2143       pkg_length = size;
2144     } else {
2145       if ((pkg_header & 0x40) == 0) {
2146         pkg_subseq = (*data++) & 0x7f;
2147         size--;
2148       } else {
2149         pkg_subseq = 0;
2150       }
2151
2152       /* length */
2153       PARSE_NUMBER (data, size, pkg_length, not_enough_data);
2154
2155       /* offset */
2156       PARSE_NUMBER (data, size, pkg_offset, not_enough_data);
2157
2158       /* seqnum */
2159       if (size < 1)
2160         goto not_enough_data;
2161
2162       pkg_seqnum = *data++;
2163       size--;
2164     }
2165
2166     GST_DEBUG_OBJECT (rmdemux,
2167         "seq %d, subseq %d, offset %d, length %d, size %d, header %02x",
2168         pkg_seqnum, pkg_subseq, pkg_offset, pkg_length, size, pkg_header);
2169
2170     /* calc size of fragment */
2171     if ((pkg_header & 0xc0) == 0x80) {
2172       fragment_size = pkg_offset;
2173     } else {
2174       if ((pkg_header & 0xc0) == 0)
2175         fragment_size = size;
2176       else
2177         fragment_size = pkg_length;
2178     }
2179     GST_DEBUG_OBJECT (rmdemux, "fragment size %d", fragment_size);
2180
2181     /* get the fragment */
2182     fragment = gst_buffer_create_sub (in, data - base, fragment_size);
2183
2184     if (pkg_subseq == 1) {
2185       GST_DEBUG_OBJECT (rmdemux, "start new fragment");
2186       gst_adapter_clear (stream->adapter);
2187       stream->frag_current = 0;
2188       stream->frag_count = 0;
2189       stream->frag_length = pkg_length;
2190     } else if (pkg_subseq == 0) {
2191       GST_DEBUG_OBJECT (rmdemux, "non fragmented packet");
2192       stream->frag_current = 0;
2193       stream->frag_count = 0;
2194       stream->frag_length = fragment_size;
2195     }
2196
2197     /* put fragment in adapter */
2198     gst_adapter_push (stream->adapter, fragment);
2199     stream->frag_offset[stream->frag_count] = stream->frag_current;
2200     stream->frag_current += fragment_size;
2201     stream->frag_count++;
2202
2203     if (stream->frag_count > MAX_FRAGS)
2204       goto too_many_fragments;
2205
2206     GST_DEBUG_OBJECT (rmdemux, "stored fragment in adapter %d/%d",
2207         stream->frag_current, stream->frag_length);
2208
2209     /* flush fragment when complete */
2210     if (stream->frag_current >= stream->frag_length) {
2211       GstBuffer *out;
2212       guint8 *outdata;
2213       guint header_size;
2214       gint i;
2215
2216       /* calculate header size, which is:
2217        * 1 byte for the number of fragments - 1
2218        * for each fragment:
2219        *   4 bytes 0x00000001 little endian
2220        *   4 bytes fragment offset
2221        *
2222        * This is also the matroska header for realvideo, the decoder needs the
2223        * fragment offsets, both in ffmpeg and real .so, so we just give it that
2224        * in front of the data.
2225        */
2226       header_size = 1 + (8 * (stream->frag_count));
2227
2228       GST_DEBUG_OBJECT (rmdemux,
2229           "fragmented completed. count %d, header_size %u", stream->frag_count,
2230           header_size);
2231
2232       out = gst_buffer_new_and_alloc (header_size + stream->frag_length);
2233       outdata = GST_BUFFER_DATA (out);
2234
2235       /* create header */
2236       *outdata++ = stream->frag_count - 1;
2237       for (i = 0; i < stream->frag_count; i++) {
2238         GST_WRITE_UINT32_LE (outdata, 0x00000001);
2239         outdata += 4;
2240         GST_WRITE_UINT32_LE (outdata, stream->frag_offset[i]);
2241         outdata += 4;
2242       }
2243
2244       /* copy packet data after the header now */
2245       gst_adapter_copy (stream->adapter, outdata, 0, stream->frag_length);
2246       gst_adapter_flush (stream->adapter, stream->frag_length);
2247
2248       gst_buffer_set_caps (out, GST_PAD_CAPS (stream->pad));
2249       GST_BUFFER_TIMESTAMP (out) = timestamp;
2250
2251       ret = gst_pad_push (stream->pad, out);
2252     }
2253     data += fragment_size;
2254     size -= fragment_size;
2255   }
2256   GST_DEBUG_OBJECT (rmdemux, "%d bytes left", size);
2257
2258   gst_buffer_unref (in);
2259
2260   ret = GST_FLOW_OK;
2261
2262   return ret;
2263
2264   /* ERRORS */
2265 not_enough_data:
2266   {
2267     GST_ELEMENT_WARNING (rmdemux, STREAM, DECODE, ("Skipping bad packet."),
2268         (NULL));
2269     gst_buffer_unref (in);
2270     return GST_FLOW_OK;
2271   }
2272 too_many_fragments:
2273   {
2274     GST_ELEMENT_ERROR (rmdemux, STREAM, DECODE,
2275         ("Got more fragments (%u) than can be handled (%u)",
2276             stream->frag_count, MAX_FRAGS), (NULL));
2277     gst_buffer_unref (in);
2278     return GST_FLOW_ERROR;
2279   }
2280 }
2281
2282 static GstFlowReturn
2283 gst_rmdemux_parse_audio_packet (GstRMDemux * rmdemux, GstRMDemuxStream * stream,
2284     GstBuffer * in, guint offset, guint16 version,
2285     GstClockTime timestamp, gboolean key)
2286 {
2287   GstFlowReturn ret, cret;
2288   GstBuffer *buffer;
2289   const guint8 *data;
2290   guint size;
2291
2292   data = GST_BUFFER_DATA (in) + offset;
2293   size = GST_BUFFER_SIZE (in) - offset;
2294
2295   ret = gst_pad_alloc_buffer_and_set_caps (stream->pad,
2296       GST_BUFFER_OFFSET_NONE, size, GST_PAD_CAPS (stream->pad), &buffer);
2297
2298   cret = gst_rmdemux_combine_flows (rmdemux, stream, ret);
2299   if (ret != GST_FLOW_OK)
2300     goto alloc_failed;
2301
2302   memcpy (GST_BUFFER_DATA (buffer), (guint8 *) data, size);
2303   GST_BUFFER_TIMESTAMP (buffer) = timestamp - rmdemux->first_ts;
2304
2305   if (stream->needs_descrambling) {
2306     ret = gst_rmdemux_handle_scrambled_packet (rmdemux, stream, buffer, key);
2307   } else {
2308     GST_LOG_OBJECT (rmdemux, "Pushing buffer of size %d to pad %s",
2309         GST_BUFFER_SIZE (buffer), GST_PAD_NAME (stream->pad));
2310
2311     ret = gst_pad_push (stream->pad, buffer);
2312   }
2313   return ret;
2314
2315   /* ERRORS */
2316 alloc_failed:
2317   {
2318     GST_DEBUG_OBJECT (rmdemux, "pad alloc returned %d", ret);
2319     return cret;
2320   }
2321 }
2322
2323 static GstFlowReturn
2324 gst_rmdemux_parse_packet (GstRMDemux * rmdemux, GstBuffer * in, guint16 version)
2325 {
2326   guint16 id;
2327   GstRMDemuxStream *stream;
2328   guint size;
2329   GstFlowReturn cret, ret;
2330   GstClockTime timestamp;
2331   gboolean key;
2332   guint8 *data, *base;
2333   guint8 flags;
2334
2335   base = data = GST_BUFFER_DATA (in);
2336   size = GST_BUFFER_SIZE (in);
2337
2338   /* stream number */
2339   id = RMDEMUX_GUINT16_GET (data);
2340
2341   stream = gst_rmdemux_get_stream_by_id (rmdemux, id);
2342   if (!stream || !stream->pad)
2343     goto unknown_stream;
2344
2345   /* timestamp in Msec */
2346   timestamp = RMDEMUX_GUINT32_GET (data + 2) * GST_MSECOND;
2347
2348   gst_segment_set_last_stop (&rmdemux->segment, GST_FORMAT_TIME, timestamp);
2349
2350   GST_LOG_OBJECT (rmdemux, "Parsing a packet for stream=%d, timestamp=%"
2351       GST_TIME_FORMAT ", size %u, version=%d", id, GST_TIME_ARGS (timestamp),
2352       size, version);
2353
2354   if (rmdemux->first_ts == GST_CLOCK_TIME_NONE) {
2355     GST_DEBUG_OBJECT (rmdemux, "First timestamp: %" GST_TIME_FORMAT,
2356         GST_TIME_ARGS (timestamp));
2357     rmdemux->first_ts = timestamp;
2358   }
2359
2360   /* skip stream_id and timestamp */
2361   data += (2 + 4);
2362   size -= (2 + 4);
2363
2364   /* skip other stuff */
2365   if (version == 0) {
2366     /* uint8 packet_group */
2367     /* uint8 flags        */
2368     flags = GST_READ_UINT8 (data + 1);
2369     data += 2;
2370     size -= 2;
2371   } else {
2372     /* uint16 asm_rule */
2373     /* uint8 asm_flags */
2374     flags = GST_READ_UINT8 (data + 2);
2375     data += 3;
2376     size -= 3;
2377   }
2378   key = (flags & 0x02) != 0;
2379   GST_DEBUG_OBJECT (rmdemux, "flags %d, Keyframe %d", flags, key);
2380
2381   if (rmdemux->need_newsegment) {
2382     GstEvent *event;
2383
2384     event = gst_event_new_new_segment (FALSE, rmdemux->segment.rate,
2385         rmdemux->segment.format, rmdemux->segment.start,
2386         rmdemux->segment.stop, rmdemux->segment.time);
2387
2388     GST_DEBUG_OBJECT (rmdemux, "sending NEWSEGMENT event, segment.start= %"
2389         GST_TIME_FORMAT, GST_TIME_ARGS (rmdemux->segment.start));
2390
2391     gst_rmdemux_send_event (rmdemux, event);
2392     rmdemux->need_newsegment = FALSE;
2393   }
2394
2395   if (stream->pending_tags != NULL) {
2396     GST_LOG_OBJECT (stream->pad, "tags %" GST_PTR_FORMAT, stream->pending_tags);
2397     gst_element_found_tags_for_pad (GST_ELEMENT_CAST (rmdemux), stream->pad,
2398         stream->pending_tags);
2399     stream->pending_tags = NULL;
2400   }
2401
2402   if ((rmdemux->offset + size) <= stream->seek_offset) {
2403     GST_DEBUG_OBJECT (rmdemux,
2404         "Stream %d is skipping: seek_offset=%d, offset=%d, size=%u",
2405         stream->id, stream->seek_offset, rmdemux->offset, size);
2406     cret = GST_FLOW_OK;
2407     goto beach;
2408   }
2409
2410   /* do special headers */
2411   if (stream->subtype == GST_RMDEMUX_STREAM_VIDEO) {
2412     ret =
2413         gst_rmdemux_parse_video_packet (rmdemux, stream, in, data - base,
2414         version, timestamp, key);
2415   } else if (stream->subtype == GST_RMDEMUX_STREAM_AUDIO) {
2416     ret =
2417         gst_rmdemux_parse_audio_packet (rmdemux, stream, in, data - base,
2418         version, timestamp, key);
2419   } else
2420     ret = GST_FLOW_OK;
2421
2422   cret = gst_rmdemux_combine_flows (rmdemux, stream, ret);
2423
2424 beach:
2425   return cret;
2426
2427   /* ERRORS */
2428 unknown_stream:
2429   {
2430     GST_WARNING_OBJECT (rmdemux, "No stream for stream id %d in parsing "
2431         "data packet", id);
2432     return GST_FLOW_OK;
2433   }
2434 }
2435
2436 static gboolean
2437 gst_rmdemux_plugin_init (GstPlugin * plugin)
2438 {
2439   return gst_element_register (plugin, "rmdemux",
2440       GST_RANK_PRIMARY, GST_TYPE_RMDEMUX) &&
2441       gst_element_register (plugin, "rademux",
2442       GST_RANK_SECONDARY, GST_TYPE_REAL_AUDIO_DEMUX);
2443 }
2444
2445
2446 static gboolean
2447 plugin_init (GstPlugin * plugin)
2448 {
2449   if (!gst_rmdemux_plugin_init (plugin))
2450     return FALSE;
2451
2452   if (!gst_rdt_depay_plugin_init (plugin))
2453     return FALSE;
2454
2455   if (!gst_rdt_manager_plugin_init (plugin))
2456     return FALSE;
2457
2458   if (!gst_rtsp_real_plugin_init (plugin))
2459     return FALSE;
2460
2461   return TRUE;
2462 }
2463
2464 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
2465     GST_VERSION_MINOR,
2466     "realmedia",
2467     "RealMedia demuxer and depayloader",
2468     plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);