gst/qtdemux/: Streamline tag handling and pass unparsed tags as binary blob in privat...
[platform/upstream/gstreamer.git] / gst / qtdemux / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 /**
24  * SECTION:element-qtdemux
25  *
26  * <refsect2>
27  * <para>
28  * Demuxes a .mov file into raw or compressed audio and/or video streams.
29  * </para>
30  * <para>
31  * This element supports both push and pull-based scheduling, depending on the
32  * capabilities of the upstream elements.
33  * </para>
34  * <title>Example launch line</title>
35  * <para>
36  * <programlisting>
37  * gst-launch filesrc location=test.mov ! qtdemux name=demux  demux.audio_00 ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_00 ! queue ! decodebin ! ffmpegcolorspace ! videoscale ! autovideosink
38  * </programlisting>
39  * Play (parse and decode) a .mov file and try to output it to
40  * an automatically detected soundcard and videosink. If the MOV file contains
41  * compressed audio or video data, this will only work if you have the
42  * right decoder elements/plugins installed.
43  * </para>
44  * </refsect2>
45  *
46  * Last reviewed on 2006-12-29 (0.10.5)
47  */
48
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include "gst/gst-i18n-plugin.h"
54
55 #include <gst/tag/tag.h>
56
57 #include "qtdemux_types.h"
58 #include "qtdemux_dump.h"
59 #include "qtdemux_fourcc.h"
60 #include "qtdemux.h"
61 #include "qtpalette.h"
62
63 #include <stdlib.h>
64 #include <string.h>
65
66 #ifdef HAVE_ZLIB
67 # include <zlib.h>
68 #endif
69
70 GST_DEBUG_CATEGORY (qtdemux_debug);
71
72 #if 0
73 #define qtdemux_dump_mem(a,b)  gst_util_dump_mem(a,b)
74 #else
75 #define qtdemux_dump_mem(a,b)   /* */
76 #endif
77
78 typedef struct _QtNode QtNode;
79 typedef struct _QtDemuxSegment QtDemuxSegment;
80 typedef struct _QtDemuxSample QtDemuxSample;
81
82 struct _QtNode
83 {
84   guint32 type;
85   guint8 *data;
86   gint len;
87 };
88
89 struct _QtDemuxSample
90 {
91   guint32 chunk;
92   guint32 size;
93   guint64 offset;
94   GstClockTimeDiff pts_offset;  /* Add this value to timestamp to get the pts */
95   guint64 timestamp;            /* In GstClockTime */
96   guint64 duration;             /* in GstClockTime */
97   gboolean keyframe;            /* TRUE when this packet is a keyframe */
98 };
99
100 /*
101  * Quicktime has tracks and segments. A track is a continuous piece of
102  * multimedia content. The track is not always played from start to finish but
103  * instead, pieces of the track are 'cut out' and played in sequence. This is
104  * what the segments do.
105  *
106  * Inside the track we have keyframes (K) and delta frames. The track has its
107  * own timing, which starts from 0 and extends to end. The position in the track
108  * is called the media_time.
109  *
110  * The segments now describe the pieces that should be played from this track
111  * and are basically tupples of media_time/duration/rate entries. We can have
112  * multiple segments and they are all played after one another. An example:
113  *
114  * segment 1: media_time: 1 second, duration: 1 second, rate 1
115  * segment 2: media_time: 3 second, duration: 2 second, rate 2
116  *
117  * To correctly play back this track, one must play: 1 second of media starting
118  * from media_time 1 followed by 2 seconds of media starting from media_time 3
119  * at a rate of 2.
120  *
121  * Each of the segments will be played at a specific time, the first segment at
122  * time 0, the second one after the duration of the first one, etc.. Note that
123  * the time in resulting playback is not identical to the media_time of the
124  * track anymore.
125  *
126  * Visually, assuming the track has 4 second of media_time:
127  *
128  *                (a)                   (b)          (c)              (d)
129  *         .-----------------------------------------------------------.
130  * track:  | K.....K.........K........K.......K.......K...........K... |
131  *         '-----------------------------------------------------------'
132  *         0              1              2              3              4    
133  *           .------------^              ^   .----------^              ^
134  *          /              .-------------'  /       .------------------'
135  *         /              /          .-----'       /
136  *         .--------------.         .--------------.
137  *         | segment 1    |         | segment 2    |
138  *         '--------------'         '--------------'
139  *       
140  * The challenge here is to cut out the right pieces of the track for each of
141  * the playback segments. This fortunatly can easily be done with the SEGMENT
142  * events of gstreamer.
143  *
144  * For playback of segment 1, we need to provide the decoder with the keyframe
145  * (a), in the above figure, but we must instruct it only to output the decoded
146  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
147  * position set to the time of the segment: 0.
148  *
149  * We then proceed to push data from keyframe (a) to frame (b). The decoder
150  * decodes but clips all before media_time 1.
151  * 
152  * After finishing a segment, we push out a new SEGMENT event with the clipping
153  * boundaries of the new data.
154  *
155  * This is a good usecase for the GStreamer accumulated SEGMENT events.
156  */
157
158 struct _QtDemuxSegment
159 {
160   /* global time and duration, all gst time */
161   guint64 time;
162   guint64 stop_time;
163   guint64 duration;
164   /* media time of trak, all gst time */
165   guint64 media_start;
166   guint64 media_stop;
167   gdouble rate;
168 };
169
170 struct _QtDemuxStream
171 {
172   GstPad *pad;
173
174   /* stream type */
175   guint32 subtype;
176   GstCaps *caps;
177   guint32 fourcc;
178
179   /* duration/scale */
180   guint64 duration;             /* in timescale */
181   guint32 timescale;
182
183   /* our samples */
184   guint32 n_samples;
185   QtDemuxSample *samples;
186   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
187   guint32 min_duration;         /* duration in timescale of first sample, used for figuring out
188                                    the framerate, in timescale units */
189
190   /* if we use chunks or samples */
191   gboolean sampled;
192   guint padding;
193
194   /* video info */
195   gint width;
196   gint height;
197   /* Numerator/denominator framerate */
198   gint fps_n;
199   gint fps_d;
200   guint16 bits_per_sample;
201   guint16 color_table_id;
202
203   /* audio info */
204   gdouble rate;
205   gint n_channels;
206   guint samples_per_packet;
207   guint samples_per_frame;
208   guint bytes_per_packet;
209   guint bytes_per_sample;
210   guint bytes_per_frame;
211   guint compression;
212
213   /* when a discontinuity is pending */
214   gboolean discont;
215
216   /* list of buffers to push first */
217   GSList *buffers;
218
219   /* if we need to clip this buffer. This is only needed for uncompressed
220    * data */
221   gboolean need_clip;
222
223   /* current position */
224   guint32 segment_index;
225   guint32 sample_index;
226   guint64 time_position;        /* in gst time */
227
228   /* the Gst segment we are processing out, used for clipping */
229   GstSegment segment;
230
231   /* last GstFlowReturn */
232   GstFlowReturn last_ret;
233
234   /* quicktime segments */
235   guint32 n_segments;
236   QtDemuxSegment *segments;
237   guint32 from_sample;
238   guint32 to_sample;
239 };
240
241 enum QtDemuxState
242 {
243   QTDEMUX_STATE_INITIAL,        /* Initial state (haven't got the header yet) */
244   QTDEMUX_STATE_HEADER,         /* Parsing the header */
245   QTDEMUX_STATE_MOVIE,          /* Parsing/Playing the media data */
246   QTDEMUX_STATE_BUFFER_MDAT     /* Buffering the mdat atom */
247 };
248
249 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
250 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
251
252 static const GstElementDetails gst_qtdemux_details =
253 GST_ELEMENT_DETAILS ("QuickTime demuxer",
254     "Codec/Demuxer",
255     "Demultiplex a QuickTime file into audio and video streams",
256     "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
257
258 static GstStaticPadTemplate gst_qtdemux_sink_template =
259     GST_STATIC_PAD_TEMPLATE ("sink",
260     GST_PAD_SINK,
261     GST_PAD_ALWAYS,
262     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
263         "application/x-3gp")
264     );
265
266 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
267 GST_STATIC_PAD_TEMPLATE ("video_%02d",
268     GST_PAD_SRC,
269     GST_PAD_SOMETIMES,
270     GST_STATIC_CAPS_ANY);
271
272 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
273 GST_STATIC_PAD_TEMPLATE ("audio_%02d",
274     GST_PAD_SRC,
275     GST_PAD_SOMETIMES,
276     GST_STATIC_CAPS_ANY);
277
278 static GstElementClass *parent_class = NULL;
279
280 static void gst_qtdemux_class_init (GstQTDemuxClass * klass);
281 static void gst_qtdemux_base_init (GstQTDemuxClass * klass);
282 static void gst_qtdemux_init (GstQTDemux * quicktime_demux);
283 static void gst_qtdemux_dispose (GObject * object);
284
285 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
286     GstStateChange transition);
287 static gboolean qtdemux_sink_activate (GstPad * sinkpad);
288 static gboolean qtdemux_sink_activate_pull (GstPad * sinkpad, gboolean active);
289 static gboolean qtdemux_sink_activate_push (GstPad * sinkpad, gboolean active);
290
291 static void gst_qtdemux_loop (GstPad * pad);
292 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf);
293 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstEvent * event);
294
295 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux, guint8 * buffer,
296     int length);
297 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
298     guint8 * buffer, int length);
299 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
300
301 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
302     QtDemuxStream * stream, GNode * esds, GstTagList * list);
303 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
304     QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
305     gchar ** codec_name);
306 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
307     QtDemuxStream * stream, guint32 fourcc, const guint8 * data, int len,
308     gchar ** codec_name);
309
310 GType
311 gst_qtdemux_get_type (void)
312 {
313   static GType qtdemux_type = 0;
314
315   if (!qtdemux_type) {
316     static const GTypeInfo qtdemux_info = {
317       sizeof (GstQTDemuxClass),
318       (GBaseInitFunc) gst_qtdemux_base_init, NULL,
319       (GClassInitFunc) gst_qtdemux_class_init,
320       NULL, NULL, sizeof (GstQTDemux), 0,
321       (GInstanceInitFunc) gst_qtdemux_init,
322     };
323
324     qtdemux_type =
325         g_type_register_static (GST_TYPE_ELEMENT, "GstQTDemux", &qtdemux_info,
326         0);
327   }
328   return qtdemux_type;
329 }
330
331 static void
332 gst_qtdemux_base_init (GstQTDemuxClass * klass)
333 {
334   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
335
336   gst_element_class_add_pad_template (element_class,
337       gst_static_pad_template_get (&gst_qtdemux_sink_template));
338   gst_element_class_add_pad_template (element_class,
339       gst_static_pad_template_get (&gst_qtdemux_videosrc_template));
340   gst_element_class_add_pad_template (element_class,
341       gst_static_pad_template_get (&gst_qtdemux_audiosrc_template));
342   gst_element_class_set_details (element_class, &gst_qtdemux_details);
343
344   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
345 }
346
347 static void
348 gst_qtdemux_class_init (GstQTDemuxClass * klass)
349 {
350   GObjectClass *gobject_class;
351   GstElementClass *gstelement_class;
352
353   gobject_class = (GObjectClass *) klass;
354   gstelement_class = (GstElementClass *) klass;
355
356   parent_class = g_type_class_peek_parent (klass);
357
358   gobject_class->dispose = gst_qtdemux_dispose;
359
360   gstelement_class->change_state = gst_qtdemux_change_state;
361 }
362
363 static void
364 gst_qtdemux_init (GstQTDemux * qtdemux)
365 {
366   qtdemux->sinkpad =
367       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
368   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
369   gst_pad_set_activatepull_function (qtdemux->sinkpad,
370       qtdemux_sink_activate_pull);
371   gst_pad_set_activatepush_function (qtdemux->sinkpad,
372       qtdemux_sink_activate_push);
373   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
374   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
375   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
376
377   qtdemux->state = QTDEMUX_STATE_INITIAL;
378   /* FIXME, use segment last_stop for this */
379   qtdemux->last_ts = GST_CLOCK_TIME_NONE;
380   qtdemux->pullbased = FALSE;
381   qtdemux->neededbytes = 16;
382   qtdemux->todrop = 0;
383   qtdemux->adapter = gst_adapter_new ();
384   qtdemux->offset = 0;
385   qtdemux->mdatoffset = GST_CLOCK_TIME_NONE;
386   qtdemux->mdatbuffer = NULL;
387   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
388 }
389
390 static void
391 gst_qtdemux_dispose (GObject * object)
392 {
393   GstQTDemux *qtdemux = GST_QTDEMUX (object);
394
395   if (qtdemux->adapter) {
396     g_object_unref (G_OBJECT (qtdemux->adapter));
397     qtdemux->adapter = NULL;
398   }
399
400   G_OBJECT_CLASS (parent_class)->dispose (object);
401 }
402
403 #if 0
404 static gboolean
405 gst_qtdemux_src_convert (GstPad * pad, GstFormat src_format, gint64 src_value,
406     GstFormat * dest_format, gint64 * dest_value)
407 {
408   gboolean res = TRUE;
409   QtDemuxStream *stream = gst_pad_get_element_private (pad);
410
411   if (stream->subtype == GST_MAKE_FOURCC ('v', 'i', 'd', 'e') &&
412       (src_format == GST_FORMAT_BYTES || *dest_format == GST_FORMAT_BYTES))
413     return FALSE;
414
415   switch (src_format) {
416     case GST_FORMAT_TIME:
417       switch (*dest_format) {
418         case GST_FORMAT_BYTES:
419           *dest_value = src_value * 1;  /* FIXME */
420           break;
421         case GST_FORMAT_DEFAULT:
422           *dest_value = src_value * 1;  /* FIXME */
423           break;
424         default:
425           res = FALSE;
426           break;
427       }
428       break;
429     case GST_FORMAT_BYTES:
430       switch (*dest_format) {
431         case GST_FORMAT_TIME:
432           *dest_value = src_value * 1;  /* FIXME */
433           break;
434         default:
435           res = FALSE;
436           break;
437       }
438       break;
439     case GST_FORMAT_DEFAULT:
440       switch (*dest_format) {
441         case GST_FORMAT_TIME:
442           *dest_value = src_value * 1;  /* FIXME */
443           break;
444         default:
445           res = FALSE;
446           break;
447       }
448       break;
449     default:
450       res = FALSE;
451   }
452
453   return res;
454 }
455 #endif
456
457 static const GstQueryType *
458 gst_qtdemux_get_src_query_types (GstPad * pad)
459 {
460   static const GstQueryType src_types[] = {
461     GST_QUERY_POSITION,
462     GST_QUERY_DURATION,
463     GST_QUERY_SEEKING,
464     0
465   };
466
467   return src_types;
468 }
469
470 static gboolean
471 gst_qtdemux_get_duration (GstQTDemux * qtdemux, gint64 * duration)
472 {
473   gboolean res = TRUE;
474
475   *duration = GST_CLOCK_TIME_NONE;
476
477   if (qtdemux->duration != 0) {
478     if (qtdemux->duration != G_MAXINT32 && qtdemux->timescale != 0) {
479       *duration = gst_util_uint64_scale (qtdemux->duration,
480           GST_SECOND, qtdemux->timescale);
481     }
482   }
483   return res;
484 }
485
486 static gboolean
487 gst_qtdemux_handle_src_query (GstPad * pad, GstQuery * query)
488 {
489   gboolean res = FALSE;
490   GstQTDemux *qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
491
492   switch (GST_QUERY_TYPE (query)) {
493     case GST_QUERY_POSITION:
494       if (GST_CLOCK_TIME_IS_VALID (qtdemux->segment.last_stop)) {
495         gst_query_set_position (query, GST_FORMAT_TIME,
496             qtdemux->segment.last_stop);
497         res = TRUE;
498       }
499       break;
500     case GST_QUERY_DURATION:{
501       GstFormat fmt;
502
503       gst_query_parse_duration (query, &fmt, NULL);
504       if (fmt == GST_FORMAT_TIME) {
505         gint64 duration = -1;
506
507         gst_qtdemux_get_duration (qtdemux, &duration);
508         if (duration > 0) {
509           gst_query_set_duration (query, GST_FORMAT_TIME, duration);
510           res = TRUE;
511         }
512       }
513       break;
514     }
515     case GST_QUERY_SEEKING:{
516       GstFormat fmt;
517
518       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
519       if (fmt == GST_FORMAT_TIME) {
520         gint64 duration = -1;
521
522         gst_qtdemux_get_duration (qtdemux, &duration);
523         gst_query_set_seeking (query, GST_FORMAT_TIME, qtdemux->pullbased,
524             0, duration);
525         res = TRUE;
526       }
527       break;
528     }
529     default:
530       res = gst_pad_query_default (pad, query);
531       break;
532   }
533
534   gst_object_unref (qtdemux);
535
536   return res;
537 }
538
539 /* push event on all source pads; takes ownership of the event */
540 static void
541 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
542 {
543   guint n;
544
545   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
546       GST_EVENT_TYPE_NAME (event));
547
548   for (n = 0; n < qtdemux->n_streams; n++) {
549     GstPad *pad;
550
551     if ((pad = qtdemux->streams[n]->pad))
552       gst_pad_push_event (pad, gst_event_ref (event));
553   }
554   gst_event_unref (event);
555 }
556
557 /* push a pending newsegment event, if any from the streaming thread */
558 static void
559 gst_qtdemux_push_pending_newsegment (GstQTDemux * qtdemux)
560 {
561   if (qtdemux->pending_newsegment) {
562     gst_qtdemux_push_event (qtdemux, qtdemux->pending_newsegment);
563     qtdemux->pending_newsegment = NULL;
564   }
565 }
566
567 /* find the index of the sample that includes the data for @media_time
568  *
569  * Returns the index of the sample or n_samples when the sample was not
570  * found.
571  */
572 /* FIXME, binary search would be nice here */
573 static guint32
574 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
575     guint64 media_time)
576 {
577   guint32 i;
578
579   if (str->n_samples == 0)
580     return 0;
581
582   for (i = 0; i < str->n_samples; i++) {
583     if (str->samples[i].timestamp > media_time) {
584       /* first sample after media_time, we need the previous one */
585       return (i == 0 ? 0 : i - 1);
586     }
587   }
588   return str->n_samples - 1;
589 }
590
591 /* find the index of the keyframe needed to decode the sample at @index
592  * of stream @str.
593  *
594  * Returns the index of the keyframe.
595  */
596 static guint32
597 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
598     guint32 index)
599 {
600   guint32 new_index = index;
601
602   if (index >= str->n_samples) {
603     new_index = str->n_samples;
604     goto beach;
605   }
606
607   /* all keyframes, return index */
608   if (str->all_keyframe) {
609     new_index = index;
610     goto beach;
611   }
612
613   /* else go back until we have a keyframe */
614   while (TRUE) {
615     if (str->samples[new_index].keyframe)
616       break;
617
618     if (new_index == 0)
619       break;
620
621     new_index--;
622   }
623
624 beach:
625   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index before index %u "
626       "gave %u", index, new_index);
627
628   return new_index;
629 }
630
631 /* find the segment for @time_position for @stream
632  *
633  * Returns -1 if the segment cannot be found.
634  */
635 static guint32
636 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
637     guint64 time_position)
638 {
639   gint i;
640   guint32 seg_idx;
641
642   GST_LOG_OBJECT (qtdemux, "finding segment for %" GST_TIME_FORMAT,
643       GST_TIME_ARGS (time_position));
644
645   /* find segment corresponding to time_position if we are looking
646    * for a segment. */
647   seg_idx = -1;
648   for (i = 0; i < stream->n_segments; i++) {
649     QtDemuxSegment *segment = &stream->segments[i];
650
651     GST_LOG_OBJECT (qtdemux,
652         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
653         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
654
655     /* For the last segment we include stop_time in the last segment */
656     if (i < stream->n_segments - 1) {
657       if (segment->time <= time_position && time_position < segment->stop_time) {
658         GST_LOG_OBJECT (qtdemux, "segment %d matches", i);
659         seg_idx = i;
660         break;
661       }
662     } else {
663       if (segment->time <= time_position && time_position <= segment->stop_time) {
664         GST_LOG_OBJECT (qtdemux, "segment %d matches", i);
665         seg_idx = i;
666         break;
667       }
668     }
669   }
670   return seg_idx;
671 }
672
673 /* move the stream @str to the sample position @index.
674  *
675  * Updates @str->sample_index and marks discontinuity if needed.
676  */
677 static void
678 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
679     guint32 index)
680 {
681   /* no change needed */
682   if (index == str->sample_index)
683     return;
684
685   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
686       str->n_samples);
687
688   /* position changed, we have a discont */
689   str->sample_index = index;
690   /* Each time we move in the stream we store the position where we are 
691    * starting from */
692   str->from_sample = index;
693   str->discont = TRUE;
694 }
695
696 /* perform the seek.
697  *
698  * We set all segment_indexes in the streams to unknown and
699  * adjust the time_position to the desired position. this is enough
700  * to trigger a segment switch in the streaming thread to start
701  * streaming from the desired position.
702  *
703  * Keyframe seeking is a little more complicated when dealing with
704  * segments. Ideally we want to move to the previous keyframe in
705  * the segment but there might not be a keyframe in the segment. In
706  * fact, none of the segments could contain a keyframe. We take a
707  * practical approach: seek to the previous keyframe in the segment,
708  * if there is none, seek to the beginning of the segment.
709  *
710  * Called with STREAM_LOCK
711  */
712 static gboolean
713 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment)
714 {
715   gint64 desired_offset;
716   gint n;
717
718   desired_offset = segment->last_stop;
719
720   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
721       GST_TIME_ARGS (desired_offset));
722
723   if (segment->flags & GST_SEEK_FLAG_KEY_UNIT) {
724     guint64 min_offset;
725
726     min_offset = desired_offset;
727
728     /* for each stream, find the index of the sample in the segment
729      * and move back to the previous keyframe. */
730     for (n = 0; n < qtdemux->n_streams; n++) {
731       QtDemuxStream *str;
732       guint32 index, kindex;
733       guint32 seg_idx;
734       guint64 media_start;
735       guint64 media_time;
736       guint64 seg_time;
737       QtDemuxSegment *seg;
738
739       str = qtdemux->streams[n];
740
741       seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_offset);
742       GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
743
744       /* segment not found, continue with normal flow */
745       if (seg_idx == -1)
746         continue;
747
748       /* get segment and time in the segment */
749       seg = &str->segments[seg_idx];
750       seg_time = desired_offset - seg->time;
751
752       /* get the media time in the segment */
753       media_start = seg->media_start + seg_time;
754
755       /* get the index of the sample with media time */
756       index = gst_qtdemux_find_index (qtdemux, str, media_start);
757       GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u",
758           GST_TIME_ARGS (media_start), index);
759
760       /* find previous keyframe */
761       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index);
762
763       /* if the keyframe is at a different position, we need to update the
764        * requiested seek time */
765       if (index != kindex) {
766         index = kindex;
767
768         /* get timestamp of keyframe */
769         media_time = str->samples[kindex].timestamp;
770         GST_DEBUG_OBJECT (qtdemux, "keyframe at %u with time %" GST_TIME_FORMAT,
771             kindex, GST_TIME_ARGS (media_time));
772
773         /* keyframes in the segment get a chance to change the
774          * desired_offset. keyframes out of the segment are
775          * ignored. */
776         if (media_time >= seg->media_start) {
777           guint64 seg_time;
778
779           /* this keyframe is inside the segment, convert back to
780            * segment time */
781           seg_time = (media_time - seg->media_start) + seg->time;
782           if (seg_time < min_offset)
783             min_offset = seg_time;
784         }
785       }
786     }
787     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
788         GST_TIME_FORMAT, GST_TIME_ARGS (desired_offset));
789     desired_offset = min_offset;
790   }
791
792   /* and set all streams to the final position */
793   for (n = 0; n < qtdemux->n_streams; n++) {
794     QtDemuxStream *stream = qtdemux->streams[n];
795
796     stream->time_position = desired_offset;
797     stream->sample_index = -1;
798     stream->segment_index = -1;
799     stream->last_ret = GST_FLOW_OK;
800   }
801   segment->last_stop = desired_offset;
802   segment->time = desired_offset;
803
804   /* we stop at the end */
805   if (segment->stop == -1)
806     segment->stop = segment->duration;
807
808   return TRUE;
809 }
810
811 /* do a seek in pull based mode */
812 static gboolean
813 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
814 {
815   gdouble rate;
816   GstFormat format;
817   GstSeekFlags flags;
818   GstSeekType cur_type, stop_type;
819   gint64 cur, stop;
820   gboolean flush;
821   gboolean res;
822   gboolean update;
823   GstSegment seeksegment;
824   int i;
825
826   if (event) {
827     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
828
829     gst_event_parse_seek (event, &rate, &format, &flags,
830         &cur_type, &cur, &stop_type, &stop);
831
832     /* we have to have a format as the segment format. Try to convert
833      * if not. */
834     if (format != GST_FORMAT_TIME) {
835       GstFormat fmt;
836
837       fmt = GST_FORMAT_TIME;
838       res = TRUE;
839       if (cur_type != GST_SEEK_TYPE_NONE)
840         res = gst_pad_query_convert (pad, format, cur, &fmt, &cur);
841       if (res && stop_type != GST_SEEK_TYPE_NONE)
842         res = gst_pad_query_convert (pad, format, stop, &fmt, &stop);
843       if (!res)
844         goto no_format;
845
846       format = fmt;
847     }
848   } else {
849     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
850     flags = 0;
851   }
852
853   flush = flags & GST_SEEK_FLAG_FLUSH;
854
855   GST_DEBUG_OBJECT (qtdemux, "seek format %d", format);
856
857   /* stop streaming, either by flushing or by pausing the task */
858   if (flush) {
859     /* unlock upstream pull_range */
860     gst_pad_push_event (qtdemux->sinkpad, gst_event_new_flush_start ());
861     /* make sure out loop function exits */
862     gst_qtdemux_push_event (qtdemux, gst_event_new_flush_start ());
863   } else {
864     /* non flushing seek, pause the task */
865     gst_pad_pause_task (qtdemux->sinkpad);
866   }
867
868   /* wait for streaming to finish */
869   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
870
871   /* copy segment, we need this because we still need the old
872    * segment when we close the current segment. */
873   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
874
875   if (event) {
876     /* configure the segment with the seek variables */
877     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
878     gst_segment_set_seek (&seeksegment, rate, format, flags,
879         cur_type, cur, stop_type, stop, &update);
880   }
881
882   /* now do the seek, this actually never returns FALSE */
883   res = gst_qtdemux_perform_seek (qtdemux, &seeksegment);
884
885   /* prepare for streaming again */
886   if (flush) {
887     gst_pad_push_event (qtdemux->sinkpad, gst_event_new_flush_stop ());
888     gst_qtdemux_push_event (qtdemux, gst_event_new_flush_stop ());
889   } else if (qtdemux->segment_running) {
890     /* we are running the current segment and doing a non-flushing seek,
891      * close the segment first based on the last_stop. */
892     GST_DEBUG_OBJECT (qtdemux, "closing running segment %" G_GINT64_FORMAT
893         " to %" G_GINT64_FORMAT, qtdemux->segment.start,
894         qtdemux->segment.last_stop);
895
896     if (qtdemux->segment.rate >= 0) {
897       /* FIXME, rate is the product of the global rate and the (quicktime)
898        * segment rate. */
899       qtdemux->pending_newsegment = gst_event_new_new_segment (TRUE,
900           qtdemux->segment.rate, qtdemux->segment.format,
901           qtdemux->segment.start, qtdemux->segment.last_stop,
902           qtdemux->segment.time);
903     } else {                    /* For Reverse Playback */
904       guint64 stop;
905
906       if ((stop = qtdemux->segment.stop) == -1)
907         stop = qtdemux->segment.duration;
908       /* for reverse playback, we played from stop to last_stop. */
909       qtdemux->pending_newsegment = gst_event_new_new_segment (TRUE,
910           qtdemux->segment.rate, qtdemux->segment.format,
911           qtdemux->segment.last_stop, stop, qtdemux->segment.last_stop);
912     }
913   }
914
915   /* commit the new segment */
916   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
917
918   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
919     gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
920         gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
921             qtdemux->segment.format, qtdemux->segment.last_stop));
922   }
923
924   /* restart streaming, NEWSEGMENT will be sent from the streaming
925    * thread. */
926   qtdemux->segment_running = TRUE;
927   for (i = 0; i < qtdemux->n_streams; i++)
928     qtdemux->streams[i]->last_ret = GST_FLOW_OK;
929
930   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
931       qtdemux->sinkpad);
932
933   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
934
935   return TRUE;
936
937   /* ERRORS */
938 no_format:
939   {
940     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
941     return FALSE;
942   }
943 }
944
945 static gboolean
946 gst_qtdemux_handle_src_event (GstPad * pad, GstEvent * event)
947 {
948   gboolean res = TRUE;
949   GstQTDemux *qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
950
951   switch (GST_EVENT_TYPE (event)) {
952     case GST_EVENT_SEEK:
953       if (qtdemux->pullbased) {
954         res = gst_qtdemux_do_seek (qtdemux, pad, event);
955       } else {
956         GST_DEBUG_OBJECT (qtdemux, "cannot seek in streaming mode");
957         res = FALSE;
958       }
959       gst_event_unref (event);
960       break;
961     case GST_EVENT_QOS:
962     case GST_EVENT_NAVIGATION:
963       res = FALSE;
964       gst_event_unref (event);
965       break;
966     default:
967       res = gst_pad_event_default (pad, event);
968       break;
969   }
970
971   gst_object_unref (qtdemux);
972
973   return res;
974 }
975
976 static gboolean
977 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstEvent * event)
978 {
979   GstQTDemux *demux = GST_QTDEMUX (GST_PAD_PARENT (sinkpad));
980   gboolean res;
981
982   switch (GST_EVENT_TYPE (event)) {
983     case GST_EVENT_NEWSEGMENT:
984       /* We need to convert it to a GST_FORMAT_TIME new segment */
985       gst_event_unref (event);
986       res = TRUE;
987       break;
988     default:
989       res = gst_pad_event_default (demux->sinkpad, event);
990       break;
991   }
992
993   return res;
994 }
995
996 static GstStateChangeReturn
997 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
998 {
999   GstQTDemux *qtdemux = GST_QTDEMUX (element);
1000   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
1001
1002   switch (transition) {
1003     case GST_STATE_CHANGE_PAUSED_TO_READY:
1004       break;
1005     default:
1006       break;
1007   }
1008
1009   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1010
1011   switch (transition) {
1012     case GST_STATE_CHANGE_PAUSED_TO_READY:{
1013       gint n;
1014
1015       qtdemux->state = QTDEMUX_STATE_INITIAL;
1016       qtdemux->last_ts = GST_CLOCK_TIME_NONE;
1017       qtdemux->neededbytes = 16;
1018       qtdemux->todrop = 0;
1019       qtdemux->pullbased = FALSE;
1020       qtdemux->offset = 0;
1021       qtdemux->mdatoffset = GST_CLOCK_TIME_NONE;
1022       if (qtdemux->mdatbuffer)
1023         gst_buffer_unref (qtdemux->mdatbuffer);
1024       qtdemux->mdatbuffer = NULL;
1025       gst_adapter_clear (qtdemux->adapter);
1026       for (n = 0; n < qtdemux->n_streams; n++) {
1027         QtDemuxStream *stream = qtdemux->streams[n];
1028
1029         while (stream->buffers) {
1030           gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
1031           stream->buffers =
1032               g_slist_delete_link (stream->buffers, stream->buffers);
1033         }
1034         if (stream->pad)
1035           gst_element_remove_pad (element, stream->pad);
1036         if (stream->samples)
1037           g_free (stream->samples);
1038         if (stream->caps)
1039           gst_caps_unref (stream->caps);
1040         if (stream->segments)
1041           g_free (stream->segments);
1042         g_free (stream);
1043       }
1044       qtdemux->major_brand = 0;
1045       qtdemux->n_streams = 0;
1046       qtdemux->n_video_streams = 0;
1047       qtdemux->n_audio_streams = 0;
1048       gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
1049       break;
1050     }
1051     default:
1052       break;
1053   }
1054
1055   return result;
1056 }
1057
1058 static void
1059 extract_initial_length_and_fourcc (guint8 * data, guint64 * plength,
1060     guint32 * pfourcc)
1061 {
1062   guint64 length;
1063   guint32 fourcc;
1064
1065   length = QT_UINT32 (data);
1066   GST_DEBUG ("length %08" G_GINT64_MODIFIER "x", length);
1067   fourcc = QT_FOURCC (data + 4);
1068   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
1069
1070   if (length == 0) {
1071     length = G_MAXUINT32;
1072   } else if (length == 1) {
1073     /* this means we have an extended size, which is the 64 bit value of
1074      * the next 8 bytes */
1075     length = QT_UINT64 (data + 8);
1076     GST_DEBUG ("length %08llx", length);
1077   }
1078
1079   if (plength)
1080     *plength = length;
1081   if (pfourcc)
1082     *pfourcc = fourcc;
1083 }
1084
1085 static GstFlowReturn
1086 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
1087 {
1088   guint64 length;
1089   guint32 fourcc;
1090   GstBuffer *buf = NULL;
1091   GstFlowReturn ret = GST_FLOW_OK;
1092   guint64 cur_offset = qtdemux->offset;
1093
1094   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
1095   if (ret != GST_FLOW_OK)
1096     goto beach;
1097   extract_initial_length_and_fourcc (GST_BUFFER_DATA (buf), &length, &fourcc);
1098   gst_buffer_unref (buf);
1099
1100   if (length == 0) {
1101     GST_ELEMENT_ERROR (qtdemux, STREAM, DECODE,
1102         (_("This file is invalid and cannot be played.")),
1103         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
1104             GST_FOURCC_ARGS (fourcc)));
1105     ret = GST_FLOW_ERROR;
1106     goto beach;
1107   }
1108
1109   switch (fourcc) {
1110     case FOURCC_mdat:
1111     case FOURCC_free:
1112     case FOURCC_wide:
1113     case FOURCC_PICT:
1114     case FOURCC_pnot:
1115     {
1116       GST_LOG_OBJECT (qtdemux,
1117           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
1118           GST_FOURCC_ARGS (fourcc), cur_offset);
1119       cur_offset += length;
1120       qtdemux->offset += length;
1121       break;
1122     }
1123     case FOURCC_moov:
1124     {
1125       GstBuffer *moov;
1126
1127       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
1128       if (ret != GST_FLOW_OK)
1129         goto beach;
1130       if (length != GST_BUFFER_SIZE (moov)) {
1131         GST_ELEMENT_ERROR (qtdemux, STREAM, DECODE,
1132             (_("This file is incomplete and cannot be played.")),
1133             ("We got less than expected (received %u, wanted %u)",
1134                 GST_BUFFER_SIZE (moov), (guint) length));
1135         ret = GST_FLOW_ERROR;
1136         goto beach;
1137       }
1138       cur_offset += length;
1139       qtdemux->offset += length;
1140
1141       qtdemux_parse_moov (qtdemux, GST_BUFFER_DATA (moov), length);
1142       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
1143
1144       qtdemux_parse_tree (qtdemux);
1145       g_node_destroy (qtdemux->moov_node);
1146       gst_buffer_unref (moov);
1147       qtdemux->moov_node = NULL;
1148       qtdemux->state = QTDEMUX_STATE_MOVIE;
1149       GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
1150           qtdemux->state);
1151       break;
1152     }
1153     case FOURCC_ftyp:
1154     {
1155       GstBuffer *ftyp;
1156
1157       /* extract major brand; might come in handy for ISO vs QT issues */
1158       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &ftyp);
1159       if (ret != GST_FLOW_OK)
1160         goto beach;
1161       cur_offset += length;
1162       qtdemux->offset += length;
1163       /* only consider at least a sufficiently complete ftyp atom */
1164       if (length >= 20) {
1165         qtdemux->major_brand = QT_FOURCC (GST_BUFFER_DATA (ftyp) + 8);
1166         GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
1167             GST_FOURCC_ARGS (qtdemux->major_brand));
1168       }
1169       gst_buffer_unref (ftyp);
1170       break;
1171     }
1172     default:
1173     {
1174       GST_LOG_OBJECT (qtdemux,
1175           "unknown %08x '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT, fourcc,
1176           GST_FOURCC_ARGS (fourcc), cur_offset);
1177       cur_offset += length;
1178       qtdemux->offset += length;
1179       break;
1180     }
1181   }
1182
1183 beach:
1184   return ret;
1185 }
1186
1187 /* Seeks to the previous keyframe of the indexed stream and 
1188  * aligns other streams with respect to the keyframe timestamp 
1189  * of indexed stream. Only called in case of Reverse Playback
1190  */
1191 static GstFlowReturn
1192 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
1193 {
1194   guint8 n = 0;
1195   guint32 seg_idx = 0, k_index = 0;
1196   guint64 k_pos = 0, last_stop = 0;
1197   QtDemuxSegment *seg = NULL;
1198   QtDemuxStream *ref_str = NULL;
1199
1200   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
1201    * and finally align all the other streams on that timestamp with their 
1202    * respective keyframes */
1203   for (n = 0; n < qtdemux->n_streams; n++) {
1204     QtDemuxStream *str = qtdemux->streams[n];
1205
1206     seg_idx = gst_qtdemux_find_segment (qtdemux, str,
1207         qtdemux->segment.last_stop);
1208
1209     /* segment not found, continue with normal flow */
1210     if (seg_idx == -1)
1211       continue;
1212
1213     /* No candidate yet, take that one */
1214     if (!ref_str) {
1215       ref_str = str;
1216       continue;
1217     }
1218
1219     /* So that stream has a segment, we prefer video streams */
1220     if (str->subtype == FOURCC_vide) {
1221       ref_str = str;
1222       break;
1223     }
1224   }
1225
1226   if (G_UNLIKELY (!ref_str)) {
1227     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
1228     goto eos;
1229   }
1230
1231   if (G_UNLIKELY (!ref_str->from_sample)) {
1232     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
1233     goto eos;
1234   }
1235
1236   /* So that stream has been playing from from_sample to to_sample. We will
1237    * get the timestamp of the previous sample and search for a keyframe before
1238    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
1239   if (ref_str->subtype == FOURCC_vide) {
1240     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
1241         ref_str->from_sample - 1);
1242   } else {
1243     k_index = ref_str->from_sample - 10;
1244   }
1245
1246   /* get current segment for that stream */
1247   seg = &ref_str->segments[ref_str->segment_index];
1248   /* Crawl back through segments to find the one containing this I frame */
1249   while (ref_str->samples[k_index].timestamp < seg->media_start) {
1250     GST_DEBUG_OBJECT (qtdemux, "keyframe position is out of segment %u",
1251         ref_str->segment_index);
1252     if (G_UNLIKELY (!ref_str->segment_index)) {
1253       /* Reached first segment, let's consider it's EOS */
1254       goto eos;
1255     }
1256     ref_str->segment_index--;
1257     seg = &ref_str->segments[ref_str->segment_index];
1258   }
1259   /* Calculate time position of the keyframe and where we should stop */
1260   k_pos = (ref_str->samples[k_index].timestamp - seg->media_start) + seg->time;
1261   last_stop = ref_str->samples[ref_str->from_sample].timestamp;
1262   last_stop = (last_stop - seg->media_start) + seg->time;
1263
1264   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
1265       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
1266       k_index, GST_TIME_ARGS (k_pos));
1267
1268   /* Set last_stop with the keyframe timestamp we pushed of that stream */
1269   gst_segment_set_last_stop (&qtdemux->segment, GST_FORMAT_TIME, last_stop);
1270   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
1271       GST_TIME_ARGS (last_stop));
1272
1273   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
1274     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
1275     goto eos;
1276   }
1277
1278   /* Align them all on this */
1279   for (n = 0; n < qtdemux->n_streams; n++) {
1280     guint32 index = 0;
1281     guint64 media_start = 0, seg_time = 0;
1282     QtDemuxStream *str = qtdemux->streams[n];
1283
1284     seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
1285     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1286
1287     /* segment not found, continue with normal flow */
1288     if (seg_idx == -1)
1289       continue;
1290
1291     /* get segment and time in the segment */
1292     seg = &str->segments[seg_idx];
1293     seg_time = k_pos - seg->time;
1294
1295     /* get the media time in the segment */
1296     media_start = seg->media_start + seg_time;
1297
1298     /* get the index of the sample with media time */
1299     index = gst_qtdemux_find_index (qtdemux, str, media_start);
1300     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u",
1301         GST_TIME_ARGS (media_start), index);
1302
1303     /* find previous keyframe */
1304     k_index = gst_qtdemux_find_keyframe (qtdemux, str, index);
1305
1306     /* Remember until where we want to go */
1307     str->to_sample = str->from_sample - 1;
1308     /* Define our time position */
1309     str->time_position =
1310         (str->samples[k_index].timestamp - seg->media_start) + seg->time;
1311     /* Now seek back in time */
1312     gst_qtdemux_move_stream (qtdemux, str, k_index);
1313     GST_DEBUG_OBJECT (qtdemux, "keyframe at %u, time position %"
1314         GST_TIME_FORMAT " playing from sample %u to %u", k_index,
1315         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
1316   }
1317
1318   return GST_FLOW_OK;
1319
1320 eos:
1321   return GST_FLOW_UNEXPECTED;
1322 }
1323
1324 /* activate the given segment number @seg_idx of @stream at time @offset.
1325  * @offset is an absolute global position over all the segments.
1326  *
1327  * This will push out a NEWSEGMENT event with the right values and
1328  * position the stream index to the first decodable sample before
1329  * @offset.
1330  */
1331 static gboolean
1332 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1333     guint32 seg_idx, guint64 offset)
1334 {
1335   GstEvent *event;
1336   QtDemuxSegment *segment;
1337   guint32 index, kf_index;
1338   guint64 seg_time;
1339   guint64 start, stop, time;
1340   gdouble rate;
1341
1342   GST_LOG_OBJECT (qtdemux, "activate segment %d, offset %" G_GUINT64_FORMAT,
1343       seg_idx, offset);
1344
1345   /* update the current segment */
1346   stream->segment_index = seg_idx;
1347
1348   /* get the segment */
1349   segment = &stream->segments[seg_idx];
1350
1351   if (offset < segment->time) {
1352     GST_WARNING_OBJECT (qtdemux, "offset < segment->time %" G_GUINT64_FORMAT,
1353         segment->time);
1354     return FALSE;
1355   }
1356
1357   /* get time in this segment */
1358   seg_time = offset - segment->time;
1359
1360   GST_LOG_OBJECT (qtdemux, "seg_time %" GST_TIME_FORMAT,
1361       GST_TIME_ARGS (seg_time));
1362
1363   if (seg_time > segment->duration) {
1364     GST_LOG_OBJECT (qtdemux, "seg_time > segment->duration %" GST_TIME_FORMAT,
1365         GST_TIME_ARGS (segment->duration));
1366     return FALSE;
1367   }
1368
1369   /* qtdemux->segment.stop is in outside-time-realm, whereas
1370    * segment->media_stop is in track-time-realm.
1371    * 
1372    * In order to compare the two, we need to bring segment.stop
1373    * into the track-time-realm */
1374
1375   if (qtdemux->segment.stop == -1)
1376     stop = segment->media_stop;
1377   else
1378     stop =
1379         MIN (segment->media_stop,
1380         qtdemux->segment.stop - segment->time + segment->media_start);
1381
1382   if (qtdemux->segment.rate >= 0) {
1383     start = MIN (segment->media_start + seg_time, stop);
1384     time = offset;
1385   } else {
1386     start = segment->media_start;
1387     stop = MIN (segment->media_start + seg_time, stop);
1388     time = segment->time;
1389   }
1390
1391   GST_DEBUG_OBJECT (qtdemux, "newsegment %d from %" GST_TIME_FORMAT
1392       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
1393       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
1394
1395   /* combine global rate with that of the segment */
1396   rate = segment->rate * qtdemux->segment.rate;
1397
1398   /* update the segment values used for clipping */
1399   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1400   gst_segment_set_newsegment (&stream->segment, FALSE, rate, GST_FORMAT_TIME,
1401       start, stop, time);
1402
1403   /* now prepare and send the segment */
1404   if (stream->pad) {
1405     event = gst_event_new_new_segment (FALSE, rate, GST_FORMAT_TIME,
1406         start, stop, time);
1407     gst_pad_push_event (stream->pad, event);
1408     /* assume we can send more data now */
1409     stream->last_ret = GST_FLOW_OK;
1410   }
1411
1412   /* and move to the keyframe before the indicated media time of the
1413    * segment */
1414   if (qtdemux->segment.rate >= 0) {
1415     index = gst_qtdemux_find_index (qtdemux, stream, start);
1416     stream->to_sample = stream->n_samples;
1417     GST_DEBUG_OBJECT (qtdemux, "moving data pointer to %" GST_TIME_FORMAT
1418         ", index: %u, pts %" GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
1419         GST_TIME_ARGS (stream->samples[index].timestamp));
1420   } else {
1421     index = gst_qtdemux_find_index (qtdemux, stream, stop);
1422     stream->to_sample = index;
1423     GST_DEBUG_OBJECT (qtdemux, "moving data pointer to %" GST_TIME_FORMAT
1424         ", index: %u, pts %" GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
1425         GST_TIME_ARGS (stream->samples[index].timestamp));
1426   }
1427
1428   /* we're at the right spot */
1429   if (index == stream->sample_index) {
1430     GST_DEBUG_OBJECT (qtdemux, "we are at the right index");
1431     return TRUE;
1432   }
1433
1434   /* find keyframe of the target index */
1435   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index);
1436
1437   /* if we move forwards, we don't have to go back to the previous
1438    * keyframe since we already sent that. We can also just jump to
1439    * the keyframe right before the target index if there is one. */
1440   if (index > stream->sample_index) {
1441     /* moving forwards check if we move past a keyframe */
1442     if (kf_index > stream->sample_index) {
1443       GST_DEBUG_OBJECT (qtdemux, "moving forwards to keyframe at %u (pts %"
1444           GST_TIME_FORMAT, kf_index,
1445           GST_TIME_ARGS (stream->samples[kf_index].timestamp));
1446       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
1447     } else {
1448       GST_DEBUG_OBJECT (qtdemux, "moving forwards, keyframe at %u (pts %"
1449           GST_TIME_FORMAT " already sent", kf_index,
1450           GST_TIME_ARGS (stream->samples[kf_index].timestamp));
1451     }
1452   } else {
1453     GST_DEBUG_OBJECT (qtdemux, "moving backwards to keyframe at %u (pts %"
1454         GST_TIME_FORMAT, kf_index,
1455         GST_TIME_ARGS (stream->samples[kf_index].timestamp));
1456     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
1457   }
1458
1459   return TRUE;
1460 }
1461
1462 /* prepare to get the current sample of @stream, getting essential values.
1463  *
1464  * This function will also prepare and send the segment when needed.
1465  *
1466  * Return FALSE if the stream is EOS.
1467  */
1468 static gboolean
1469 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
1470     QtDemuxStream * stream, guint64 * offset, guint * size, guint64 * timestamp,
1471     guint64 * duration, gboolean * keyframe)
1472 {
1473   QtDemuxSample *sample;
1474   guint64 time_position;
1475   guint32 seg_idx;
1476
1477   g_return_val_if_fail (stream != NULL, FALSE);
1478
1479   time_position = stream->time_position;
1480   if (time_position == -1)
1481     goto eos;
1482
1483   seg_idx = stream->segment_index;
1484   if (seg_idx == -1) {
1485     /* find segment corresponding to time_position if we are looking
1486      * for a segment. */
1487     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
1488
1489     /* nothing found, we're really eos */
1490     if (seg_idx == -1)
1491       goto eos;
1492   }
1493
1494   /* different segment, activate it, sample_index will be set. */
1495   if (stream->segment_index != seg_idx)
1496     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
1497
1498   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
1499       stream->sample_index, stream->n_samples);
1500
1501   /* send out pending buffers */
1502   while (stream->buffers) {
1503     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
1504
1505     if (stream->discont) {
1506       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
1507       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
1508       stream->discont = FALSE;
1509     }
1510     gst_buffer_set_caps (buffer, stream->caps);
1511
1512     gst_pad_push (stream->pad, buffer);
1513
1514     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
1515   }
1516
1517   if (stream->sample_index >= stream->n_samples)
1518     goto eos;
1519
1520   /* now get the info for the sample we're at */
1521   sample = &stream->samples[stream->sample_index];
1522
1523   *timestamp = sample->timestamp + sample->pts_offset;
1524   *offset = sample->offset;
1525   *size = sample->size;
1526   *duration = sample->duration;
1527   *keyframe = stream->all_keyframe || sample->keyframe;
1528
1529   /* add padding */
1530   if (stream->padding) {
1531     *offset += stream->padding;
1532     *size -= stream->padding;
1533   }
1534
1535   return TRUE;
1536
1537   /* special cases */
1538 eos:
1539   {
1540     stream->time_position = -1;
1541     return FALSE;
1542   }
1543 }
1544
1545 /* move to the next sample in @stream.
1546  *
1547  * Moves to the next segment when needed.
1548  */
1549 static void
1550 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
1551 {
1552   QtDemuxSample *sample;
1553   QtDemuxSegment *segment;
1554
1555   if (stream->sample_index >= stream->to_sample) {
1556     /* Mark the stream as EOS */
1557     GST_DEBUG_OBJECT (qtdemux, "reached max allowed sample %u, mark EOS",
1558         stream->to_sample);
1559     stream->time_position = -1;
1560     return;
1561   }
1562
1563   /* move to next sample */
1564   stream->sample_index++;
1565
1566   /* get current segment */
1567   segment = &stream->segments[stream->segment_index];
1568
1569   /* reached the last sample, we need the next segment */
1570   if (stream->sample_index >= stream->n_samples)
1571     goto next_segment;
1572
1573   /* get next sample */
1574   sample = &stream->samples[stream->sample_index];
1575
1576   /* see if we are past the segment */
1577   if (sample->timestamp >= segment->media_stop)
1578     goto next_segment;
1579
1580   if (sample->timestamp >= segment->media_start) {
1581     /* inside the segment, update time_position, looks very familiar to
1582      * GStreamer segments, doesn't it? */
1583     stream->time_position =
1584         (sample->timestamp - segment->media_start) + segment->time;
1585   } else {
1586     /* not yet in segment, time does not yet increment. This means
1587      * that we are still prerolling keyframes to the decoder so it can
1588      * decode the first sample of the segment. */
1589     stream->time_position = segment->time;
1590   }
1591   return;
1592
1593   /* move to the next segment */
1594 next_segment:
1595   {
1596     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
1597
1598     if (stream->segment_index == stream->n_segments - 1) {
1599       /* are we at the end of the last segment, we're EOS */
1600       stream->time_position = -1;
1601     } else {
1602       /* else we're only at the end of the current segment */
1603       stream->time_position = segment->stop_time;
1604     }
1605     /* make sure we select a new segment */
1606     stream->segment_index = -1;
1607   }
1608 }
1609
1610 /* UNEXPECTED and NOT_LINKED need to be combined. This means that we return:
1611  *  
1612  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
1613  *  GST_FLOW_UNEXPECTED: when all pads UNEXPECTED or NOT_LINKED.
1614  */
1615 static GstFlowReturn
1616 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
1617     GstFlowReturn ret)
1618 {
1619   gint i;
1620   gboolean unexpected = FALSE, not_linked = TRUE;
1621
1622   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
1623
1624   /* store the value */
1625   stream->last_ret = ret;
1626
1627   for (i = 0; i < demux->n_streams; i++) {
1628     QtDemuxStream *ostream = demux->streams[i];
1629
1630     ret = ostream->last_ret;
1631
1632     /* no unexpected or unlinked, return */
1633     if (ret != GST_FLOW_UNEXPECTED && ret != GST_FLOW_NOT_LINKED)
1634       goto done;
1635
1636     /* we check to see if we have at least 1 unexpected or all unlinked */
1637     unexpected |= (ret == GST_FLOW_UNEXPECTED);
1638     not_linked &= (ret == GST_FLOW_NOT_LINKED);
1639   }
1640   /* when we get here, we all have unlinked or unexpected */
1641   if (not_linked)
1642     ret = GST_FLOW_NOT_LINKED;
1643   else if (unexpected)
1644     ret = GST_FLOW_UNEXPECTED;
1645 done:
1646   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
1647   return ret;
1648 }
1649
1650 /* the input buffer metadata must be writable. Returns NULL when the buffer is
1651  * completely cliped */
1652 static GstBuffer *
1653 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
1654     GstBuffer * buf)
1655 {
1656   gint64 start, stop, cstart, cstop, diff;
1657   GstClockTime timestamp = GST_CLOCK_TIME_NONE, duration = GST_CLOCK_TIME_NONE;
1658   guint8 *data;
1659   guint size;
1660   gint num_rate, denom_rate;
1661   gint frame_size;
1662   gboolean clip_data;
1663
1664   data = GST_BUFFER_DATA (buf);
1665   size = GST_BUFFER_SIZE (buf);
1666
1667   /* depending on the type, setup the clip parameters */
1668   if (stream->subtype == FOURCC_soun) {
1669     frame_size = stream->bytes_per_frame;
1670     num_rate = GST_SECOND;
1671     denom_rate = (gint) stream->rate;
1672     clip_data = TRUE;
1673   } else if (stream->subtype == FOURCC_vide) {
1674     frame_size = size;
1675     num_rate = stream->fps_n;
1676     denom_rate = stream->fps_d;
1677     clip_data = FALSE;
1678   } else
1679     goto wrong_type;
1680
1681   /* we can only clip if we have a valid timestamp */
1682   timestamp = GST_BUFFER_TIMESTAMP (buf);
1683   if (!GST_CLOCK_TIME_IS_VALID (timestamp))
1684     goto no_timestamp;
1685
1686   if (GST_BUFFER_DURATION_IS_VALID (buf)) {
1687     duration = GST_BUFFER_DURATION (buf);
1688   } else {
1689     duration =
1690         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
1691   }
1692
1693   start = timestamp;
1694   stop = start + duration;
1695
1696   if (!gst_segment_clip (&stream->segment, GST_FORMAT_TIME,
1697           start, stop, &cstart, &cstop))
1698     goto clipped;
1699
1700   /* see if some clipping happened */
1701   diff = cstart - start;
1702   if (diff > 0) {
1703     timestamp = cstart;
1704     duration -= diff;
1705
1706     if (clip_data) {
1707       /* bring clipped time to samples and to bytes */
1708       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
1709       diff *= frame_size;
1710
1711       GST_DEBUG_OBJECT (qtdemux, "clipping start to %" GST_TIME_FORMAT " %"
1712           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
1713
1714       data += diff;
1715       size -= diff;
1716     }
1717   }
1718   diff = stop - cstop;
1719   if (diff > 0) {
1720     duration -= diff;
1721
1722     if (clip_data) {
1723       /* bring clipped time to samples and then to bytes */
1724       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
1725       diff *= frame_size;
1726
1727       GST_DEBUG_OBJECT (qtdemux, "clipping stop to %" GST_TIME_FORMAT " %"
1728           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstop), diff);
1729
1730       size -= diff;
1731     }
1732   }
1733
1734   GST_BUFFER_TIMESTAMP (buf) = timestamp;
1735   GST_BUFFER_DURATION (buf) = duration;
1736   GST_BUFFER_SIZE (buf) = size;
1737   GST_BUFFER_DATA (buf) = data;
1738
1739   return buf;
1740
1741   /* dropped buffer */
1742 wrong_type:
1743   {
1744     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
1745     return buf;
1746   }
1747 no_timestamp:
1748   {
1749     GST_DEBUG_OBJECT (qtdemux, "no timestamp on buffer");
1750     return buf;
1751   }
1752 clipped:
1753   {
1754     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
1755     gst_buffer_unref (buf);
1756     return NULL;
1757   }
1758 }
1759
1760 static GstFlowReturn
1761 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
1762 {
1763   GstFlowReturn ret = GST_FLOW_OK;
1764   GstBuffer *buf = NULL;
1765   QtDemuxStream *stream;
1766   guint64 min_time;
1767   guint64 offset;
1768   guint64 timestamp;
1769   guint64 duration;
1770   gboolean keyframe;
1771   guint size;
1772   gint index;
1773   gint i;
1774
1775   gst_qtdemux_push_pending_newsegment (qtdemux);
1776
1777   /* Figure out the next stream sample to output, min_time is expressed in
1778    * global time and runs over the edit list segments. */
1779   min_time = G_MAXUINT64;
1780   index = -1;
1781   for (i = 0; i < qtdemux->n_streams; i++) {
1782     guint64 position;
1783
1784     stream = qtdemux->streams[i];
1785     position = stream->time_position;
1786
1787     /* position of -1 is EOS */
1788     if (position != -1 && position < min_time) {
1789       min_time = position;
1790       index = i;
1791     }
1792   }
1793   /* all are EOS */
1794   if (index == -1) {
1795     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
1796     goto eos;
1797   }
1798
1799   /* check for segment end */
1800   if (qtdemux->segment.stop != -1 && qtdemux->segment.stop < min_time) {
1801     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
1802     goto eos;
1803   }
1804
1805   stream = qtdemux->streams[index];
1806
1807   /* fetch info for the current sample of this stream */
1808   if (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &offset, &size,
1809           &timestamp, &duration, &keyframe))
1810     goto eos;
1811
1812   GST_LOG_OBJECT (qtdemux,
1813       "pushing from stream %d, offset %" G_GUINT64_FORMAT
1814       ", size %d, timestamp=%" GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT,
1815       index, offset, size, GST_TIME_ARGS (timestamp), GST_TIME_ARGS (duration));
1816
1817   /* hmm, empty sample, skip and move to next sample */
1818   if (G_UNLIKELY (size <= 0))
1819     goto next;
1820
1821   /* last pushed sample was out of boundary, goto next sample */
1822   if (stream->last_ret == GST_FLOW_UNEXPECTED)
1823     goto next;
1824
1825   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
1826       offset);
1827
1828   ret = gst_pad_pull_range (qtdemux->sinkpad, offset, size, &buf);
1829   if (ret != GST_FLOW_OK)
1830     goto beach;
1831
1832   if (stream->fourcc == FOURCC_rtsp) {
1833     GstMessage *m;
1834     gchar *url;
1835
1836     url = g_strndup ((gchar *) GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
1837
1838     /* we have RTSP redirect now */
1839     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
1840         gst_structure_new ("redirect",
1841             "new-location", G_TYPE_STRING, url, NULL));
1842     g_free (url);
1843
1844     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
1845   }
1846
1847   qtdemux->last_ts = min_time;
1848   if (qtdemux->segment.rate >= 0) {
1849     gst_segment_set_last_stop (&qtdemux->segment, GST_FORMAT_TIME, min_time);
1850   }
1851   if (stream->pad) {
1852     /* we're going to modify the metadata */
1853     buf = gst_buffer_make_metadata_writable (buf);
1854
1855     GST_BUFFER_TIMESTAMP (buf) = timestamp;
1856     GST_BUFFER_DURATION (buf) = duration;
1857     GST_BUFFER_OFFSET (buf) = -1;
1858     GST_BUFFER_OFFSET_END (buf) = -1;
1859
1860     if (stream->need_clip)
1861       buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
1862
1863     if (buf == NULL)
1864       goto next;
1865
1866     if (stream->discont) {
1867       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
1868       GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
1869       stream->discont = FALSE;
1870     }
1871
1872     if (!keyframe)
1873       GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
1874
1875     gst_buffer_set_caps (buf, stream->caps);
1876
1877     GST_LOG_OBJECT (qtdemux,
1878         "Pushing buffer with time %" GST_TIME_FORMAT ", duration %"
1879         GST_TIME_FORMAT " on pad %s",
1880         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
1881         GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_PAD_NAME (stream->pad));
1882
1883     ret = gst_pad_push (stream->pad, buf);
1884   } else {
1885     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
1886     gst_buffer_unref (buf);
1887     ret = GST_FLOW_OK;
1888   }
1889
1890   /* combine flows */
1891   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
1892   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
1893    * we have no more data for the pad to push */
1894   if (ret == GST_FLOW_UNEXPECTED)
1895     ret = GST_FLOW_OK;
1896
1897 next:
1898   gst_qtdemux_advance_sample (qtdemux, stream);
1899
1900 beach:
1901   return ret;
1902
1903   /* special cases */
1904 eos:
1905   {
1906     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
1907     ret = GST_FLOW_UNEXPECTED;
1908     goto beach;
1909   }
1910 }
1911
1912 static void
1913 gst_qtdemux_loop (GstPad * pad)
1914 {
1915   GstQTDemux *qtdemux;
1916   guint64 cur_offset;
1917   GstFlowReturn ret;
1918
1919   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
1920
1921   cur_offset = qtdemux->offset;
1922   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %d",
1923       cur_offset, qtdemux->state);
1924
1925   switch (qtdemux->state) {
1926     case QTDEMUX_STATE_INITIAL:
1927     case QTDEMUX_STATE_HEADER:
1928       ret = gst_qtdemux_loop_state_header (qtdemux);
1929       break;
1930     case QTDEMUX_STATE_MOVIE:
1931       ret = gst_qtdemux_loop_state_movie (qtdemux);
1932       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_UNEXPECTED) {
1933         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
1934       }
1935       break;
1936     default:
1937       /* ouch */
1938       goto invalid_state;
1939   }
1940
1941   /* if something went wrong, pause */
1942   if (ret != GST_FLOW_OK)
1943     goto pause;
1944
1945 done:
1946   gst_object_unref (qtdemux);
1947   return;
1948
1949   /* ERRORS */
1950 invalid_state:
1951   {
1952     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
1953         (NULL), ("streaming stopped, invalid state"));
1954     qtdemux->segment_running = FALSE;
1955     gst_pad_pause_task (pad);
1956     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
1957     goto done;
1958   }
1959 pause:
1960   {
1961     const gchar *reason = gst_flow_get_name (ret);
1962
1963     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
1964
1965     qtdemux->segment_running = FALSE;
1966     gst_pad_pause_task (pad);
1967
1968     /* fatal errors need special actions */
1969     if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) {
1970       /* check EOS */
1971       if (ret == GST_FLOW_UNEXPECTED) {
1972         if (qtdemux->n_streams == 0) {
1973           /* we have no streams, post an error */
1974           GST_ELEMENT_ERROR (qtdemux, STREAM, DECODE,
1975               (_("This file contains no playable streams.")),
1976               ("no known streams found"));
1977         }
1978         if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1979           gint64 stop;
1980
1981           /* FIXME: I am not sure this is the right fix. If the sinks are
1982            * supposed to detect the segment is complete and accumulate 
1983            * automatically, it does not seem to work here. Need more work */
1984           qtdemux->segment_running = TRUE;
1985
1986           if ((stop = qtdemux->segment.stop) == -1)
1987             stop = qtdemux->segment.duration;
1988
1989           if (qtdemux->segment.rate >= 0) {
1990             GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
1991             gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
1992                 gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
1993                     GST_FORMAT_TIME, stop));
1994           } else {
1995             /*  For Reverse Playback */
1996             GST_LOG_OBJECT (qtdemux,
1997                 "Sending segment done, at start of segment");
1998             gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
1999                 gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
2000                     GST_FORMAT_TIME, qtdemux->segment.start));
2001           }
2002         } else {
2003           GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
2004           gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
2005         }
2006       } else {
2007         GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
2008             (NULL), ("streaming stopped, reason %s", reason));
2009         gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
2010       }
2011     }
2012     goto done;
2013   }
2014 }
2015
2016 /*
2017  * next_entry_size
2018  *
2019  * Returns the size of the first entry at the current offset.
2020  * If -1, there are none (which means EOS or empty file).
2021  */
2022 static guint64
2023 next_entry_size (GstQTDemux * demux)
2024 {
2025   QtDemuxStream *stream;
2026   int i;
2027   int smallidx = -1;
2028   guint64 smalloffs = (guint64) - 1;
2029
2030   GST_LOG_OBJECT (demux, "Finding entry at offset %lld", demux->offset);
2031
2032   for (i = 0; i < demux->n_streams; i++) {
2033     stream = demux->streams[i];
2034
2035     if (stream->sample_index == -1)
2036       stream->sample_index = 0;
2037
2038     GST_LOG_OBJECT (demux,
2039         "Checking Stream %d (sample_index:%d / offset:%lld / size:%d / chunk:%d)",
2040         i, stream->sample_index, stream->samples[stream->sample_index].offset,
2041         stream->samples[stream->sample_index].size,
2042         stream->samples[stream->sample_index].chunk);
2043
2044     if (((smalloffs == -1)
2045             || (stream->samples[stream->sample_index].offset < smalloffs))
2046         && (stream->samples[stream->sample_index].size)) {
2047       smallidx = i;
2048       smalloffs = stream->samples[stream->sample_index].offset;
2049     }
2050   }
2051
2052   GST_LOG_OBJECT (demux, "stream %d offset %lld demux->offset :%lld",
2053       smallidx, smalloffs, demux->offset);
2054
2055   if (smallidx == -1)
2056     return -1;
2057   stream = demux->streams[smallidx];
2058
2059   if (stream->samples[stream->sample_index].offset >= demux->offset) {
2060     demux->todrop =
2061         stream->samples[stream->sample_index].offset - demux->offset;
2062     return stream->samples[stream->sample_index].size + demux->todrop;
2063   }
2064
2065   GST_DEBUG_OBJECT (demux, "There wasn't any entry at offset %lld",
2066       demux->offset);
2067   return -1;
2068 }
2069
2070 static void
2071 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
2072 {
2073   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
2074
2075   gst_element_post_message (GST_ELEMENT_CAST (demux),
2076       gst_message_new_element (GST_OBJECT_CAST (demux),
2077           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
2078 }
2079
2080 /* FIXME, unverified after edit list updates */
2081 static GstFlowReturn
2082 gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
2083 {
2084   GstQTDemux *demux;
2085   GstFlowReturn ret = GST_FLOW_OK;
2086
2087   demux = GST_QTDEMUX (gst_pad_get_parent (sinkpad));
2088
2089   gst_adapter_push (demux->adapter, inbuf);
2090
2091   GST_DEBUG_OBJECT (demux, "pushing in inbuf %p, neededbytes:%u, available:%u",
2092       inbuf, demux->neededbytes, gst_adapter_available (demux->adapter));
2093
2094   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
2095       (ret == GST_FLOW_OK)) {
2096
2097     GST_DEBUG_OBJECT (demux,
2098         "state:%d , demux->neededbytes:%d, demux->offset:%lld", demux->state,
2099         demux->neededbytes, demux->offset);
2100
2101     switch (demux->state) {
2102       case QTDEMUX_STATE_INITIAL:{
2103         const guint8 *data;
2104         guint32 fourcc;
2105         guint64 size;
2106
2107         data = gst_adapter_peek (demux->adapter, demux->neededbytes);
2108
2109         /* get fourcc/length, set neededbytes */
2110         extract_initial_length_and_fourcc ((guint8 *) data, &size, &fourcc);
2111         GST_DEBUG_OBJECT (demux,
2112             "Peeking found [%" GST_FOURCC_FORMAT "] size: %u",
2113             GST_FOURCC_ARGS (fourcc), (guint) size);
2114         if (size == 0) {
2115           GST_ELEMENT_ERROR (demux, STREAM, DECODE,
2116               (_("This file is invalid and cannot be played.")),
2117               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
2118                   GST_FOURCC_ARGS (fourcc)));
2119           ret = GST_FLOW_ERROR;
2120           break;
2121         }
2122         if (fourcc == FOURCC_mdat) {
2123           if (demux->n_streams > 0) {
2124             demux->state = QTDEMUX_STATE_MOVIE;
2125             demux->neededbytes = next_entry_size (demux);
2126           } else {
2127             demux->state = QTDEMUX_STATE_BUFFER_MDAT;
2128             demux->neededbytes = size;
2129             demux->mdatoffset = demux->offset;
2130           }
2131         } else {
2132           demux->neededbytes = size;
2133           demux->state = QTDEMUX_STATE_HEADER;
2134         }
2135         break;
2136       }
2137       case QTDEMUX_STATE_HEADER:{
2138         guint8 *data;
2139         guint32 fourcc;
2140
2141         GST_DEBUG_OBJECT (demux, "In header");
2142
2143         data = gst_adapter_take (demux->adapter, demux->neededbytes);
2144
2145         /* parse the header */
2146         extract_initial_length_and_fourcc (data, NULL, &fourcc);
2147         if (fourcc == FOURCC_moov) {
2148           GST_DEBUG_OBJECT (demux, "Parsing [moov]");
2149
2150           qtdemux_parse_moov (demux, data, demux->neededbytes);
2151           qtdemux_node_dump (demux, demux->moov_node);
2152           qtdemux_parse_tree (demux);
2153
2154           g_node_destroy (demux->moov_node);
2155           g_free (data);
2156           demux->moov_node = NULL;
2157         } else {
2158           GST_WARNING_OBJECT (demux,
2159               "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
2160               GST_FOURCC_ARGS (fourcc));
2161           /* Let's jump that one and go back to initial state */
2162         }
2163
2164         GST_DEBUG_OBJECT (demux, "Finished parsing the header");
2165         if (demux->mdatbuffer && demux->n_streams) {
2166           /* the mdat was before the header */
2167           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
2168               demux->n_streams, demux->mdatbuffer);
2169           gst_adapter_clear (demux->adapter);
2170           GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
2171               GST_FOURCC_ARGS (QT_UINT32 (demux->mdatbuffer)));
2172           gst_adapter_push (demux->adapter, demux->mdatbuffer);
2173           demux->mdatbuffer = NULL;
2174           demux->offset = demux->mdatoffset;
2175           demux->neededbytes = next_entry_size (demux);
2176           demux->state = QTDEMUX_STATE_MOVIE;
2177         } else {
2178           GST_DEBUG_OBJECT (demux, "Carrying on normally");
2179           demux->offset += demux->neededbytes;
2180           demux->neededbytes = 16;
2181           demux->state = QTDEMUX_STATE_INITIAL;
2182         }
2183
2184         break;
2185       }
2186       case QTDEMUX_STATE_BUFFER_MDAT:{
2187         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %lld",
2188             demux->mdatoffset);
2189         if (demux->mdatbuffer)
2190           gst_buffer_unref (demux->mdatbuffer);
2191         demux->mdatbuffer = gst_buffer_new ();
2192         gst_buffer_set_data (demux->mdatbuffer,
2193             gst_adapter_take (demux->adapter, demux->neededbytes),
2194             demux->neededbytes);
2195         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
2196             GST_FOURCC_ARGS (QT_UINT32 (demux->mdatbuffer)));
2197         demux->offset += demux->neededbytes;
2198         demux->neededbytes = 16;
2199         demux->state = QTDEMUX_STATE_INITIAL;
2200         gst_qtdemux_post_progress (demux, 1, 1);
2201
2202         break;
2203       }
2204       case QTDEMUX_STATE_MOVIE:{
2205         guint8 *data;
2206         GstBuffer *outbuf;
2207         QtDemuxStream *stream = NULL;
2208         int i = -1;
2209
2210         GST_DEBUG_OBJECT (demux, "BEGIN // in MOVIE for offset %lld",
2211             demux->offset);
2212
2213         if (demux->todrop) {
2214           gst_adapter_flush (demux->adapter, demux->todrop);
2215           demux->neededbytes -= demux->todrop;
2216           demux->offset += demux->todrop;
2217         }
2218
2219         /* Figure out which stream this is packet belongs to */
2220         for (i = 0; i < demux->n_streams; i++) {
2221           stream = demux->streams[i];
2222           GST_LOG_OBJECT (demux,
2223               "Checking stream %d (sample_index:%d / offset:%lld / size:%d / chunk:%d)",
2224               i, stream->sample_index,
2225               stream->samples[stream->sample_index].offset,
2226               stream->samples[stream->sample_index].size,
2227               stream->samples[stream->sample_index].chunk);
2228
2229           if (stream->samples[stream->sample_index].offset == demux->offset)
2230             break;
2231         }
2232
2233         if (stream == NULL)
2234           goto unknown_stream;
2235
2236         /* first buffer? */
2237         /* FIXME : this should be handled in sink_event */
2238         if (demux->last_ts == GST_CLOCK_TIME_NONE) {
2239           gst_qtdemux_push_event (demux,
2240               gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
2241                   0, GST_CLOCK_TIME_NONE, 0));
2242         }
2243
2244         /* get data */
2245         data = gst_adapter_take (demux->adapter, demux->neededbytes);
2246
2247         /* Put data in a buffer, set timestamps, caps, ... */
2248         outbuf = gst_buffer_new ();
2249         gst_buffer_set_data (outbuf, data, demux->neededbytes);
2250         GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
2251             GST_FOURCC_ARGS (stream->fourcc));
2252
2253         if (stream->samples[stream->sample_index].pts_offset) {
2254           demux->last_ts = stream->samples[stream->sample_index].timestamp;
2255           GST_BUFFER_TIMESTAMP (outbuf) = demux->last_ts +
2256               stream->samples[stream->sample_index].pts_offset;
2257         } else {
2258           GST_BUFFER_TIMESTAMP (outbuf) =
2259               stream->samples[stream->sample_index].timestamp;
2260           demux->last_ts = GST_BUFFER_TIMESTAMP (outbuf);
2261         }
2262         GST_BUFFER_DURATION (outbuf) =
2263             stream->samples[stream->sample_index].duration;
2264
2265         /* send buffer */
2266         if (stream->pad) {
2267           GST_LOG_OBJECT (demux,
2268               "Pushing buffer with time %" GST_TIME_FORMAT " on pad %p",
2269               GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)), stream->pad);
2270           gst_buffer_set_caps (outbuf, stream->caps);
2271           ret = gst_pad_push (stream->pad, outbuf);
2272         } else {
2273           gst_buffer_unref (outbuf);
2274           ret = GST_FLOW_OK;
2275         }
2276
2277         /* combine flows */
2278         ret = gst_qtdemux_combine_flows (demux, stream, ret);
2279
2280         stream->sample_index++;
2281
2282         /* update current offset and figure out size of next buffer */
2283         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
2284             demux->offset, demux->neededbytes);
2285         demux->offset += demux->neededbytes;
2286         GST_LOG_OBJECT (demux, "offset is now %lld", demux->offset);
2287
2288         if ((demux->neededbytes = next_entry_size (demux)) == -1)
2289           goto eos;
2290         break;
2291       }
2292       default:
2293         goto invalid_state;
2294     }
2295   }
2296
2297   /* when buffering movie data, at least show user something is happening */
2298   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
2299       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
2300     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
2301         demux->neededbytes);
2302   }
2303 done:
2304   gst_object_unref (demux);
2305
2306   return ret;
2307
2308   /* ERRORS */
2309 unknown_stream:
2310   {
2311     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
2312     ret = GST_FLOW_ERROR;
2313     goto done;
2314   }
2315 eos:
2316   {
2317     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
2318     ret = GST_FLOW_UNEXPECTED;
2319     goto done;
2320   }
2321 invalid_state:
2322   {
2323     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
2324         (NULL), ("qtdemuxer invalid state %d", demux->state));
2325     ret = GST_FLOW_ERROR;
2326     goto done;
2327   }
2328 }
2329
2330 static gboolean
2331 qtdemux_sink_activate (GstPad * sinkpad)
2332 {
2333   if (gst_pad_check_pull_range (sinkpad))
2334     return gst_pad_activate_pull (sinkpad, TRUE);
2335   else
2336     return gst_pad_activate_push (sinkpad, TRUE);
2337 }
2338
2339 static gboolean
2340 qtdemux_sink_activate_pull (GstPad * sinkpad, gboolean active)
2341 {
2342   GstQTDemux *demux = GST_QTDEMUX (GST_PAD_PARENT (sinkpad));
2343
2344   if (active) {
2345     demux->pullbased = TRUE;
2346     demux->segment_running = TRUE;
2347     return gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
2348         sinkpad);
2349   } else {
2350     demux->segment_running = FALSE;
2351     return gst_pad_stop_task (sinkpad);
2352   }
2353 }
2354
2355 static gboolean
2356 qtdemux_sink_activate_push (GstPad * sinkpad, gboolean active)
2357 {
2358   GstQTDemux *demux = GST_QTDEMUX (GST_PAD_PARENT (sinkpad));
2359
2360   demux->pullbased = FALSE;
2361
2362   return TRUE;
2363 }
2364
2365 #ifdef HAVE_ZLIB
2366 static void *
2367 qtdemux_zalloc (void *opaque, unsigned int items, unsigned int size)
2368 {
2369   return g_malloc (items * size);
2370 }
2371
2372 static void
2373 qtdemux_zfree (void *opaque, void *addr)
2374 {
2375   g_free (addr);
2376 }
2377
2378 static void *
2379 qtdemux_inflate (void *z_buffer, int z_length, int length)
2380 {
2381   guint8 *buffer;
2382   z_stream *z;
2383   int ret;
2384
2385   z = g_new0 (z_stream, 1);
2386   z->zalloc = qtdemux_zalloc;
2387   z->zfree = qtdemux_zfree;
2388   z->opaque = NULL;
2389
2390   z->next_in = z_buffer;
2391   z->avail_in = z_length;
2392
2393   buffer = (guint8 *) g_malloc (length);
2394   ret = inflateInit (z);
2395   while (z->avail_in > 0) {
2396     if (z->avail_out == 0) {
2397       length += 1024;
2398       buffer = (guint8 *) g_realloc (buffer, length);
2399       z->next_out = buffer + z->total_out;
2400       z->avail_out = 1024;
2401     }
2402     ret = inflate (z, Z_SYNC_FLUSH);
2403     if (ret != Z_OK)
2404       break;
2405   }
2406   if (ret != Z_STREAM_END) {
2407     g_warning ("inflate() returned %d", ret);
2408   }
2409
2410   g_free (z);
2411   return buffer;
2412 }
2413 #endif /* HAVE_ZLIB */
2414
2415 static gboolean
2416 qtdemux_parse_moov (GstQTDemux * qtdemux, guint8 * buffer, int length)
2417 {
2418   GNode *cmov;
2419
2420   qtdemux->moov_node = g_node_new (buffer);
2421
2422   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
2423   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
2424
2425   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
2426   if (cmov) {
2427     guint32 method;
2428     GNode *dcom;
2429     GNode *cmvd;
2430
2431     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
2432     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
2433     if (dcom == NULL || cmvd == NULL)
2434       goto invalid_compression;
2435
2436     method = QT_FOURCC ((guint8 *) dcom->data + 8);
2437     switch (method) {
2438 #ifdef HAVE_ZLIB
2439       case GST_MAKE_FOURCC ('z', 'l', 'i', 'b'):{
2440         int uncompressed_length;
2441         int compressed_length;
2442         guint8 *buf;
2443
2444         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
2445         compressed_length = QT_UINT32 ((guint8 *) cmvd->data + 4) - 12;
2446         GST_LOG ("length = %d", uncompressed_length);
2447
2448         buf =
2449             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
2450             compressed_length, uncompressed_length);
2451
2452         qtdemux->moov_node_compressed = qtdemux->moov_node;
2453         qtdemux->moov_node = g_node_new (buf);
2454
2455         qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
2456             uncompressed_length);
2457         break;
2458       }
2459 #endif /* HAVE_ZLIB */
2460       default:
2461         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
2462             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
2463         break;
2464     }
2465   }
2466   return TRUE;
2467
2468   /* ERRORS */
2469 invalid_compression:
2470   {
2471     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
2472     return FALSE;
2473   }
2474 }
2475
2476 static gboolean
2477 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, guint8 * buf,
2478     guint8 * end)
2479 {
2480   while (buf < end) {
2481     GNode *child;
2482     guint32 len;
2483
2484     if (buf + 4 > end) {
2485       GST_LOG_OBJECT (qtdemux, "buffer overrun");
2486       break;
2487     }
2488     len = QT_UINT32 (buf);
2489     if (len == 0) {
2490       GST_LOG_OBJECT (qtdemux, "empty container");
2491       break;
2492     }
2493     if (len < 8) {
2494       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
2495       break;
2496     }
2497     if (len > (end - buf)) {
2498       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len, end - buf);
2499       break;
2500     }
2501
2502     child = g_node_new (buf);
2503     g_node_append (node, child);
2504     qtdemux_parse_node (qtdemux, child, buf, len);
2505
2506     buf += len;
2507   }
2508   return TRUE;
2509 }
2510
2511 static gboolean
2512 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
2513     GNode * xdxt)
2514 {
2515   int len = QT_UINT32 (xdxt->data);
2516   guint8 *buf = xdxt->data;
2517   guint8 *end = buf + len;
2518   GstBuffer *buffer;
2519
2520   /* skip size and type */
2521   buf += 8;
2522   end -= 8;
2523
2524   while (buf < end) {
2525     gint size;
2526     guint32 type;
2527
2528     size = QT_UINT32 (buf);
2529     type = QT_FOURCC (buf + 4);
2530
2531     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
2532
2533     if (buf + size > end || size <= 0)
2534       break;
2535
2536     buf += 8;
2537     size -= 8;
2538
2539     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
2540         GST_FOURCC_ARGS (type));
2541
2542     switch (type) {
2543       case FOURCC_tCtH:
2544         buffer = gst_buffer_new_and_alloc (size);
2545         memcpy (GST_BUFFER_DATA (buffer), buf, size);
2546         stream->buffers = g_slist_append (stream->buffers, buffer);
2547         GST_LOG_OBJECT (qtdemux, "parsing theora header");
2548         break;
2549       case FOURCC_tCt_:
2550         buffer = gst_buffer_new_and_alloc (size);
2551         memcpy (GST_BUFFER_DATA (buffer), buf, size);
2552         stream->buffers = g_slist_append (stream->buffers, buffer);
2553         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
2554         break;
2555       case FOURCC_tCtC:
2556         buffer = gst_buffer_new_and_alloc (size);
2557         memcpy (GST_BUFFER_DATA (buffer), buf, size);
2558         stream->buffers = g_slist_append (stream->buffers, buffer);
2559         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
2560         break;
2561       default:
2562         GST_WARNING_OBJECT (qtdemux,
2563             "unknown theora cookie %" GST_FOURCC_FORMAT,
2564             GST_FOURCC_ARGS (type));
2565         break;
2566     }
2567     buf += size;
2568   }
2569   return TRUE;
2570 }
2571
2572 static gboolean
2573 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, guint8 * buffer,
2574     int length)
2575 {
2576   guint32 fourcc;
2577   guint32 node_length;
2578   const QtNodeType *type;
2579   guint8 *end;
2580
2581   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %d", buffer, length);
2582
2583   node_length = QT_UINT32 (buffer);
2584   fourcc = QT_FOURCC (buffer + 4);
2585
2586   type = qtdemux_type_get (fourcc);
2587
2588   /* ignore empty nodes */
2589   if (fourcc == 0 || node_length == 8)
2590     return TRUE;
2591
2592   end = buffer + length;
2593
2594   GST_LOG_OBJECT (qtdemux,
2595       "parsing '%" GST_FOURCC_FORMAT "', length=%d, name '%s'",
2596       GST_FOURCC_ARGS (fourcc), node_length, type->name);
2597
2598   if (type->flags & QT_FLAG_CONTAINER) {
2599     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
2600   } else {
2601     switch (fourcc) {
2602       case FOURCC_stsd:
2603       {
2604         if (node_length < 20) {
2605           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
2606           break;
2607         }
2608         GST_DEBUG_OBJECT (qtdemux,
2609             "parsing stsd (sample table, sample description) atom");
2610         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
2611         break;
2612       }
2613       case FOURCC_mp4a:
2614       {
2615         guint32 version;
2616         guint32 offset;
2617
2618         if (length < 20) {
2619           /* small boxes are also inside wave inside the mp4a box */
2620           GST_LOG_OBJECT (qtdemux, "skipping small mp4a box");
2621           break;
2622         }
2623         version = QT_UINT32 (buffer + 16);
2624
2625         GST_WARNING_OBJECT (qtdemux, "mp4a version 0x%08x", version);
2626
2627         /* parse any esds descriptors */
2628         switch (version) {
2629           case 0x00000000:
2630             offset = 0x24;
2631             break;
2632           case 0x00010000:
2633             offset = 0x34;
2634             break;
2635           case 0x00020000:
2636             offset = 0x58;
2637             break;
2638           default:
2639             GST_WARNING_OBJECT (qtdemux, "unhandled mp4a version 0x%08x",
2640                 version);
2641             offset = 0;
2642             break;
2643         }
2644         if (offset)
2645           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
2646         break;
2647       }
2648       case FOURCC_mp4v:
2649       {
2650         guint8 *buf;
2651         guint32 version;
2652         int tlen;
2653
2654         GST_DEBUG_OBJECT (qtdemux, "parsing in mp4v");
2655         version = QT_UINT32 (buffer + 16);
2656         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
2657         if (1 || version == 0x00000000) {
2658           buf = buffer + 0x32;
2659
2660           /* FIXME Quicktime uses PASCAL string while
2661            * the iso format uses C strings. Check the file
2662            * type before attempting to parse the string here. */
2663           tlen = QT_UINT8 (buf);
2664           GST_DEBUG_OBJECT (qtdemux, "tlen = %d", tlen);
2665           buf++;
2666           GST_DEBUG_OBJECT (qtdemux, "string = %.*s", tlen, (char *) buf);
2667           /* the string has a reserved space of 32 bytes so skip
2668            * the remaining 31 */
2669           buf += 31;
2670           buf += 4;             /* and 4 bytes reserved */
2671
2672           qtdemux_dump_mem (buf, end - buf);
2673
2674           qtdemux_parse_container (qtdemux, node, buf, end);
2675         }
2676         break;
2677       }
2678       case FOURCC_mjp2:
2679       {
2680         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
2681         break;
2682       }
2683       case FOURCC_meta:
2684       {
2685         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
2686         qtdemux_parse_container (qtdemux, node, buffer + 12, end);
2687         break;
2688       }
2689       case FOURCC_XiTh:
2690       {
2691         guint32 version;
2692         guint32 offset;
2693
2694         version = QT_UINT32 (buffer + 12);
2695         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
2696
2697         switch (version) {
2698           case 0x00000001:
2699             offset = 0x62;
2700             break;
2701           default:
2702             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
2703             offset = 0;
2704             break;
2705         }
2706         if (offset)
2707           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
2708         break;
2709       }
2710       default:
2711         break;
2712     }
2713   }
2714   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT,
2715       GST_FOURCC_ARGS (fourcc));
2716   return TRUE;
2717 }
2718
2719 static GNode *
2720 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
2721 {
2722   GNode *child;
2723   guint8 *buffer;
2724   guint32 child_fourcc;
2725
2726   for (child = g_node_first_child (node); child;
2727       child = g_node_next_sibling (child)) {
2728     buffer = (guint8 *) child->data;
2729
2730     child_fourcc = QT_FOURCC (buffer + 4);
2731
2732     if (child_fourcc == fourcc) {
2733       return child;
2734     }
2735   }
2736   return NULL;
2737 }
2738
2739 static GNode *
2740 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
2741 {
2742   GNode *child;
2743   guint8 *buffer;
2744   guint32 child_fourcc;
2745
2746   for (child = g_node_next_sibling (node); child;
2747       child = g_node_next_sibling (child)) {
2748     buffer = (guint8 *) child->data;
2749
2750     child_fourcc = QT_FOURCC (buffer + 4);
2751
2752     if (child_fourcc == fourcc) {
2753       return child;
2754     }
2755   }
2756   return NULL;
2757 }
2758
2759 static gboolean
2760 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
2761     QtDemuxStream * stream, GstTagList * list)
2762 {
2763   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
2764     goto too_many_streams;
2765
2766   if (stream->subtype == FOURCC_vide) {
2767     gchar *name = g_strdup_printf ("video_%02d", qtdemux->n_video_streams);
2768
2769     stream->pad =
2770         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
2771     g_free (name);
2772
2773     /* fps is calculated base on the duration of the first frames since
2774      * qt does not have a fixed framerate. */
2775     if ((stream->n_samples == 1) && (stream->min_duration == 0)) {
2776       /* still frame */
2777       stream->fps_n = 0;
2778       stream->fps_d = 1;
2779     } else {
2780       stream->fps_n = stream->timescale;
2781       if (stream->min_duration == 0)
2782         stream->fps_d = 1;
2783       else
2784         stream->fps_d = stream->min_duration;
2785     }
2786
2787     if (stream->caps) {
2788       gboolean gray;
2789       gint depth, palette_count;
2790       const guint32 *palette_data = NULL;
2791
2792       gst_caps_set_simple (stream->caps,
2793           "width", G_TYPE_INT, stream->width,
2794           "height", G_TYPE_INT, stream->height,
2795           "framerate", GST_TYPE_FRACTION, stream->fps_n, stream->fps_d, NULL);
2796
2797       depth = stream->bits_per_sample;
2798
2799       /* more than 32 bits means grayscale */
2800       gray = (depth > 32);
2801       /* low 32 bits specify the depth  */
2802       depth &= 0x1F;
2803
2804       /* different number of palette entries is determined by depth. */
2805       palette_count = 0;
2806       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
2807         palette_count = (1 << depth);
2808
2809       switch (palette_count) {
2810         case 0:
2811           break;
2812         case 2:
2813           palette_data = ff_qt_default_palette_2;
2814           break;
2815         case 4:
2816           palette_data = ff_qt_default_palette_4;
2817           break;
2818         case 16:
2819           if (gray)
2820             palette_data = ff_qt_grayscale_palette_16;
2821           else
2822             palette_data = ff_qt_default_palette_16;
2823           break;
2824         case 256:
2825           if (gray)
2826             palette_data = ff_qt_grayscale_palette_256;
2827           else
2828             palette_data = ff_qt_default_palette_256;
2829           break;
2830         default:
2831           GST_ELEMENT_WARNING (qtdemux, STREAM, DECODE,
2832               (_("The video in this file might not play correctly.")),
2833               ("unsupported palette depth %d", depth));
2834           break;
2835       }
2836       if (palette_data) {
2837         GstBuffer *palette;
2838
2839         /* make sure it's not writable. We leave MALLOCDATA to NULL so that we
2840          * don't free any of the buffer data. */
2841         palette = gst_buffer_new ();
2842         GST_BUFFER_FLAG_SET (palette, GST_BUFFER_FLAG_READONLY);
2843         GST_BUFFER_DATA (palette) = (guint8 *) palette_data;
2844         GST_BUFFER_SIZE (palette) = sizeof (guint32) * palette_count;
2845
2846         gst_caps_set_simple (stream->caps, "palette_data",
2847             GST_TYPE_BUFFER, palette, NULL);
2848         gst_buffer_unref (palette);
2849       } else if (palette_count != 0) {
2850         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
2851             (NULL), ("Unsupported palette depth %d. Ignoring stream.", depth));
2852
2853         gst_object_unref (stream->pad);
2854         stream->pad = NULL;
2855       }
2856     }
2857     qtdemux->n_video_streams++;
2858   } else if (stream->subtype == FOURCC_soun) {
2859     gchar *name = g_strdup_printf ("audio_%02d", qtdemux->n_audio_streams);
2860
2861     stream->pad =
2862         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
2863     g_free (name);
2864     if (stream->caps) {
2865       gst_caps_set_simple (stream->caps,
2866           "rate", G_TYPE_INT, (int) stream->rate,
2867           "channels", G_TYPE_INT, stream->n_channels, NULL);
2868     }
2869     qtdemux->n_audio_streams++;
2870   } else if (stream->subtype == FOURCC_strm) {
2871     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
2872   } else {
2873     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
2874     goto done;
2875   }
2876
2877   qtdemux->streams[qtdemux->n_streams] = stream;
2878   qtdemux->n_streams++;
2879   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
2880
2881   if (stream->pad) {
2882     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
2883
2884     gst_pad_use_fixed_caps (stream->pad);
2885     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
2886     gst_pad_set_query_type_function (stream->pad,
2887         gst_qtdemux_get_src_query_types);
2888     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
2889
2890     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT, stream->caps);
2891     gst_pad_set_caps (stream->pad, stream->caps);
2892
2893     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
2894         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
2895     gst_pad_set_active (stream->pad, TRUE);
2896     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
2897     if (list)
2898       gst_element_found_tags_for_pad (GST_ELEMENT_CAST (qtdemux), stream->pad,
2899           list);
2900   }
2901 done:
2902   return TRUE;
2903
2904 too_many_streams:
2905   {
2906     GST_ELEMENT_WARNING (qtdemux, STREAM, DECODE,
2907         (_("This file contains too many streams. Only playing first %d"),
2908             GST_QTDEMUX_MAX_STREAMS), (NULL));
2909     return TRUE;
2910   }
2911 }
2912
2913 /* collect all samples for @stream by reading the info from @stbl
2914  */
2915 static gboolean
2916 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream,
2917     GNode * stbl)
2918 {
2919   int offset;
2920   GNode *stsc;
2921   GNode *stsz;
2922   GNode *stco;
2923   GNode *co64;
2924   GNode *stts;
2925   GNode *stss;
2926   GNode *ctts;
2927   const guint8 *stsc_data, *stsz_data, *stco_data;
2928   int sample_size;
2929   int sample_index;
2930   int n_samples;
2931   int n_samples_per_chunk;
2932   int n_sample_times;
2933   QtDemuxSample *samples;
2934   gint i, j, k;
2935   int index;
2936   guint64 timestamp, time;
2937
2938   /* sample to chunk */
2939   if (!(stsc = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsc)))
2940     goto corrupt_file;
2941   stsc_data = (const guint8 *) stsc->data;
2942   /* sample size */
2943   if (!(stsz = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsz)))
2944     goto corrupt_file;
2945   stsz_data = (const guint8 *) stsz->data;
2946   /* chunk offsets */
2947   stco = qtdemux_tree_get_child_by_type (stbl, FOURCC_stco);
2948   co64 = qtdemux_tree_get_child_by_type (stbl, FOURCC_co64);
2949   if (stco) {
2950     stco_data = (const guint8 *) stco->data;
2951   } else {
2952     stco_data = NULL;
2953     if (co64 == NULL)
2954       goto corrupt_file;
2955   }
2956   /* sample time */
2957   if (!(stts = qtdemux_tree_get_child_by_type (stbl, FOURCC_stts)))
2958     goto corrupt_file;
2959
2960   /* sample sync, can be NULL */
2961   stss = qtdemux_tree_get_child_by_type (stbl, FOURCC_stss);
2962
2963   sample_size = QT_UINT32 (stsz_data + 12);
2964   if (sample_size == 0 || stream->sampled) {
2965     n_samples = QT_UINT32 (stsz_data + 16);
2966     GST_DEBUG_OBJECT (qtdemux, "stsz sample_size 0, allocating n_samples %d",
2967         n_samples);
2968     stream->n_samples = n_samples;
2969     samples = g_new0 (QtDemuxSample, n_samples);
2970     stream->samples = samples;
2971
2972     for (i = 0; i < n_samples; i++) {
2973       if (sample_size == 0)
2974         samples[i].size = QT_UINT32 (stsz_data + i * 4 + 20);
2975       else
2976         samples[i].size = sample_size;
2977
2978       GST_LOG_OBJECT (qtdemux, "sample %d has size %d", i, samples[i].size);
2979       /* init other fields to defaults for this sample */
2980       samples[i].keyframe = FALSE;
2981     }
2982     n_samples_per_chunk = QT_UINT32 (stsc_data + 12);
2983     index = 0;
2984     for (i = 0; i < n_samples_per_chunk; i++) {
2985       guint32 first_chunk, last_chunk;
2986       guint32 samples_per_chunk;
2987
2988       first_chunk = QT_UINT32 (stsc_data + 16 + i * 12 + 0) - 1;
2989       if (i == n_samples_per_chunk - 1) {
2990         last_chunk = G_MAXUINT32;
2991       } else {
2992         last_chunk = QT_UINT32 (stsc_data + 16 + i * 12 + 12) - 1;
2993       }
2994       samples_per_chunk = QT_UINT32 (stsc_data + 16 + i * 12 + 4);
2995
2996       for (j = first_chunk; j < last_chunk; j++) {
2997         guint64 chunk_offset;
2998
2999         if (stco) {
3000           chunk_offset = QT_UINT32 (stco_data + 16 + j * 4);
3001         } else {
3002           chunk_offset = QT_UINT64 ((guint8 *) co64->data + 16 + j * 8);
3003         }
3004         for (k = 0; k < samples_per_chunk; k++) {
3005           GST_LOG_OBJECT (qtdemux, "Creating entry %d with offset %lld",
3006               index, chunk_offset);
3007           samples[index].chunk = j;
3008           samples[index].offset = chunk_offset;
3009           chunk_offset += samples[index].size;
3010           index++;
3011           if (index >= n_samples)
3012             goto done2;
3013         }
3014       }
3015     }
3016   done2:
3017
3018     n_sample_times = QT_UINT32 ((guint8 *) stts->data + 12);
3019     timestamp = 0;
3020     stream->min_duration = 0;
3021     time = 0;
3022     index = 0;
3023     for (i = 0; i < n_sample_times; i++) {
3024       guint32 n;
3025       guint32 duration;
3026
3027       n = QT_UINT32 ((guint8 *) stts->data + 16 + 8 * i);
3028       duration = QT_UINT32 ((guint8 *) stts->data + 16 + 8 * i + 4);
3029       for (j = 0; j < n; j++) {
3030         GST_DEBUG_OBJECT (qtdemux, "sample %d: timestamp %" GST_TIME_FORMAT,
3031             index, GST_TIME_ARGS (timestamp));
3032
3033         samples[index].timestamp = timestamp;
3034         /* take first duration for fps */
3035         if (stream->min_duration == 0)
3036           stream->min_duration = duration;
3037         /* add non-scaled values to avoid rounding errors */
3038         time += duration;
3039         timestamp = gst_util_uint64_scale (time, GST_SECOND, stream->timescale);
3040         samples[index].duration = timestamp - samples[index].timestamp;
3041
3042         index++;
3043       }
3044     }
3045     if (stss) {
3046       /* mark keyframes */
3047       guint32 n_sample_syncs;
3048
3049       n_sample_syncs = QT_UINT32 ((guint8 *) stss->data + 12);
3050       if (n_sample_syncs == 0) {
3051         stream->all_keyframe = TRUE;
3052       } else {
3053         offset = 16;
3054         for (i = 0; i < n_sample_syncs; i++) {
3055           /* note that the first sample is index 1, not 0 */
3056           index = QT_UINT32 ((guint8 *) stss->data + offset);
3057           if (index > 0) {
3058             samples[index - 1].keyframe = TRUE;
3059             offset += 4;
3060           }
3061         }
3062       }
3063     } else {
3064       /* no stss, all samples are keyframes */
3065       stream->all_keyframe = TRUE;
3066     }
3067   } else {
3068     GST_DEBUG_OBJECT (qtdemux,
3069         "stsz sample_size %d != 0, treating chunks as samples", sample_size);
3070
3071     /* treat chunks as samples */
3072     if (stco) {
3073       n_samples = QT_UINT32 (stco_data + 12);
3074     } else {
3075       n_samples = QT_UINT32 ((guint8 *) co64->data + 12);
3076     }
3077     stream->n_samples = n_samples;
3078     GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %d", n_samples);
3079     samples = g_new0 (QtDemuxSample, n_samples);
3080     stream->samples = samples;
3081
3082     n_samples_per_chunk = QT_UINT32 (stsc_data + 12);
3083     GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %d", n_samples_per_chunk);
3084     sample_index = 0;
3085     timestamp = 0;
3086     for (i = 0; i < n_samples_per_chunk; i++) {
3087       guint32 first_chunk, last_chunk;
3088       guint32 samples_per_chunk;
3089
3090       first_chunk = QT_UINT32 (stsc_data + 16 + i * 12 + 0) - 1;
3091       /* the last chunk of each entry is calculated by taking the first chunk
3092        * of the next entry; except if there is no next, where we fake it with
3093        * INT_MAX */
3094       if (i == n_samples_per_chunk - 1) {
3095         last_chunk = G_MAXUINT32;
3096       } else {
3097         last_chunk = QT_UINT32 (stsc_data + 16 + i * 12 + 12) - 1;
3098       }
3099       samples_per_chunk = QT_UINT32 (stsc_data + 16 + i * 12 + 4);
3100
3101       GST_LOG_OBJECT (qtdemux,
3102           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d", i,
3103           first_chunk, last_chunk, samples_per_chunk);
3104
3105       for (j = first_chunk; j < last_chunk; j++) {
3106         guint64 chunk_offset;
3107
3108         if (j >= n_samples)
3109           goto done;
3110
3111         if (stco) {
3112           chunk_offset = QT_UINT32 (stco_data + 16 + j * 4);
3113         } else {
3114           chunk_offset = QT_UINT64 ((guint8 *) co64->data + 16 + j * 8);
3115         }
3116         GST_LOG_OBJECT (qtdemux,
3117             "Creating entry %d with offset %" G_GUINT64_FORMAT, j,
3118             chunk_offset);
3119
3120         samples[j].chunk = j;
3121         samples[j].offset = chunk_offset;
3122
3123         if (stream->samples_per_frame * stream->bytes_per_frame) {
3124           samples[j].size = (samples_per_chunk * stream->n_channels) /
3125               stream->samples_per_frame * stream->bytes_per_frame;
3126         } else {
3127           samples[j].size = samples_per_chunk;
3128         }
3129
3130         GST_DEBUG_OBJECT (qtdemux, "sample %d: timestamp %" GST_TIME_FORMAT
3131             ", size %u", j, GST_TIME_ARGS (timestamp), samples[j].size);
3132
3133         samples[j].timestamp = timestamp;
3134         sample_index += samples_per_chunk;
3135
3136         timestamp = gst_util_uint64_scale (sample_index,
3137             GST_SECOND, stream->timescale);
3138         samples[j].duration = timestamp - samples[j].timestamp;
3139
3140         samples[j].keyframe = TRUE;
3141       }
3142     }
3143   }
3144
3145   /* composition time to sample */
3146   if ((ctts = qtdemux_tree_get_child_by_type (stbl, FOURCC_ctts))) {
3147     const guint8 *ctts_data = (const guint8 *) ctts->data;
3148     guint32 n_entries = QT_UINT32 (ctts_data + 12);
3149     guint32 count;
3150     gint32 soffset;
3151
3152     /* Fill in the pts_offsets */
3153     for (i = 0, j = 0; (j < stream->n_samples) && (i < n_entries); i++) {
3154       count = QT_UINT32 (ctts_data + 16 + i * 8);
3155       soffset = QT_UINT32 (ctts_data + 20 + i * 8);
3156       for (k = 0; k < count; k++, j++) {
3157         /* we operate with very small soffset values here, it shouldn't overflow */
3158         samples[j].pts_offset = soffset * GST_SECOND / stream->timescale;
3159       }
3160     }
3161   }
3162 done:
3163   return TRUE;
3164
3165 /* ERRORS */
3166 corrupt_file:
3167   {
3168     GST_ELEMENT_ERROR (qtdemux, STREAM, DECODE,
3169         (_("This file is corrupt and cannot be played.")), (NULL));
3170     return FALSE;
3171   }
3172 }
3173
3174 /* collect all segment info for @stream.
3175  */
3176 static gboolean
3177 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
3178     GNode * trak)
3179 {
3180   GNode *edts;
3181
3182   /* parse and prepare segment info from the edit list */
3183   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
3184   stream->n_segments = 0;
3185   stream->segments = NULL;
3186   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
3187     GNode *elst;
3188     gint n_segments;
3189     gint i, count;
3190     guint64 time, stime;
3191     guint8 *buffer;
3192
3193     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
3194     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
3195       goto done;
3196
3197     buffer = elst->data;
3198
3199     n_segments = QT_UINT32 (buffer + 12);
3200
3201     /* we might allocate a bit too much, at least allocate 1 segment */
3202     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
3203
3204     /* segments always start from 0 */
3205     time = 0;
3206     stime = 0;
3207     count = 0;
3208     for (i = 0; i < n_segments; i++) {
3209       guint64 duration;
3210       guint64 media_time;
3211       QtDemuxSegment *segment;
3212
3213       media_time = QT_UINT32 (buffer + 20 + i * 12);
3214
3215       /* -1 media time is an empty segment, just ignore it */
3216       if (media_time == G_MAXUINT32)
3217         continue;
3218
3219       duration = QT_UINT32 (buffer + 16 + i * 12);
3220
3221       segment = &stream->segments[count++];
3222
3223       /* time and duration expressed in global timescale */
3224       segment->time = stime;
3225       /* add non scaled values so we don't cause roundoff errors */
3226       time += duration;
3227       stime = gst_util_uint64_scale (time, GST_SECOND, qtdemux->timescale);
3228       segment->stop_time = stime;
3229       segment->duration = stime - segment->time;
3230       /* media_time expressed in stream timescale */
3231       segment->media_start =
3232           gst_util_uint64_scale (media_time, GST_SECOND, stream->timescale);
3233       segment->media_stop = segment->media_start + segment->duration;
3234       segment->rate = QT_FP32 (buffer + 24 + i * 12);
3235
3236       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
3237           ", duration %" GST_TIME_FORMAT ", media_time %" GST_TIME_FORMAT
3238           ", rate %g", i, GST_TIME_ARGS (segment->time),
3239           GST_TIME_ARGS (segment->duration),
3240           GST_TIME_ARGS (segment->media_start), segment->rate);
3241     }
3242     GST_DEBUG_OBJECT (qtdemux, "found %d non-empty segments", count);
3243     stream->n_segments = count;
3244   }
3245 done:
3246
3247   /* no segments, create one to play the complete trak */
3248   if (stream->n_segments == 0) {
3249     if (stream->segments == NULL)
3250       stream->segments = g_new (QtDemuxSegment, 1);
3251
3252     stream->segments[0].time = 0;
3253     stream->segments[0].stop_time = qtdemux->segment.duration;
3254     stream->segments[0].duration = qtdemux->segment.duration;
3255     stream->segments[0].media_start = 0;
3256     stream->segments[0].media_stop = qtdemux->segment.duration;
3257     stream->segments[0].rate = 1.0;
3258
3259     GST_DEBUG_OBJECT (qtdemux, "created dummy segment");
3260     stream->n_segments = 1;
3261   }
3262   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
3263
3264   return TRUE;
3265 }
3266
3267 /* parse the traks.
3268  * With each track we associate a new QtDemuxStream that contains all the info
3269  * about the trak.
3270  * traks that do not decode to something (like strm traks) will not have a pad.
3271  */
3272 static gboolean
3273 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
3274 {
3275   int offset;
3276   GNode *tkhd;
3277   GNode *mdia;
3278   GNode *mdhd;
3279   GNode *hdlr;
3280   GNode *minf;
3281   GNode *stbl;
3282   GNode *stsd;
3283   GNode *mp4a;
3284   GNode *mp4v;
3285   GNode *wave;
3286   GNode *esds;
3287   QtDemuxStream *stream;
3288   GstTagList *list = NULL;
3289   gchar *codec = NULL;
3290   const guint8 *stsd_data;
3291   guint32 version;
3292
3293   stream = g_new0 (QtDemuxStream, 1);
3294   /* new streams always need a discont */
3295   stream->discont = TRUE;
3296   /* we enable clipping for raw audio/video streams */
3297   stream->need_clip = FALSE;
3298   stream->segment_index = -1;
3299   stream->time_position = 0;
3300   stream->sample_index = -1;
3301   stream->last_ret = GST_FLOW_OK;
3302
3303   if (!(tkhd = qtdemux_tree_get_child_by_type (trak, FOURCC_tkhd)))
3304     goto corrupt_file;
3305
3306   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags: 0x%08x",
3307       QT_UINT32 ((guint8 *) tkhd->data + 8));
3308
3309   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
3310     goto corrupt_file;
3311
3312   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
3313     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
3314     if (qtdemux->major_brand != FOURCC_mjp2 ||
3315         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
3316       goto corrupt_file;
3317   }
3318
3319   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
3320   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
3321   if (version == 0x01000000) {
3322     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
3323     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
3324   } else {
3325     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
3326     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
3327   }
3328
3329   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
3330       stream->timescale);
3331   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
3332       stream->duration);
3333
3334   if (qtdemux->duration != G_MAXINT32 && stream->duration != G_MAXINT32) {
3335     guint64 tdur1, tdur2;
3336
3337     /* don't overflow */
3338     tdur1 = stream->timescale * (guint64) qtdemux->duration;
3339     tdur2 = qtdemux->timescale * (guint64) stream->duration;
3340
3341     /* HACK:
3342      * some of those trailers, nowadays, have prologue images that are
3343      * themselves vide tracks as well. I haven't really found a way to
3344      * identify those yet, except for just looking at their duration. */
3345     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
3346       GST_WARNING_OBJECT (qtdemux,
3347           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
3348           " vs. %" G_GUINT32_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
3349           "found, assuming preview image or something; skipping track",
3350           stream->duration, stream->timescale, qtdemux->duration,
3351           qtdemux->timescale);
3352       g_free (stream);
3353       return TRUE;
3354     }
3355   }
3356
3357   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
3358     goto corrupt_file;
3359
3360   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
3361       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
3362
3363   stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
3364   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
3365       GST_FOURCC_ARGS (stream->subtype));
3366
3367   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
3368     goto corrupt_file;
3369
3370   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
3371     goto corrupt_file;
3372
3373   /* parse stsd */
3374   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
3375     goto corrupt_file;
3376   stsd_data = (const guint8 *) stsd->data;
3377
3378   if (stream->subtype == FOURCC_vide) {
3379     guint32 fourcc;
3380
3381     stream->sampled = TRUE;
3382
3383     offset = 16;
3384     stream->fourcc = fourcc = QT_FOURCC (stsd_data + offset + 4);
3385     GST_LOG_OBJECT (qtdemux, "st type:          %" GST_FOURCC_FORMAT,
3386         GST_FOURCC_ARGS (fourcc));
3387
3388     stream->width = QT_UINT16 (stsd_data + offset + 32);
3389     stream->height = QT_UINT16 (stsd_data + offset + 34);
3390     stream->fps_n = 0;          /* this is filled in later */
3391     stream->fps_d = 0;          /* this is filled in later */
3392     stream->bits_per_sample = QT_UINT16 (stsd_data + offset + 82);
3393     stream->color_table_id = QT_UINT16 (stsd_data + offset + 84);
3394
3395     GST_LOG_OBJECT (qtdemux, "frame count:   %u",
3396         QT_UINT16 (stsd_data + offset + 48));
3397
3398     if (fourcc == FOURCC_drms)
3399       goto error_encrypted;
3400
3401     stream->caps =
3402         qtdemux_video_caps (qtdemux, stream, fourcc, stsd_data, &codec);
3403     if (codec) {
3404       list = gst_tag_list_new ();
3405       gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
3406           GST_TAG_VIDEO_CODEC, codec, NULL);
3407       g_free (codec);
3408       codec = NULL;
3409     }
3410
3411     esds = NULL;
3412     mp4v = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4v);
3413     if (mp4v)
3414       esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
3415
3416     if (esds) {
3417       gst_qtdemux_handle_esds (qtdemux, stream, esds, list);
3418     } else {
3419       switch (fourcc) {
3420         case FOURCC_avc1:
3421         {
3422           gint len = QT_UINT32 (stsd_data) - 0x66;
3423           const guint8 *avc_data = stsd_data + 0x66;
3424
3425           /* find avcC */
3426           while (len >= 0x8 &&
3427               QT_FOURCC (avc_data + 0x4) != FOURCC_avcC &&
3428               QT_UINT32 (avc_data) < len) {
3429             len -= QT_UINT32 (avc_data);
3430             avc_data += QT_UINT32 (avc_data);
3431           }
3432
3433           /* parse, if found */
3434           if (len > 0x8 && QT_FOURCC (avc_data + 0x4) == FOURCC_avcC) {
3435             GstBuffer *buf;
3436             gint size;
3437
3438             if (QT_UINT32 (avc_data) < len)
3439               size = QT_UINT32 (avc_data) - 0x8;
3440             else
3441               size = len - 0x8;
3442
3443             GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
3444
3445             buf = gst_buffer_new_and_alloc (size);
3446             memcpy (GST_BUFFER_DATA (buf), avc_data + 0x8, size);
3447             gst_caps_set_simple (stream->caps,
3448                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
3449             gst_buffer_unref (buf);
3450           }
3451           break;
3452         }
3453         case FOURCC_mjp2:
3454         {
3455           GNode *jp2h, *colr, *mjp2, *field, *prefix;
3456           const guint8 *data;
3457           guint32 fourcc = 0;
3458
3459           GST_DEBUG_OBJECT (qtdemux, "found mjp2");
3460           /* some required atoms */
3461           mjp2 = qtdemux_tree_get_child_by_type (stsd, FOURCC_mjp2);
3462           if (!mjp2)
3463             break;
3464           jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
3465           if (!jp2h)
3466             break;
3467           colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
3468           if (!colr)
3469             break;
3470           GST_DEBUG_OBJECT (qtdemux, "found colr");
3471           /* try to extract colour space info */
3472           if (QT_UINT8 (colr->data + 8) == 1) {
3473             switch (QT_UINT32 (colr->data + 11)) {
3474               case 16:
3475                 fourcc = GST_MAKE_FOURCC ('s', 'R', 'G', 'B');
3476                 break;
3477               case 17:
3478                 fourcc = GST_MAKE_FOURCC ('G', 'R', 'A', 'Y');
3479                 break;
3480               case 18:
3481                 fourcc = GST_MAKE_FOURCC ('s', 'Y', 'U', 'V');
3482                 break;
3483               default:
3484                 break;
3485             }
3486           }
3487
3488           if (fourcc)
3489             gst_caps_set_simple (stream->caps,
3490                 "fourcc", GST_TYPE_FOURCC, fourcc, NULL);
3491
3492           /* some optional atoms */
3493           field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
3494           prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
3495
3496           /* indicate possible fields in caps */
3497           if (field) {
3498             data = field->data + 8;
3499             if (*data != 1)
3500               gst_caps_set_simple (stream->caps, "fields", G_TYPE_INT,
3501                   (gint) * data, NULL);
3502           }
3503           /* add codec_data if provided */
3504           if (prefix) {
3505             GstBuffer *buf;
3506             gint len;
3507
3508             GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
3509             data = prefix->data;
3510             len = QT_UINT32 (data);
3511             if (len > 0x8) {
3512               len -= 0x8;
3513               buf = gst_buffer_new_and_alloc (len);
3514               memcpy (GST_BUFFER_DATA (buf), data + 8, len);
3515               gst_caps_set_simple (stream->caps,
3516                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
3517               gst_buffer_unref (buf);
3518             }
3519           }
3520           break;
3521         }
3522         case FOURCC_SVQ3:
3523         case FOURCC_VP31:
3524         {
3525           GstBuffer *buf;
3526           gint len = QT_UINT32 (stsd_data);
3527
3528           GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
3529
3530           buf = gst_buffer_new_and_alloc (len);
3531           memcpy (GST_BUFFER_DATA (buf), stsd_data, len);
3532           gst_caps_set_simple (stream->caps,
3533               "codec_data", GST_TYPE_BUFFER, buf, NULL);
3534           gst_buffer_unref (buf);
3535           break;
3536         }
3537         case FOURCC_rle_:
3538         {
3539           gst_caps_set_simple (stream->caps,
3540               "depth", G_TYPE_INT, QT_UINT16 (stsd_data + offset + 82), NULL);
3541           break;
3542         }
3543         case FOURCC_XiTh:
3544         {
3545           GNode *xith, *xdxt;
3546
3547           GST_DEBUG_OBJECT (qtdemux, "found XiTh");
3548           xith = qtdemux_tree_get_child_by_type (stsd, FOURCC_XiTh);
3549           if (!xith)
3550             break;
3551
3552           xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
3553           if (!xdxt)
3554             break;
3555
3556           GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
3557           /* collect the headers and store them in a stream list so that we can
3558            * send them out first */
3559           qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
3560           break;
3561         }
3562         default:
3563           break;
3564       }
3565     }
3566
3567     GST_INFO_OBJECT (qtdemux,
3568         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
3569         GST_FOURCC_ARGS (fourcc), stream->caps);
3570
3571   } else if (stream->subtype == FOURCC_soun) {
3572     int version, samplesize;
3573     guint32 fourcc;
3574     int len;
3575     guint16 compression_id;
3576
3577     len = QT_UINT32 (stsd_data + 16);
3578     GST_LOG_OBJECT (qtdemux, "stsd len:           %d", len);
3579
3580     stream->fourcc = fourcc = QT_FOURCC (stsd_data + 16 + 4);
3581     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
3582         GST_FOURCC_ARGS (stream->fourcc));
3583
3584     offset = 32;
3585
3586     version = QT_UINT32 (stsd_data + offset);
3587     stream->n_channels = QT_UINT16 (stsd_data + offset + 8);
3588     samplesize = QT_UINT16 (stsd_data + offset + 10);
3589     compression_id = QT_UINT16 (stsd_data + offset + 12);
3590     stream->rate = QT_FP32 (stsd_data + offset + 16);
3591
3592     GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
3593     GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
3594         QT_UINT32 (stsd_data + offset + 4));
3595     GST_LOG_OBJECT (qtdemux, "n_channels:       %d", stream->n_channels);
3596     GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
3597     GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
3598     GST_LOG_OBJECT (qtdemux, "packet size:      %d",
3599         QT_UINT16 (stsd_data + offset + 14));
3600     GST_LOG_OBJECT (qtdemux, "sample rate:      %g", stream->rate);
3601
3602     if (compression_id == 0xfffe)
3603       stream->sampled = TRUE;
3604
3605     /* first assume uncompressed audio */
3606     stream->bytes_per_sample = samplesize / 8;
3607     stream->samples_per_frame = stream->n_channels;
3608     stream->bytes_per_frame = stream->n_channels * stream->bytes_per_sample;
3609     stream->samples_per_packet = stream->samples_per_frame;
3610     stream->bytes_per_packet = stream->bytes_per_sample;
3611
3612     offset = 52;
3613     switch (fourcc) {
3614         /* Yes, these have to be hard-coded */
3615       case FOURCC_MAC6:
3616       {
3617         stream->samples_per_packet = 6;
3618         stream->bytes_per_packet = 1;
3619         stream->bytes_per_frame = 1 * stream->n_channels;
3620         stream->bytes_per_sample = 1;
3621         stream->samples_per_frame = 6 * stream->n_channels;
3622         break;
3623       }
3624       case FOURCC_MAC3:
3625       {
3626         stream->samples_per_packet = 3;
3627         stream->bytes_per_packet = 1;
3628         stream->bytes_per_frame = 1 * stream->n_channels;
3629         stream->bytes_per_sample = 1;
3630         stream->samples_per_frame = 3 * stream->n_channels;
3631         break;
3632       }
3633       case FOURCC_ima4:
3634       {
3635         stream->samples_per_packet = 64;
3636         stream->bytes_per_packet = 34;
3637         stream->bytes_per_frame = 34 * stream->n_channels;
3638         stream->bytes_per_sample = 2;
3639         stream->samples_per_frame = 64 * stream->n_channels;
3640         break;
3641       }
3642       case FOURCC_ulaw:
3643       case FOURCC_alaw:
3644       {
3645         stream->samples_per_packet = 1;
3646         stream->bytes_per_packet = 1;
3647         stream->bytes_per_frame = 1 * stream->n_channels;
3648         stream->bytes_per_sample = 1;
3649         stream->samples_per_frame = 1 * stream->n_channels;
3650         break;
3651       }
3652       default:
3653         break;
3654     }
3655     if (version == 0x00010000) {
3656       switch (fourcc) {
3657         case FOURCC_twos:
3658         case FOURCC_sowt:
3659         case FOURCC_raw_:
3660           break;
3661         default:
3662         {
3663           /* only parse extra decoding config for non-pcm audio */
3664           stream->samples_per_packet = QT_UINT32 (stsd_data + offset);
3665           stream->bytes_per_packet = QT_UINT32 (stsd_data + offset + 4);
3666           stream->bytes_per_frame = QT_UINT32 (stsd_data + offset + 8);
3667           stream->bytes_per_sample = QT_UINT32 (stsd_data + offset + 12);
3668
3669           GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
3670               stream->samples_per_packet);
3671           GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
3672               stream->bytes_per_packet);
3673           GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
3674               stream->bytes_per_frame);
3675           GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
3676               stream->bytes_per_sample);
3677
3678           if (!stream->sampled && stream->bytes_per_packet) {
3679             stream->samples_per_frame = (stream->bytes_per_frame /
3680                 stream->bytes_per_packet) * stream->samples_per_packet;
3681             GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
3682                 stream->samples_per_frame);
3683           }
3684           break;
3685         }
3686       }
3687       offset = 68;
3688     } else if (version == 0x00020000) {
3689       union
3690       {
3691         gdouble fp;
3692         guint64 val;
3693       } qtfp;
3694
3695       stream->samples_per_packet = QT_UINT32 (stsd_data + offset);
3696       qtfp.val = QT_UINT64 (stsd_data + offset + 4);
3697       stream->rate = qtfp.fp;
3698       stream->n_channels = QT_UINT32 (stsd_data + offset + 12);
3699
3700       GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
3701           stream->samples_per_packet);
3702       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", stream->rate);
3703       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", stream->n_channels);
3704
3705       offset = 68;
3706     } else {
3707       GST_WARNING_OBJECT (qtdemux, "unknown version %08x", version);
3708     }
3709
3710     if (fourcc == FOURCC_drms)
3711       goto error_encrypted;
3712
3713     stream->caps = qtdemux_audio_caps (qtdemux, stream, fourcc, NULL, 0,
3714         &codec);
3715
3716     if (codec) {
3717       list = gst_tag_list_new ();
3718       gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
3719           GST_TAG_AUDIO_CODEC, codec, NULL);
3720       g_free (codec);
3721       codec = NULL;
3722     }
3723
3724     mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4a);
3725     wave = NULL;
3726     esds = NULL;
3727     if (mp4a) {
3728       wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
3729       if (wave)
3730         esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
3731       if (!esds)
3732         esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
3733     }
3734
3735     if (esds) {
3736       gst_qtdemux_handle_esds (qtdemux, stream, esds, list);
3737     } else {
3738       switch (fourcc) {
3739 #if 0
3740           /* FIXME: what is in the chunk? */
3741         case FOURCC_QDMC:
3742         {
3743           gint len = QT_UINT32 (stsd_data);
3744
3745           /* seems to be always = 116 = 0x74 */
3746           break;
3747         }
3748 #endif
3749         case FOURCC_QDM2:
3750         {
3751           gint len = QT_UINT32 (stsd_data);
3752
3753           if (len > 0x4C) {
3754             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x4C);
3755
3756             memcpy (GST_BUFFER_DATA (buf), stsd_data + 0x4C, len - 0x4C);
3757             gst_caps_set_simple (stream->caps,
3758                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
3759             gst_buffer_unref (buf);
3760           }
3761           gst_caps_set_simple (stream->caps,
3762               "samplesize", G_TYPE_INT, samplesize, NULL);
3763           break;
3764         }
3765         case FOURCC_alac:
3766         {
3767           gint len = QT_UINT32 (stsd_data);
3768
3769           if (len > 0x34) {
3770             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x34);
3771
3772             memcpy (GST_BUFFER_DATA (buf), stsd_data + 0x34, len - 0x34);
3773             gst_caps_set_simple (stream->caps,
3774                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
3775             gst_buffer_unref (buf);
3776           }
3777           gst_caps_set_simple (stream->caps,
3778               "samplesize", G_TYPE_INT, samplesize, NULL);
3779           break;
3780         }
3781         case FOURCC_samr:
3782         {
3783           gint len = QT_UINT32 (stsd_data);
3784
3785           if (len > 0x34) {
3786             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x34);
3787
3788             memcpy (GST_BUFFER_DATA (buf), stsd_data + 0x34, len - 0x34);
3789
3790             gst_caps_set_simple (stream->caps,
3791                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
3792             gst_buffer_unref (buf);
3793           }
3794           break;
3795         }
3796         default:
3797           break;
3798       }
3799     }
3800     GST_INFO_OBJECT (qtdemux,
3801         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
3802         GST_FOURCC_ARGS (fourcc), stream->caps);
3803
3804   } else if (stream->subtype == FOURCC_strm) {
3805     guint32 fourcc;
3806
3807     stream->fourcc = fourcc = QT_FOURCC (stsd_data + 16 + 4);
3808     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
3809         GST_FOURCC_ARGS (fourcc));
3810
3811     if (fourcc != FOURCC_rtsp) {
3812       GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
3813           GST_FOURCC_ARGS (fourcc));
3814       goto unknown_stream;
3815     }
3816     stream->sampled = TRUE;
3817   } else {
3818     goto unknown_stream;
3819   }
3820
3821   /* promote to sampled format */
3822   if (stream->fourcc == FOURCC_samr) {
3823     /* force mono 8000 Hz for AMR */
3824     stream->sampled = TRUE;
3825     stream->n_channels = 1;
3826     stream->rate = 8000;
3827   } else if (stream->fourcc == FOURCC_sawb) {
3828     /* force mono 16000 Hz for AMR-WB */
3829     stream->sampled = TRUE;
3830     stream->n_channels = 1;
3831     stream->rate = 16000;
3832   } else if (stream->fourcc == FOURCC_mp4a) {
3833     stream->sampled = TRUE;
3834   }
3835
3836   /* collect sample information */
3837   if (!qtdemux_parse_samples (qtdemux, stream, stbl))
3838     goto samples_failed;
3839
3840   /* configure segments */
3841   if (!qtdemux_parse_segments (qtdemux, stream, trak))
3842     goto segments_failed;
3843
3844   /* now we are ready to add the stream */
3845   gst_qtdemux_add_stream (qtdemux, stream, list);
3846
3847   return TRUE;
3848
3849 /* ERRORS */
3850 corrupt_file:
3851   {
3852     GST_ELEMENT_ERROR (qtdemux, STREAM, DECODE,
3853         (_("This file is corrupt and cannot be played.")), (NULL));
3854     g_free (stream);
3855     return FALSE;
3856   }
3857 error_encrypted:
3858   {
3859     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
3860     g_free (stream);
3861     return FALSE;
3862   }
3863 samples_failed:
3864   {
3865     /* we posted an error already */
3866     g_free (stream);
3867     return FALSE;
3868   }
3869 segments_failed:
3870   {
3871     /* we posted an error already */
3872     g_free (stream);
3873     return FALSE;
3874   }
3875 unknown_stream:
3876   {
3877     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
3878         GST_FOURCC_ARGS (stream->subtype));
3879     g_free (stream);
3880     return TRUE;
3881   }
3882 }
3883
3884 static void
3885 qtdemux_tag_add_str (GstQTDemux * qtdemux, const char *tag, const char *dummy,
3886     GNode * node)
3887 {
3888   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
3889   GNode *data;
3890   char *s;
3891   int len;
3892   int type;
3893   int offset;
3894
3895   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
3896   if (data) {
3897     len = QT_UINT32 (data->data);
3898     type = QT_UINT32 ((guint8 *) data->data + 8);
3899     if (type == 0x00000001) {
3900       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
3901           env_vars);
3902       if (s) {
3903         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
3904         gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag, s,
3905             NULL);
3906         g_free (s);
3907       } else {
3908         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
3909       }
3910     }
3911   } else {
3912     len = QT_UINT32 (node->data);
3913     type = QT_UINT32 ((guint8 *) node->data + 4);
3914     if (type & 0xa9000000) {
3915       /* Type starts with the (C) symbol, so the next 32 bits are
3916        * the language code, which we ignore */
3917       offset = 12;
3918       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
3919     } else {
3920       offset = 8;
3921       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
3922     }
3923     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
3924         len - offset, env_vars);
3925     if (s) {
3926       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
3927       gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag, s, NULL);
3928       g_free (s);
3929     } else {
3930       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
3931     }
3932   }
3933 }
3934
3935 static void
3936 qtdemux_tag_add_num (GstQTDemux * qtdemux, const char *tag1,
3937     const char *tag2, GNode * node)
3938 {
3939   GNode *data;
3940   int len;
3941   int type;
3942   int n1, n2;
3943
3944   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
3945   if (data) {
3946     len = QT_UINT32 (data->data);
3947     type = QT_UINT32 ((guint8 *) data->data + 8);
3948     if (type == 0x00000000 && len >= 22) {
3949       n1 = QT_UINT16 ((guint8 *) data->data + 18);
3950       n2 = QT_UINT16 ((guint8 *) data->data + 20);
3951       GST_DEBUG_OBJECT (qtdemux, "adding tag %d/%d", n1, n2);
3952       gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
3953           tag1, n1, tag2, n2, NULL);
3954     }
3955   }
3956 }
3957
3958 static void
3959 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, const char *tag1, const char *dummy,
3960     GNode * node)
3961 {
3962   GNode *data;
3963   int len;
3964   int type;
3965   int n1;
3966
3967   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
3968   if (data) {
3969     len = QT_UINT32 (data->data);
3970     type = QT_UINT32 ((guint8 *) data->data + 8);
3971     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
3972     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
3973     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
3974       n1 = QT_UINT16 ((guint8 *) data->data + 16);
3975       if (n1) {
3976         /* do not add bpm=0 */
3977         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
3978         gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
3979             tag1, (gdouble) n1, NULL);
3980       }
3981     }
3982   }
3983 }
3984
3985 static void
3986 qtdemux_tag_add_covr (GstQTDemux * qtdemux, const char *tag1, const char *dummy,
3987     GNode * node)
3988 {
3989   GNode *data;
3990   int len;
3991   int type;
3992   GstBuffer *buf;
3993
3994   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
3995   if (data) {
3996     len = QT_UINT32 (data->data);
3997     type = QT_UINT32 ((guint8 *) data->data + 8);
3998     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
3999     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
4000       if ((buf = gst_tag_image_data_to_image_buffer (data->data + 16, len - 16,
4001                   GST_TAG_IMAGE_TYPE_NONE))) {
4002         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
4003         gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
4004             tag1, buf, NULL);
4005       }
4006     }
4007   }
4008 }
4009
4010 static void
4011 qtdemux_tag_add_date (GstQTDemux * qtdemux, const char *tag, const char *dummy,
4012     GNode * node)
4013 {
4014   GNode *data;
4015   char *s;
4016   int len;
4017   int type;
4018
4019   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
4020   if (data) {
4021     len = QT_UINT32 (data->data);
4022     type = QT_UINT32 ((guint8 *) data->data + 8);
4023     if (type == 0x00000001) {
4024       guint y, m = 1, d = 1;
4025       gint ret;
4026
4027       s = g_strndup ((char *) data->data + 16, len - 16);
4028       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
4029       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
4030       if (ret >= 1 && y > 1500 && y < 3000) {
4031         GDate *date;
4032
4033         date = g_date_new_dmy (d, m, y);
4034         gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag,
4035             date, NULL);
4036         g_date_free (date);
4037       } else {
4038         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
4039       }
4040       g_free (s);
4041     }
4042   }
4043 }
4044
4045 static void
4046 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, const char *tag, const char *dummy,
4047     GNode * node)
4048 {
4049   static const gchar *genres[] = {
4050     "N/A", "Blues", "Classic Rock", "Country", "Dance", "Disco",
4051     "Funk", "Grunge", "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies",
4052     "Other", "Pop", "R&B", "Rap", "Reggae", "Rock", "Techno",
4053     "Industrial", "Alternative", "Ska", "Death Metal", "Pranks",
4054     "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop", "Vocal",
4055     "Jazz+Funk", "Fusion", "Trance", "Classical", "Instrumental",
4056     "Acid", "House", "Game", "Sound Clip", "Gospel", "Noise",
4057     "AlternRock", "Bass", "Soul", "Punk", "Space", "Meditative",
4058     "Instrumental Pop", "Instrumental Rock", "Ethnic", "Gothic",
4059     "Darkwave", "Techno-Industrial", "Electronic", "Pop-Folk",
4060     "Eurodance", "Dream", "Southern Rock", "Comedy", "Cult", "Gangsta",
4061     "Top 40", "Christian Rap", "Pop/Funk", "Jungle", "Native American",
4062     "Cabaret", "New Wave", "Psychadelic", "Rave", "Showtunes",
4063     "Trailer", "Lo-Fi", "Tribal", "Acid Punk", "Acid Jazz", "Polka",
4064     "Retro", "Musical", "Rock & Roll", "Hard Rock", "Folk",
4065     "Folk/Rock", "National Folk", "Swing", "Fast-Fusion", "Bebob",
4066     "Latin", "Revival", "Celtic", "Bluegrass", "Avantgarde",
4067     "Gothic Rock", "Progressive Rock", "Psychedelic Rock",
4068     "Symphonic Rock", "Slow Rock", "Big Band", "Chorus",
4069     "Easy Listening", "Acoustic", "Humour", "Speech", "Chanson",
4070     "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass",
4071     "Primus", "Porn Groove", "Satire", "Slow Jam", "Club", "Tango",
4072     "Samba", "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul",
4073     "Freestyle", "Duet", "Punk Rock", "Drum Solo", "A capella",
4074     "Euro-House", "Dance Hall", "Goa", "Drum & Bass", "Club House",
4075     "Hardcore", "Terror", "Indie", "BritPop", "NegerPunk",
4076     "Polsk Punk", "Beat", "Christian Gangsta", "Heavy Metal",
4077     "Black Metal", "Crossover", "Contemporary C", "Christian Rock",
4078     "Merengue", "Salsa", "Thrash Metal", "Anime", "JPop", "SynthPop"
4079   };
4080   GNode *data;
4081   int len;
4082   int type;
4083   int n;
4084
4085   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
4086   if (data) {
4087     len = QT_UINT32 (data->data);
4088     type = QT_UINT32 ((guint8 *) data->data + 8);
4089     if (type == 0x00000000 && len >= 18) {
4090       n = QT_UINT16 ((guint8 *) data->data + 16);
4091       if (n > 0 && n < sizeof (genres) / sizeof (char *)) {
4092         GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genres[n]);
4093         gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
4094             tag, genres[n], NULL);
4095       }
4096     }
4097   }
4098 }
4099
4100 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux,
4101     const char *tag, const char *tag_bis, GNode * node);
4102
4103 static const struct
4104 {
4105   guint32 fourcc;
4106   const gchar *gst_tag;
4107   const gchar *gst_tag_bis;
4108   const GstQTDemuxAddTagFunc func;
4109 } add_funcs[] = {
4110   {
4111   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
4112   FOURCC__grp, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
4113   FOURCC__wrt, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
4114   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
4115   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
4116   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
4117   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
4118   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
4119   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
4120   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
4121   FOURCC__too, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
4122   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
4123   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
4124         qtdemux_tag_add_num}, {
4125   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
4126         qtdemux_tag_add_num}, {
4127   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
4128   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
4129   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
4130   FOURCC_covr, GST_TAG_PREVIEW_IMAGE, NULL, qtdemux_tag_add_covr}, {
4131   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
4132   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}
4133 };
4134
4135 static void
4136 qtdemux_tag_add_blob (GNode * node, GstQTDemux * demux)
4137 {
4138   gint len;
4139   guint8 *data;
4140   GstBuffer *buf;
4141   gchar *media_type, *style;
4142   GstCaps *caps;
4143
4144   data = node->data;
4145   len = QT_UINT32 (data);
4146   buf = gst_buffer_new_and_alloc (len);
4147   memcpy (GST_BUFFER_DATA (buf), data, len);
4148
4149   /* heuristic to determine style of tag */
4150   if (QT_FOURCC (data + 4) == FOURCC_____ ||
4151       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
4152     style = "itunes";
4153   else if (demux->major_brand == GST_MAKE_FOURCC ('q', 't', ' ', ' '))
4154     style = "quicktime";
4155   /* fall back to assuming iso/3gp tag style */
4156   else
4157     style = "iso";
4158
4159   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
4160       g_ascii_tolower (data[4]), g_ascii_tolower (data[5]),
4161       g_ascii_tolower (data[6]), g_ascii_tolower (data[7]));
4162   caps = gst_caps_new_simple (media_type, "style", G_TYPE_STRING, style, NULL);
4163   gst_buffer_set_caps (buf, caps);
4164   gst_caps_unref (caps);
4165   g_free (media_type);
4166
4167   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, caps %" GST_PTR_FORMAT,
4168       GST_BUFFER_SIZE (buf), caps);
4169
4170   gst_tag_list_add (demux->tag_list, GST_TAG_MERGE_APPEND,
4171       GST_QT_DEMUX_PRIVATE_TAG, buf, NULL);
4172   gst_buffer_unref (buf);
4173 }
4174
4175 static void
4176 qtdemux_parse_udta (GstQTDemux * qtdemux, GNode * udta)
4177 {
4178   GNode *meta;
4179   GNode *ilst;
4180   GNode *node;
4181   gint i;
4182
4183   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
4184   if (meta != NULL) {
4185     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
4186     if (ilst == NULL) {
4187       GST_LOG_OBJECT (qtdemux, "no ilst");
4188       return;
4189     }
4190   } else {
4191     ilst = udta;
4192     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
4193   }
4194
4195   GST_DEBUG_OBJECT (qtdemux, "new tag list");
4196   qtdemux->tag_list = gst_tag_list_new ();
4197
4198   for (i = 0; i < G_N_ELEMENTS (add_funcs); ++i) {
4199     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
4200     if (node) {
4201       add_funcs[i].func (qtdemux, add_funcs[i].gst_tag,
4202           add_funcs[i].gst_tag_bis, node);
4203       g_node_destroy (node);
4204     }
4205   }
4206
4207   /* parsed nodes have been removed, pass along remainder as blob */
4208   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
4209       (GNodeForeachFunc) qtdemux_tag_add_blob, qtdemux);
4210
4211 }
4212
4213 typedef struct
4214 {
4215   GstStructure *structure;      /* helper for sort function */
4216   gchar *location;
4217   guint min_req_bitrate;
4218   guint min_req_qt_version;
4219 } GstQtReference;
4220
4221 static gint
4222 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
4223 {
4224   GstQtReference *ref_a = (GstQtReference *) a;
4225   GstQtReference *ref_b = (GstQtReference *) b;
4226
4227   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
4228     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
4229
4230   /* known bitrates go before unknown; higher bitrates go first */
4231   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
4232 }
4233
4234 /* sort the redirects and post a message for the application.
4235  */
4236 static void
4237 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
4238 {
4239   GstQtReference *best;
4240   GstStructure *s;
4241   GstMessage *msg;
4242   GValue list_val = { 0, };
4243   GList *l;
4244
4245   g_assert (references != NULL);
4246
4247   references = g_list_sort (references, qtdemux_redirects_sort_func);
4248
4249   best = (GstQtReference *) references->data;
4250
4251   g_value_init (&list_val, GST_TYPE_LIST);
4252
4253   for (l = references; l != NULL; l = l->next) {
4254     GstQtReference *ref = (GstQtReference *) l->data;
4255     GValue struct_val = { 0, };
4256
4257     ref->structure = gst_structure_new ("redirect",
4258         "new-location", G_TYPE_STRING, ref->location, NULL);
4259
4260     if (ref->min_req_bitrate > 0) {
4261       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
4262           ref->min_req_bitrate, NULL);
4263     }
4264
4265     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
4266     g_value_set_boxed (&struct_val, ref->structure);
4267     gst_value_list_append_value (&list_val, &struct_val);
4268     g_value_unset (&struct_val);
4269     /* don't free anything here yet, since we need best->structure below */
4270   }
4271
4272   g_assert (best != NULL);
4273   s = gst_structure_copy (best->structure);
4274
4275   if (g_list_length (references) > 1) {
4276     gst_structure_set_value (s, "locations", &list_val);
4277   }
4278
4279   g_value_unset (&list_val);
4280
4281   for (l = references; l != NULL; l = l->next) {
4282     GstQtReference *ref = (GstQtReference *) l->data;
4283
4284     gst_structure_free (ref->structure);
4285     g_free (ref->location);
4286     g_free (ref);
4287   }
4288   g_list_free (references);
4289
4290   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
4291   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
4292   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
4293 }
4294
4295 /* look for redirect nodes, collect all redirect information and
4296  * process it.
4297  */
4298 static gboolean
4299 qtdemux_parse_redirects (GstQTDemux * qtdemux)
4300 {
4301   GNode *rmra, *rmda, *rdrf;
4302
4303   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
4304   if (rmra) {
4305     GList *redirects = NULL;
4306
4307     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
4308     while (rmda) {
4309       GstQtReference ref = { NULL, NULL, 0, 0 };
4310       GNode *rmdr, *rmvc;
4311
4312       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
4313         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
4314         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
4315             ref.min_req_bitrate);
4316       }
4317
4318       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
4319         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
4320         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
4321
4322 #ifndef GST_DISABLE_GST_DEBUG
4323         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
4324 #endif
4325         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
4326
4327         GST_LOG_OBJECT (qtdemux,
4328             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
4329             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
4330             bitmask, check_type);
4331         if (package == FOURCC_qtim && check_type == 0) {
4332           ref.min_req_qt_version = version;
4333         }
4334       }
4335
4336       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
4337       if (rdrf) {
4338         guint32 ref_type;
4339         guint8 *ref_data;
4340
4341         ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
4342         ref_data = (guint8 *) rdrf->data + 20;
4343         if (ref_type == FOURCC_alis) {
4344           guint record_len, record_version, fn_len;
4345
4346           /* MacOSX alias record, google for alias-layout.txt */
4347           record_len = QT_UINT16 (ref_data + 4);
4348           record_version = QT_UINT16 (ref_data + 4 + 2);
4349           fn_len = QT_UINT8 (ref_data + 50);
4350           if (record_len > 50 && record_version == 2 && fn_len > 0) {
4351             ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
4352           }
4353         } else if (ref_type == FOURCC_url_) {
4354           ref.location = g_strdup ((gchar *) ref_data);
4355         } else {
4356           GST_DEBUG_OBJECT (qtdemux,
4357               "unknown rdrf reference type %" GST_FOURCC_FORMAT,
4358               GST_FOURCC_ARGS (ref_type));
4359         }
4360         if (ref.location != NULL) {
4361           GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
4362           redirects = g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
4363         } else {
4364           GST_WARNING_OBJECT (qtdemux,
4365               "Failed to extract redirect location from rdrf atom");
4366         }
4367       }
4368
4369       /* look for others */
4370       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
4371     }
4372
4373     if (redirects != NULL) {
4374       qtdemux_process_redirects (qtdemux, redirects);
4375     }
4376   }
4377   return TRUE;
4378 }
4379
4380 /* we have read th complete moov node now.
4381  * This function parses all of the relevant info, creates the traks and
4382  * prepares all data structures for playback
4383  */
4384 static gboolean
4385 qtdemux_parse_tree (GstQTDemux * qtdemux)
4386 {
4387   GNode *mvhd;
4388   GNode *trak;
4389   GNode *udta;
4390   gint64 duration;
4391
4392   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
4393   if (mvhd == NULL) {
4394     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
4395     return qtdemux_parse_redirects (qtdemux);
4396   }
4397
4398   qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
4399   qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
4400
4401   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
4402   GST_INFO_OBJECT (qtdemux, "duration: %u", qtdemux->duration);
4403
4404   /* set duration in the segment info */
4405   gst_qtdemux_get_duration (qtdemux, &duration);
4406   gst_segment_set_duration (&qtdemux->segment, GST_FORMAT_TIME, duration);
4407
4408   /* parse all traks */
4409   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
4410   while (trak) {
4411     qtdemux_parse_trak (qtdemux, trak);
4412     /* iterate all siblings */
4413     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
4414   }
4415   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
4416
4417   /* find and push tags, we do this after adding the pads so we can push the
4418    * tags downstream as well. */
4419   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
4420   if (udta) {
4421     qtdemux_parse_udta (qtdemux, udta);
4422
4423     if (qtdemux->tag_list) {
4424       GST_DEBUG_OBJECT (qtdemux,
4425           "calling gst_element_found_tags with %" GST_PTR_FORMAT,
4426           qtdemux->tag_list);
4427       gst_element_found_tags (GST_ELEMENT_CAST (qtdemux), qtdemux->tag_list);
4428       qtdemux->tag_list = NULL;
4429     }
4430   } else {
4431     GST_LOG_OBJECT (qtdemux, "No udta node found.");
4432   }
4433   return TRUE;
4434 }
4435
4436 /* taken from ffmpeg */
4437 static unsigned int
4438 get_size (guint8 * ptr, guint8 ** end)
4439 {
4440   int count = 4;
4441   int len = 0;
4442
4443   while (count--) {
4444     int c = *ptr;
4445
4446     ptr++;
4447     len = (len << 7) | (c & 0x7f);
4448     if (!(c & 0x80))
4449       break;
4450   }
4451   if (end)
4452     *end = ptr;
4453   return len;
4454 }
4455
4456 /* this can change the codec originally present in @list */
4457 static void
4458 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
4459     GNode * esds, GstTagList * list)
4460 {
4461   int len = QT_UINT32 (esds->data);
4462   guint8 *ptr = esds->data;
4463   guint8 *end = ptr + len;
4464   int tag;
4465   guint8 *data_ptr = NULL;
4466   int data_len = 0;
4467   guint8 object_type_id = 0;
4468
4469   qtdemux_dump_mem (ptr, len);
4470   ptr += 8;
4471   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
4472   ptr += 4;
4473   while (ptr < end) {
4474     tag = QT_UINT8 (ptr);
4475     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
4476     ptr++;
4477     len = get_size (ptr, &ptr);
4478     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
4479
4480     switch (tag) {
4481       case 0x03:
4482         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
4483         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
4484         ptr += 3;
4485         break;
4486       case 0x04:
4487         object_type_id = QT_UINT8 (ptr);
4488         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
4489         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
4490         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
4491         GST_DEBUG_OBJECT (qtdemux, "max bitrate %d", QT_UINT32 (ptr + 5));
4492         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %d", QT_UINT32 (ptr + 9));
4493         ptr += 13;
4494         break;
4495       case 0x05:
4496         GST_DEBUG_OBJECT (qtdemux, "data:");
4497         qtdemux_dump_mem (ptr, len);
4498         data_ptr = ptr;
4499         data_len = len;
4500         ptr += len;
4501         break;
4502       case 0x06:
4503         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
4504         ptr += 1;
4505         break;
4506       default:
4507         GST_ERROR_OBJECT (qtdemux, "parse error");
4508     }
4509   }
4510
4511   if (data_ptr) {
4512     GstBuffer *buffer;
4513
4514     buffer = gst_buffer_new_and_alloc (data_len);
4515     memcpy (GST_BUFFER_DATA (buffer), data_ptr, data_len);
4516     qtdemux_dump_mem (GST_BUFFER_DATA (buffer), data_len);
4517
4518     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
4519
4520     gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
4521         buffer, NULL);
4522     gst_buffer_unref (buffer);
4523   }
4524   /* object_type_id in the stsd atom in mp4a tells us about AAC or plain
4525    * MPEG audio and other formats */
4526   switch (object_type_id) {
4527     case 107:
4528       /* change to mpeg1 layer 3 audio */
4529       gst_caps_set_simple (stream->caps, "layer", G_TYPE_INT, 3,
4530           "mpegversion", G_TYPE_INT, 1, NULL);
4531       if (list)
4532         gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
4533             GST_TAG_AUDIO_CODEC, "MPEG-1 layer 3", NULL);
4534       break;
4535     case 0xE1:
4536     {
4537       GstStructure *structure;
4538
4539       /* QCELP, the codec_data is a riff tag (little endian) with
4540        * more info (http://ftp.3gpp2.org/TSGC/Working/2003/2003-05-SanDiego/TSG-C-2003-05-San%20Diego/WG1/SWG12/C12-20030512-006%20=%20C12-20030217-015_Draft_Baseline%20Text%20of%20FFMS_R2.doc). */
4541       structure = gst_caps_get_structure (stream->caps, 0);
4542       gst_structure_set_name (structure, "audio/qcelp");
4543       gst_structure_remove_fields (structure, "mpegversion", "framed", NULL);
4544
4545       if (list)
4546         gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
4547             GST_TAG_AUDIO_CODEC, "QCELP", NULL);
4548       break;
4549     }
4550     default:
4551       break;
4552   }
4553 }
4554
4555 #define _codec(name) \
4556   do { \
4557     if (codec_name) { \
4558       *codec_name = g_strdup (name); \
4559     } \
4560   } while (0)
4561
4562 static GstCaps *
4563 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
4564     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
4565 {
4566   GstCaps *caps;
4567   const GstStructure *s;
4568   const gchar *name;
4569
4570   switch (fourcc) {
4571     case GST_MAKE_FOURCC ('p', 'n', 'g', ' '):
4572       _codec ("PNG still images");
4573       caps = gst_caps_new_simple ("image/png", NULL);
4574       break;
4575     case GST_MAKE_FOURCC ('j', 'p', 'e', 'g'):
4576       _codec ("JPEG still images");
4577       caps = gst_caps_new_simple ("image/jpeg", NULL);
4578       break;
4579     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
4580     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
4581     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
4582       _codec ("Motion-JPEG");
4583       caps = gst_caps_new_simple ("image/jpeg", NULL);
4584       break;
4585     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
4586       _codec ("Motion-JPEG format B");
4587       caps = gst_caps_new_simple ("video/x-mjpeg-b", NULL);
4588       break;
4589     case GST_MAKE_FOURCC ('m', 'j', 'p', '2'):
4590       _codec ("JPEG-2000");
4591       /* override to what it should be according to spec, avoid palette_data */
4592       stream->bits_per_sample = 24;
4593       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
4594       break;
4595     case GST_MAKE_FOURCC ('S', 'V', 'Q', '3'):
4596       _codec ("Sorensen video v.3");
4597       caps = gst_caps_new_simple ("video/x-svq",
4598           "svqversion", G_TYPE_INT, 3, NULL);
4599       break;
4600     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
4601     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
4602       _codec ("Sorensen video v.1");
4603       caps = gst_caps_new_simple ("video/x-svq",
4604           "svqversion", G_TYPE_INT, 1, NULL);
4605       break;
4606     case GST_MAKE_FOURCC ('r', 'a', 'w', ' '):
4607     {
4608       guint16 bps;
4609
4610       _codec ("Raw RGB video");
4611       bps = QT_UINT16 (stsd_data + 98);
4612       /* set common stuff */
4613       caps = gst_caps_new_simple ("video/x-raw-rgb",
4614           "endianness", G_TYPE_INT, G_BYTE_ORDER, "depth", G_TYPE_INT, bps,
4615           NULL);
4616
4617       switch (bps) {
4618         case 15:
4619           gst_caps_set_simple (caps,
4620               "bpp", G_TYPE_INT, 16,
4621               "endianness", G_TYPE_INT, G_BIG_ENDIAN,
4622               "red_mask", G_TYPE_INT, 0x7c00,
4623               "green_mask", G_TYPE_INT, 0x03e0,
4624               "blue_mask", G_TYPE_INT, 0x001f, NULL);
4625           break;
4626         case 16:
4627           gst_caps_set_simple (caps,
4628               "bpp", G_TYPE_INT, 16,
4629               "endianness", G_TYPE_INT, G_BIG_ENDIAN,
4630               "red_mask", G_TYPE_INT, 0xf800,
4631               "green_mask", G_TYPE_INT, 0x07e0,
4632               "blue_mask", G_TYPE_INT, 0x001f, NULL);
4633           break;
4634         case 24:
4635           gst_caps_set_simple (caps,
4636               "bpp", G_TYPE_INT, 24,
4637               "endianness", G_TYPE_INT, G_BIG_ENDIAN,
4638               "red_mask", G_TYPE_INT, 0xff0000,
4639               "green_mask", G_TYPE_INT, 0x00ff00,
4640               "blue_mask", G_TYPE_INT, 0x0000ff, NULL);
4641           break;
4642         case 32:
4643           gst_caps_set_simple (caps,
4644               "bpp", G_TYPE_INT, 32,
4645               "endianness", G_TYPE_INT, G_BIG_ENDIAN,
4646               "alpha_mask", G_TYPE_INT, 0xff000000,
4647               "red_mask", G_TYPE_INT, 0x00ff0000,
4648               "green_mask", G_TYPE_INT, 0x0000ff00,
4649               "blue_mask", G_TYPE_INT, 0x000000ff, NULL);
4650           break;
4651         default:
4652           /* unknown */
4653           break;
4654       }
4655       break;
4656     }
4657     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
4658       _codec ("Raw planar YUV 4:2:0");
4659       caps = gst_caps_new_simple ("video/x-raw-yuv",
4660           "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
4661           NULL);
4662       break;
4663     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
4664     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
4665       _codec ("Raw packed YUV 4:2:2");
4666       caps = gst_caps_new_simple ("video/x-raw-yuv",
4667           "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'),
4668           NULL);
4669       break;
4670     case GST_MAKE_FOURCC ('2', 'v', 'u', 'y'):
4671       _codec ("Raw packed YUV 4:2:0");
4672       caps = gst_caps_new_simple ("video/x-raw-yuv",
4673           "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'),
4674           NULL);
4675       break;
4676     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
4677     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
4678       _codec ("MPEG-1 video");
4679       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
4680           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
4681       break;
4682     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): // HDV 720p30
4683     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): // HDV 1080i60
4684     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): // HDV 1080i50
4685     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): // HDV 720p25
4686     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): // HDV 1080i60
4687     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): // MPEG2 IMX NTSC 525/60 50mb/s produced by FCP
4688     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): // MPEG2 IMX PAL 625/60 50mb/s produced by FCP
4689     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): // MPEG2 IMX NTSC 525/60 40mb/s produced by FCP
4690     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): // MPEG2 IMX PAL 625/60 40mb/s produced by FCP
4691     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): // MPEG2 IMX NTSC 525/60 30mb/s produced by FCP
4692     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): // MPEG2 IMX PAL 625/50 30mb/s produced by FCP
4693     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): // XDCAM HD 1080i60
4694     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): // AVID IMX PAL
4695     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): // AVID IMX PAL
4696       _codec ("MPEG-2 video");
4697       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
4698           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
4699       break;
4700     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
4701       _codec ("GIF still images");
4702       caps = gst_caps_new_simple ("image/gif", NULL);
4703       break;
4704     case GST_MAKE_FOURCC ('h', '2', '6', '3'):
4705     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
4706     case GST_MAKE_FOURCC ('s', '2', '6', '3'):
4707     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
4708       _codec ("H.263");
4709       /* ffmpeg uses the height/width props, don't know why */
4710       caps = gst_caps_new_simple ("video/x-h263", NULL);
4711       break;
4712     case GST_MAKE_FOURCC ('m', 'p', '4', 'v'):
4713       _codec ("MPEG-4 video");
4714       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
4715           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
4716       break;
4717     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
4718     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
4719       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
4720       caps = gst_caps_new_simple ("video/x-msmpeg",
4721           "msmpegversion", G_TYPE_INT, 43, NULL);
4722       break;
4723     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
4724     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
4725       _codec ("3ivX video");
4726       caps = gst_caps_new_simple ("video/x-3ivx", NULL);
4727       break;
4728     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
4729       _codec ("DivX 3");
4730       caps = gst_caps_new_simple ("video/x-divx",
4731           "divxversion", G_TYPE_INT, 3, NULL);
4732       break;
4733     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
4734     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
4735       _codec ("DivX 4");
4736       caps = gst_caps_new_simple ("video/x-divx",
4737           "divxversion", G_TYPE_INT, 4, NULL);
4738       break;
4739     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
4740       _codec ("DivX 5");
4741       caps = gst_caps_new_simple ("video/x-divx",
4742           "divxversion", G_TYPE_INT, 5, NULL);
4743       break;
4744     case GST_MAKE_FOURCC ('X', 'V', 'I', 'D'):
4745     case GST_MAKE_FOURCC ('x', 'v', 'i', 'd'):
4746       _codec ("XVID MPEG-4");
4747       caps = gst_caps_new_simple ("video/x-xvid", NULL);
4748       break;
4749
4750     case GST_MAKE_FOURCC ('F', 'M', 'P', '4'):
4751     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
4752       caps = gst_caps_new_simple ("video/mpeg",
4753           "mpegversion", G_TYPE_INT, 4, NULL);
4754       if (codec_name)
4755         *codec_name = g_strdup ("FFmpeg MPEG-4");
4756       break;
4757
4758     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
4759       _codec ("Cinepak");
4760       caps = gst_caps_new_simple ("video/x-cinepak", NULL);
4761       break;
4762     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
4763       _codec ("Apple QuickDraw");
4764       caps = gst_caps_new_simple ("video/x-qdrw", NULL);
4765       break;
4766     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
4767       _codec ("Apple video");
4768       caps = gst_caps_new_simple ("video/x-apple-video", NULL);
4769       break;
4770     case GST_MAKE_FOURCC ('a', 'v', 'c', '1'):
4771       _codec ("H.264 / AVC");
4772       caps = gst_caps_new_simple ("video/x-h264", NULL);
4773       break;
4774     case GST_MAKE_FOURCC ('r', 'l', 'e', ' '):
4775       _codec ("Run-length encoding");
4776       caps = gst_caps_new_simple ("video/x-rle",
4777           "layout", G_TYPE_STRING, "quicktime", NULL);
4778       break;
4779     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
4780       _codec ("Indeo Video 3");
4781       caps = gst_caps_new_simple ("video/x-indeo",
4782           "indeoversion", G_TYPE_INT, 3, NULL);
4783       break;
4784     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
4785     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
4786       _codec ("Intel Video 4");
4787       caps = gst_caps_new_simple ("video/x-indeo",
4788           "indeoversion", G_TYPE_INT, 4, NULL);
4789       break;
4790     case GST_MAKE_FOURCC ('d', 'v', 'c', 'p'):
4791     case GST_MAKE_FOURCC ('d', 'v', 'c', ' '):
4792     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
4793     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
4794     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
4795     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
4796     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
4797     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
4798       _codec ("DV Video");
4799       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
4800           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
4801       break;
4802     case GST_MAKE_FOURCC ('d', 'v', '5', 'n'): //DVCPRO50 NTSC
4803     case GST_MAKE_FOURCC ('d', 'v', '5', 'p'): //DVCPRO50 PAL
4804       _codec ("DVCPro50 Video");
4805       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
4806           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
4807       break;
4808     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): //DVCPRO HD 50i produced by FCP
4809     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): //DVCPRO HD 60i produced by FCP
4810       _codec ("DVCProHD Video");
4811       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
4812           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
4813       break;
4814     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
4815       _codec ("Apple Graphics (SMC)");
4816       caps = gst_caps_new_simple ("video/x-smc", NULL);
4817       break;
4818     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
4819       _codec ("VP3");
4820       caps = gst_caps_new_simple ("video/x-vp3", NULL);
4821       break;
4822     case GST_MAKE_FOURCC ('X', 'i', 'T', 'h'):
4823       _codec ("Theora");
4824       caps = gst_caps_new_simple ("video/x-theora", NULL);
4825       /* theora uses one byte of padding in the data stream because it does not
4826        * allow 0 sized packets while theora does */
4827       stream->padding = 1;
4828       break;
4829     case GST_MAKE_FOURCC ('d', 'r', 'a', 'c'):
4830       _codec ("Dirac");
4831       caps = gst_caps_new_simple ("video/x-dirac", NULL);
4832       break;
4833     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
4834       _codec ("TIFF still images");
4835       caps = gst_caps_new_simple ("image/tiff", NULL);
4836       break;
4837     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
4838     default:
4839     {
4840       char *s;
4841
4842       s = g_strdup_printf ("video/x-gst-fourcc-%" GST_FOURCC_FORMAT,
4843           GST_FOURCC_ARGS (fourcc));
4844       caps = gst_caps_new_simple (s, NULL);
4845       break;
4846     }
4847   }
4848
4849   /* enable clipping for raw video streams */
4850   s = gst_caps_get_structure (caps, 0);
4851   name = gst_structure_get_name (s);
4852   if (g_str_has_prefix (name, "video/x-raw-")) {
4853     stream->need_clip = TRUE;
4854   }
4855   return caps;
4856 }
4857
4858 static GstCaps *
4859 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
4860     guint32 fourcc, const guint8 * data, int len, gchar ** codec_name)
4861 {
4862   GstCaps *caps;
4863   const GstStructure *s;
4864   const gchar *name;
4865   gint endian = 0;
4866
4867   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc %08x", fourcc);
4868
4869   switch (fourcc) {
4870     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
4871     case GST_MAKE_FOURCC ('r', 'a', 'w', ' '):
4872       _codec ("Raw 8-bit PCM audio");
4873       caps = gst_caps_new_simple ("audio/x-raw-int", "width", G_TYPE_INT, 8,
4874           "depth", G_TYPE_INT, 8, "signed", G_TYPE_BOOLEAN, FALSE, NULL);
4875       break;
4876     case GST_MAKE_FOURCC ('t', 'w', 'o', 's'):
4877       endian = G_BIG_ENDIAN;
4878       /* fall-through */
4879     case GST_MAKE_FOURCC ('s', 'o', 'w', 't'):
4880     {
4881       gchar *str;
4882       gint depth;
4883
4884       if (!endian)
4885         endian = G_LITTLE_ENDIAN;
4886
4887       depth = stream->bytes_per_packet * 8;
4888       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
4889       _codec (str);
4890       g_free (str);
4891       caps = gst_caps_new_simple ("audio/x-raw-int",
4892           "width", G_TYPE_INT, depth, "depth", G_TYPE_INT, depth,
4893           "endianness", G_TYPE_INT, endian,
4894           "signed", G_TYPE_BOOLEAN, TRUE, NULL);
4895       break;
4896     }
4897     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
4898       _codec ("Raw 64-bit floating-point audio");
4899       caps = gst_caps_new_simple ("audio/x-raw-float", "width", G_TYPE_INT, 64,
4900           "endianness", G_TYPE_INT, G_BIG_ENDIAN, NULL);
4901       break;
4902     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
4903       _codec ("Raw 32-bit floating-point audio");
4904       caps = gst_caps_new_simple ("audio/x-raw-float", "width", G_TYPE_INT, 32,
4905           "endianness", G_TYPE_INT, G_BIG_ENDIAN, NULL);
4906       break;
4907     case GST_MAKE_FOURCC ('i', 'n', '2', '4'):
4908       _codec ("Raw 24-bit PCM audio");
4909       caps = gst_caps_new_simple ("audio/x-raw-int", "width", G_TYPE_INT, 24,
4910           "depth", G_TYPE_INT, 24,
4911           "endianness", G_TYPE_INT, G_BIG_ENDIAN,
4912           "signed", G_TYPE_BOOLEAN, TRUE, NULL);
4913       break;
4914     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
4915       _codec ("Raw 32-bit PCM audio");
4916       caps = gst_caps_new_simple ("audio/x-raw-int", "width", G_TYPE_INT, 32,
4917           "depth", G_TYPE_INT, 32,
4918           "endianness", G_TYPE_INT, G_BIG_ENDIAN,
4919           "signed", G_TYPE_BOOLEAN, TRUE, NULL);
4920       break;
4921     case GST_MAKE_FOURCC ('u', 'l', 'a', 'w'):
4922       _codec ("Mu-law audio");
4923       caps = gst_caps_new_simple ("audio/x-mulaw", NULL);
4924       break;
4925     case GST_MAKE_FOURCC ('a', 'l', 'a', 'w'):
4926       _codec ("A-law audio");
4927       caps = gst_caps_new_simple ("audio/x-alaw", NULL);
4928       break;
4929     case 0x0200736d:
4930     case 0x6d730002:
4931       _codec ("Microsoft ADPCM");
4932       /* Microsoft ADPCM-ACM code 2 */
4933       caps = gst_caps_new_simple ("audio/x-adpcm",
4934           "layout", G_TYPE_STRING, "microsoft", NULL);
4935       break;
4936     case 0x1100736d:
4937     case 0x6d730011:
4938       _codec ("IMA Loki SDL MJPEG ADPCM");
4939       /* Loki ADPCM, See #550288 for a file that only decodes
4940        * with the smjpeg variant of the ADPCM decoder. */
4941       caps = gst_caps_new_simple ("audio/x-adpcm",
4942           "layout", G_TYPE_STRING, "smjpeg", NULL);
4943       break;
4944     case 0x1700736d:
4945     case 0x6d730017:
4946       _codec ("DVI/Intel IMA ADPCM");
4947       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
4948       caps = gst_caps_new_simple ("audio/x-adpcm",
4949           "layout", G_TYPE_STRING, "quicktime", NULL);
4950       break;
4951     case 0x5500736d:
4952     case 0x6d730055:
4953       /* MPEG layer 3, CBR only (pre QT4.1) */
4954     case GST_MAKE_FOURCC ('.', 'm', 'p', '3'):
4955       _codec ("MPEG-1 layer 3");
4956       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
4957       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
4958           "mpegversion", G_TYPE_INT, 1, NULL);
4959       break;
4960     case 0x20736d:
4961       _codec ("AC-3 audio");
4962       caps = gst_caps_new_simple ("audio/x-ac3", NULL);
4963       break;
4964     case GST_MAKE_FOURCC ('M', 'A', 'C', '3'):
4965       _codec ("MACE-3");
4966       caps = gst_caps_new_simple ("audio/x-mace",
4967           "maceversion", G_TYPE_INT, 3, NULL);
4968       break;
4969     case GST_MAKE_FOURCC ('M', 'A', 'C', '6'):
4970       _codec ("MACE-6");
4971       caps = gst_caps_new_simple ("audio/x-mace",
4972           "maceversion", G_TYPE_INT, 6, NULL);
4973       break;
4974     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
4975       /* ogg/vorbis */
4976       caps = gst_caps_new_simple ("application/ogg", NULL);
4977       break;
4978     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
4979       _codec ("DV audio");
4980       caps = gst_caps_new_simple ("audio/x-dv", NULL);
4981       break;
4982     case GST_MAKE_FOURCC ('m', 'p', '4', 'a'):
4983       _codec ("MPEG-4 AAC audio");
4984       caps = gst_caps_new_simple ("audio/mpeg",
4985           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE, NULL);
4986       break;
4987     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
4988       _codec ("QDesign Music");
4989       caps = gst_caps_new_simple ("audio/x-qdm", NULL);
4990       break;
4991     case GST_MAKE_FOURCC ('Q', 'D', 'M', '2'):
4992       _codec ("QDesign Music v.2");
4993       /* FIXME: QDesign music version 2 (no constant) */
4994       if (data) {
4995         caps = gst_caps_new_simple ("audio/x-qdm2",
4996             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
4997             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
4998             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
4999       } else {
5000         caps = gst_caps_new_simple ("audio/x-qdm2", NULL);
5001       }
5002       break;
5003     case GST_MAKE_FOURCC ('a', 'g', 's', 'm'):
5004       _codec ("GSM audio");
5005       caps = gst_caps_new_simple ("audio/x-gsm", NULL);
5006       break;
5007     case GST_MAKE_FOURCC ('s', 'a', 'm', 'r'):
5008       _codec ("AMR audio");
5009       caps = gst_caps_new_simple ("audio/AMR", NULL);
5010       break;
5011     case GST_MAKE_FOURCC ('s', 'a', 'w', 'b'):
5012       _codec ("AMR-WB audio");
5013       caps = gst_caps_new_simple ("audio/AMR-WB", NULL);
5014       break;
5015     case GST_MAKE_FOURCC ('i', 'm', 'a', '4'):
5016       _codec ("Quicktime IMA ADPCM");
5017       caps = gst_caps_new_simple ("audio/x-adpcm",
5018           "layout", G_TYPE_STRING, "quicktime", NULL);
5019       break;
5020     case GST_MAKE_FOURCC ('a', 'l', 'a', 'c'):
5021       _codec ("Apple lossless audio");
5022       caps = gst_caps_new_simple ("audio/x-alac", NULL);
5023       break;
5024     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
5025       /* ? */
5026     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
5027       /* QUALCOMM PureVoice */
5028     default:
5029     {
5030       char *s;
5031
5032       s = g_strdup_printf ("audio/x-gst-fourcc-%" GST_FOURCC_FORMAT,
5033           GST_FOURCC_ARGS (fourcc));
5034       caps = gst_caps_new_simple (s, NULL);
5035       break;
5036     }
5037   }
5038
5039   /* enable clipping for raw audio streams */
5040   s = gst_caps_get_structure (caps, 0);
5041   name = gst_structure_get_name (s);
5042   if (g_str_has_prefix (name, "audio/x-raw-")) {
5043     stream->need_clip = TRUE;
5044   }
5045   return caps;
5046 }