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