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