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