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