qtdemux: use G_GSIZE_FORMAT for platform independent gsize qualifier
[platform/upstream/gst-plugins-good.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  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public
20  * License along with this library; if not, write to the
21  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22  * Boston, MA 02111-1307, USA.
23  */
24
25 /**
26  * SECTION:element-qtdemux
27  *
28  * Demuxes a .mov file into raw or compressed audio and/or video streams.
29  *
30  * This element supports both push and pull-based scheduling, depending on the
31  * capabilities of the upstream elements.
32  *
33  * <refsect2>
34  * <title>Example launch line</title>
35  * |[
36  * gst-launch filesrc location=test.mov ! qtdemux name=demux  demux.audio_00 ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_00 ! queue ! decodebin ! ffmpegcolorspace ! videoscale ! autovideosink
37  * ]| Play (parse and decode) a .mov file and try to output it to
38  * an automatically detected soundcard and videosink. If the MOV file contains
39  * compressed audio or video data, this will only work if you have the
40  * right decoder elements/plugins installed.
41  * </refsect2>
42  *
43  * Last reviewed on 2006-12-29 (0.10.5)
44  */
45
46 #ifdef HAVE_CONFIG_H
47 #include "config.h"
48 #endif
49
50 #include "gst/gst-i18n-plugin.h"
51
52 #include <gst/tag/tag.h>
53
54 #include "qtatomparser.h"
55 #include "qtdemux_types.h"
56 #include "qtdemux_dump.h"
57 #include "qtdemux_fourcc.h"
58 #include "qtdemux.h"
59 #include "qtpalette.h"
60
61 #include "gst/riff/riff-media.h"
62 #include "gst/riff/riff-read.h"
63
64 #include <stdio.h>
65 #include <stdlib.h>
66 #include <string.h>
67
68 #ifdef HAVE_ZLIB
69 # include <zlib.h>
70 #endif
71
72 /* max. size considered 'sane' for non-mdat atoms */
73 #define QTDEMUX_MAX_ATOM_SIZE (25*1024*1024)
74
75 /* if the sample index is larger than this, something is likely wrong */
76 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (50*1024*1024)
77
78 GST_DEBUG_CATEGORY (qtdemux_debug);
79
80 /*typedef struct _QtNode QtNode; */
81 typedef struct _QtDemuxSegment QtDemuxSegment;
82 typedef struct _QtDemuxSample QtDemuxSample;
83
84 /*struct _QtNode
85 {
86   guint32 type;
87   guint8 *data;
88   gint len;
89 };*/
90
91 struct _QtDemuxSample
92 {
93   guint32 size;
94   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
95   guint64 offset;
96   guint64 timestamp;            /* DTS In mov time */
97   guint32 duration;             /* In mov time */
98   gboolean keyframe;            /* TRUE when this packet is a keyframe */
99 };
100
101 /* timestamp is the DTS */
102 #define QTSAMPLE_DTS(stream,sample) gst_util_uint64_scale ((sample)->timestamp,\
103     GST_SECOND, (stream)->timescale)
104 /* timestamp + offset is the PTS */
105 #define QTSAMPLE_PTS(stream,sample) gst_util_uint64_scale ((sample)->timestamp + \
106     (sample)->pts_offset, GST_SECOND, (stream)->timescale)
107 /* timestamp + duration - dts is the duration */
108 #define QTSAMPLE_DUR_DTS(stream,sample,dts) (gst_util_uint64_scale ((sample)->timestamp + \
109     (sample)->duration, GST_SECOND, (stream)->timescale) - (dts));
110 /* timestamp + offset + duration - pts is the duration */
111 #define QTSAMPLE_DUR_PTS(stream,sample,pts) (gst_util_uint64_scale ((sample)->timestamp + \
112     (sample)->pts_offset + (sample)->duration, GST_SECOND, (stream)->timescale) - (pts));
113
114 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
115
116 /*
117  * Quicktime has tracks and segments. A track is a continuous piece of
118  * multimedia content. The track is not always played from start to finish but
119  * instead, pieces of the track are 'cut out' and played in sequence. This is
120  * what the segments do.
121  *
122  * Inside the track we have keyframes (K) and delta frames. The track has its
123  * own timing, which starts from 0 and extends to end. The position in the track
124  * is called the media_time.
125  *
126  * The segments now describe the pieces that should be played from this track
127  * and are basically tupples of media_time/duration/rate entries. We can have
128  * multiple segments and they are all played after one another. An example:
129  *
130  * segment 1: media_time: 1 second, duration: 1 second, rate 1
131  * segment 2: media_time: 3 second, duration: 2 second, rate 2
132  *
133  * To correctly play back this track, one must play: 1 second of media starting
134  * from media_time 1 followed by 2 seconds of media starting from media_time 3
135  * at a rate of 2.
136  *
137  * Each of the segments will be played at a specific time, the first segment at
138  * time 0, the second one after the duration of the first one, etc.. Note that
139  * the time in resulting playback is not identical to the media_time of the
140  * track anymore.
141  *
142  * Visually, assuming the track has 4 second of media_time:
143  *
144  *                (a)                   (b)          (c)              (d)
145  *         .-----------------------------------------------------------.
146  * track:  | K.....K.........K........K.......K.......K...........K... |
147  *         '-----------------------------------------------------------'
148  *         0              1              2              3              4    
149  *           .------------^              ^   .----------^              ^
150  *          /              .-------------'  /       .------------------'
151  *         /              /          .-----'       /
152  *         .--------------.         .--------------.
153  *         | segment 1    |         | segment 2    |
154  *         '--------------'         '--------------'
155  *       
156  * The challenge here is to cut out the right pieces of the track for each of
157  * the playback segments. This fortunatly can easily be done with the SEGMENT
158  * events of gstreamer.
159  *
160  * For playback of segment 1, we need to provide the decoder with the keyframe
161  * (a), in the above figure, but we must instruct it only to output the decoded
162  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
163  * position set to the time of the segment: 0.
164  *
165  * We then proceed to push data from keyframe (a) to frame (b). The decoder
166  * decodes but clips all before media_time 1.
167  * 
168  * After finishing a segment, we push out a new SEGMENT event with the clipping
169  * boundaries of the new data.
170  *
171  * This is a good usecase for the GStreamer accumulated SEGMENT events.
172  */
173
174 struct _QtDemuxSegment
175 {
176   /* global time and duration, all gst time */
177   guint64 time;
178   guint64 stop_time;
179   guint64 duration;
180   /* media time of trak, all gst time */
181   guint64 media_start;
182   guint64 media_stop;
183   gdouble rate;
184 };
185
186 struct _QtDemuxStream
187 {
188   GstPad *pad;
189
190   /* stream type */
191   guint32 subtype;
192   GstCaps *caps;
193   guint32 fourcc;
194
195   /* duration/scale */
196   guint64 duration;             /* in timescale */
197   guint32 timescale;
198
199   /* language */
200   guint lang_code;
201   gchar lang_id[4];             /* in ISO 639-2 */
202
203   /* our samples */
204   guint32 n_samples;
205   QtDemuxSample *samples;
206   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
207   guint32 min_duration;         /* duration in timescale of first sample, used for figuring out
208                                    the framerate, in timescale units */
209
210   /* if we use chunks or samples */
211   gboolean sampled;
212   guint padding;
213
214   /* video info */
215   gint width;
216   gint height;
217   /* aspect ratio */
218   gint display_width;
219   gint display_height;
220   gint par_w;
221   gint par_h;
222   /* Numerator/denominator framerate */
223   gint fps_n;
224   gint fps_d;
225   guint16 bits_per_sample;
226   guint16 color_table_id;
227
228   /* audio info */
229   gdouble rate;
230   gint n_channels;
231   guint samples_per_packet;
232   guint samples_per_frame;
233   guint bytes_per_packet;
234   guint bytes_per_sample;
235   guint bytes_per_frame;
236   guint compression;
237
238   /* when a discontinuity is pending */
239   gboolean discont;
240
241   /* list of buffers to push first */
242   GSList *buffers;
243
244   /* if we need to clip this buffer. This is only needed for uncompressed
245    * data */
246   gboolean need_clip;
247
248   /* buffer needs some custom processing, e.g. subtitles */
249   gboolean need_process;
250
251   /* current position */
252   guint32 segment_index;
253   guint32 sample_index;
254   guint64 time_position;        /* in gst time */
255
256   /* the Gst segment we are processing out, used for clipping */
257   GstSegment segment;
258
259   /* last GstFlowReturn */
260   GstFlowReturn last_ret;
261
262   /* quicktime segments */
263   guint32 n_segments;
264   QtDemuxSegment *segments;
265   guint32 from_sample;
266   guint32 to_sample;
267
268   gboolean sent_eos;
269   GstTagList *pending_tags;
270   gboolean send_global_tags;
271
272   GstEvent *pending_event;
273
274   GstByteReader stco;
275   GstByteReader stsz;
276   GstByteReader stsc;
277   GstByteReader stts;
278   GstByteReader stss;
279   GstByteReader stps;
280   GstByteReader ctts;
281
282   gboolean chunks_are_chunks;
283   gint64 stbl_index;
284   /* stco */
285   guint co_size;
286   GstByteReader co_chunk;
287   guint32 first_chunk;
288   guint32 current_chunk;
289   guint32 last_chunk;
290   guint32 samples_per_chunk;
291   guint32 stco_sample_index;
292   /* stsz */
293   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
294   /* stsc */
295   guint32 stsc_index;
296   guint32 n_samples_per_chunk;
297   guint32 stsc_chunk_index;
298   guint32 stsc_sample_index;
299   guint64 chunk_offset;
300   /* stts */
301   guint32 stts_index;
302   guint32 stts_samples;
303   guint32 n_sample_times;
304   guint32 stts_sample_index;
305   guint64 stts_time;
306   guint64 stts_duration;
307   /* stss */
308   gboolean stss_present;
309   guint32 n_sample_syncs;
310   guint32 stss_index;
311   /* stps */
312   gboolean stps_present;
313   guint32 n_sample_partial_syncs;
314   guint32 stps_index;
315   /* ctts */
316   gboolean ctts_present;
317   guint32 n_composition_times;
318   guint32 ctts_index;
319   guint32 ctts_sample_index;
320   guint32 ctts_count;
321   gint32 ctts_soffset;
322 };
323
324 enum QtDemuxState
325 {
326   QTDEMUX_STATE_INITIAL,        /* Initial state (haven't got the header yet) */
327   QTDEMUX_STATE_HEADER,         /* Parsing the header */
328   QTDEMUX_STATE_MOVIE,          /* Parsing/Playing the media data */
329   QTDEMUX_STATE_BUFFER_MDAT     /* Buffering the mdat atom */
330 };
331
332 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
333 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
334     guint32 fourcc, GstByteReader * parser);
335 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
336
337 static const GstElementDetails gst_qtdemux_details =
338 GST_ELEMENT_DETAILS ("QuickTime demuxer",
339     "Codec/Demuxer",
340     "Demultiplex a QuickTime file into audio and video streams",
341     "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
342
343 static GstStaticPadTemplate gst_qtdemux_sink_template =
344     GST_STATIC_PAD_TEMPLATE ("sink",
345     GST_PAD_SINK,
346     GST_PAD_ALWAYS,
347     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
348         "application/x-3gp")
349     );
350
351 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
352 GST_STATIC_PAD_TEMPLATE ("video_%02d",
353     GST_PAD_SRC,
354     GST_PAD_SOMETIMES,
355     GST_STATIC_CAPS_ANY);
356
357 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
358 GST_STATIC_PAD_TEMPLATE ("audio_%02d",
359     GST_PAD_SRC,
360     GST_PAD_SOMETIMES,
361     GST_STATIC_CAPS_ANY);
362
363 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
364 GST_STATIC_PAD_TEMPLATE ("subtitle_%02d",
365     GST_PAD_SRC,
366     GST_PAD_SOMETIMES,
367     GST_STATIC_CAPS_ANY);
368
369 static GstElementClass *parent_class = NULL;
370
371 static void gst_qtdemux_class_init (GstQTDemuxClass * klass);
372 static void gst_qtdemux_base_init (GstQTDemuxClass * klass);
373 static void gst_qtdemux_init (GstQTDemux * quicktime_demux);
374 static void gst_qtdemux_dispose (GObject * object);
375
376 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
377 static GstIndex *gst_qtdemux_get_index (GstElement * element);
378 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
379     GstStateChange transition);
380 static gboolean qtdemux_sink_activate (GstPad * sinkpad);
381 static gboolean qtdemux_sink_activate_pull (GstPad * sinkpad, gboolean active);
382 static gboolean qtdemux_sink_activate_push (GstPad * sinkpad, gboolean active);
383
384 static void gst_qtdemux_loop (GstPad * pad);
385 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf);
386 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstEvent * event);
387
388 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer,
389     guint length);
390 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
391     const guint8 * buffer, guint length);
392 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
393
394 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
395     QtDemuxStream * stream, GNode * esds, GstTagList * list);
396 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
397     QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
398     gchar ** codec_name);
399 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
400     QtDemuxStream * stream, guint32 fourcc, const guint8 * data, int len,
401     gchar ** codec_name);
402 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux,
403     QtDemuxStream * stream, guint32 fourcc, const guint8 * data,
404     gchar ** codec_name);
405 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
406     QtDemuxStream * stream, guint32 n);
407
408 GType
409 gst_qtdemux_get_type (void)
410 {
411   static GType qtdemux_type = 0;
412
413   if (G_UNLIKELY (!qtdemux_type)) {
414     static const GTypeInfo qtdemux_info = {
415       sizeof (GstQTDemuxClass),
416       (GBaseInitFunc) gst_qtdemux_base_init, NULL,
417       (GClassInitFunc) gst_qtdemux_class_init,
418       NULL, NULL, sizeof (GstQTDemux), 0,
419       (GInstanceInitFunc) gst_qtdemux_init,
420     };
421
422     qtdemux_type =
423         g_type_register_static (GST_TYPE_ELEMENT, "GstQTDemux", &qtdemux_info,
424         0);
425   }
426   return qtdemux_type;
427 }
428
429 static void
430 gst_qtdemux_base_init (GstQTDemuxClass * klass)
431 {
432   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
433
434   gst_element_class_add_pad_template (element_class,
435       gst_static_pad_template_get (&gst_qtdemux_sink_template));
436   gst_element_class_add_pad_template (element_class,
437       gst_static_pad_template_get (&gst_qtdemux_videosrc_template));
438   gst_element_class_add_pad_template (element_class,
439       gst_static_pad_template_get (&gst_qtdemux_audiosrc_template));
440   gst_element_class_add_pad_template (element_class,
441       gst_static_pad_template_get (&gst_qtdemux_subsrc_template));
442   gst_element_class_set_details (element_class, &gst_qtdemux_details);
443
444   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
445 }
446
447 static void
448 gst_qtdemux_class_init (GstQTDemuxClass * klass)
449 {
450   GObjectClass *gobject_class;
451   GstElementClass *gstelement_class;
452
453   gobject_class = (GObjectClass *) klass;
454   gstelement_class = (GstElementClass *) klass;
455
456   parent_class = g_type_class_peek_parent (klass);
457
458   gobject_class->dispose = gst_qtdemux_dispose;
459
460   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
461
462   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
463   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
464 }
465
466 static void
467 gst_qtdemux_init (GstQTDemux * qtdemux)
468 {
469   qtdemux->sinkpad =
470       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
471   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
472   gst_pad_set_activatepull_function (qtdemux->sinkpad,
473       qtdemux_sink_activate_pull);
474   gst_pad_set_activatepush_function (qtdemux->sinkpad,
475       qtdemux_sink_activate_push);
476   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
477   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
478   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
479
480   qtdemux->state = QTDEMUX_STATE_INITIAL;
481   qtdemux->pullbased = FALSE;
482   qtdemux->neededbytes = 16;
483   qtdemux->todrop = 0;
484   qtdemux->adapter = gst_adapter_new ();
485   qtdemux->offset = 0;
486   qtdemux->first_mdat = -1;
487   qtdemux->mdatoffset = GST_CLOCK_TIME_NONE;
488   qtdemux->mdatbuffer = NULL;
489   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
490 }
491
492 static void
493 gst_qtdemux_dispose (GObject * object)
494 {
495   GstQTDemux *qtdemux = GST_QTDEMUX (object);
496
497   if (qtdemux->adapter) {
498     g_object_unref (G_OBJECT (qtdemux->adapter));
499     qtdemux->adapter = NULL;
500   }
501
502   G_OBJECT_CLASS (parent_class)->dispose (object);
503 }
504
505 static GstFlowReturn
506 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
507     GstBuffer ** buf)
508 {
509   GstFlowReturn flow;
510
511   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
512   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
513     GST_ELEMENT_ERROR (qtdemux, STREAM, DECODE,
514         (_("This file is invalid and cannot be played.")),
515         ("atom has bogus size %" G_GUINT64_FORMAT, size));
516     return GST_FLOW_ERROR;
517   }
518
519   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
520
521   if (G_UNLIKELY (flow != GST_FLOW_OK))
522     return flow;
523
524   /* Catch short reads - we don't want any partial atoms */
525   if (G_UNLIKELY (GST_BUFFER_SIZE (*buf) < size)) {
526     GST_WARNING_OBJECT (qtdemux, "short read: %u < %" G_GUINT64_FORMAT,
527         GST_BUFFER_SIZE (*buf), size);
528     gst_buffer_unref (*buf);
529     *buf = NULL;
530     return GST_FLOW_UNEXPECTED;
531   }
532
533   return flow;
534 }
535
536 #if 0
537 static gboolean
538 gst_qtdemux_src_convert (GstPad * pad, GstFormat src_format, gint64 src_value,
539     GstFormat * dest_format, gint64 * dest_value)
540 {
541   gboolean res = TRUE;
542   QtDemuxStream *stream = gst_pad_get_element_private (pad);
543
544   if (stream->subtype == GST_MAKE_FOURCC ('v', 'i', 'd', 'e') &&
545       (src_format == GST_FORMAT_BYTES || *dest_format == GST_FORMAT_BYTES))
546     return FALSE;
547
548   switch (src_format) {
549     case GST_FORMAT_TIME:
550       switch (*dest_format) {
551         case GST_FORMAT_BYTES:
552           *dest_value = src_value * 1;  /* FIXME */
553           break;
554         case GST_FORMAT_DEFAULT:
555           *dest_value = src_value * 1;  /* FIXME */
556           break;
557         default:
558           res = FALSE;
559           break;
560       }
561       break;
562     case GST_FORMAT_BYTES:
563       switch (*dest_format) {
564         case GST_FORMAT_TIME:
565           *dest_value = src_value * 1;  /* FIXME */
566           break;
567         default:
568           res = FALSE;
569           break;
570       }
571       break;
572     case GST_FORMAT_DEFAULT:
573       switch (*dest_format) {
574         case GST_FORMAT_TIME:
575           *dest_value = src_value * 1;  /* FIXME */
576           break;
577         default:
578           res = FALSE;
579           break;
580       }
581       break;
582     default:
583       res = FALSE;
584   }
585
586   return res;
587 }
588 #endif
589
590 static const GstQueryType *
591 gst_qtdemux_get_src_query_types (GstPad * pad)
592 {
593   static const GstQueryType src_types[] = {
594     GST_QUERY_POSITION,
595     GST_QUERY_DURATION,
596     GST_QUERY_SEEKING,
597     0
598   };
599
600   return src_types;
601 }
602
603 static gboolean
604 gst_qtdemux_get_duration (GstQTDemux * qtdemux, gint64 * duration)
605 {
606   gboolean res = TRUE;
607
608   *duration = GST_CLOCK_TIME_NONE;
609
610   if (qtdemux->duration != 0) {
611     if (qtdemux->duration != G_MAXINT32 && qtdemux->timescale != 0) {
612       *duration = gst_util_uint64_scale (qtdemux->duration,
613           GST_SECOND, qtdemux->timescale);
614     }
615   }
616   return res;
617 }
618
619 static gboolean
620 gst_qtdemux_handle_src_query (GstPad * pad, GstQuery * query)
621 {
622   gboolean res = FALSE;
623   GstQTDemux *qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
624
625   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
626
627   switch (GST_QUERY_TYPE (query)) {
628     case GST_QUERY_POSITION:
629       if (GST_CLOCK_TIME_IS_VALID (qtdemux->segment.last_stop)) {
630         gst_query_set_position (query, GST_FORMAT_TIME,
631             qtdemux->segment.last_stop);
632         res = TRUE;
633       }
634       break;
635     case GST_QUERY_DURATION:{
636       GstFormat fmt;
637
638       gst_query_parse_duration (query, &fmt, NULL);
639       if (fmt == GST_FORMAT_TIME) {
640         gint64 duration = -1;
641
642         gst_qtdemux_get_duration (qtdemux, &duration);
643         if (duration > 0) {
644           gst_query_set_duration (query, GST_FORMAT_TIME, duration);
645           res = TRUE;
646         }
647       }
648       break;
649     }
650     case GST_QUERY_SEEKING:{
651       GstFormat fmt;
652       gboolean seekable;
653
654       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
655       if (fmt == GST_FORMAT_TIME) {
656         gint64 duration = -1;
657
658         gst_qtdemux_get_duration (qtdemux, &duration);
659         seekable = TRUE;
660         if (!qtdemux->pullbased) {
661           GstQuery *q;
662
663           /* we might be able with help from upstream */
664           seekable = FALSE;
665           q = gst_query_new_seeking (GST_FORMAT_BYTES);
666           if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
667             gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
668             GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
669           }
670           gst_query_unref (q);
671         }
672         gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
673         res = TRUE;
674       }
675       break;
676     }
677     default:
678       res = gst_pad_query_default (pad, query);
679       break;
680   }
681
682   gst_object_unref (qtdemux);
683
684   return res;
685 }
686
687 static void
688 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
689 {
690   if (G_LIKELY (stream->pad)) {
691     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
692         GST_DEBUG_PAD_NAME (stream->pad));
693
694     if (G_UNLIKELY (stream->pending_tags)) {
695       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
696           stream->pending_tags);
697       gst_pad_push_event (stream->pad,
698           gst_event_new_tag (stream->pending_tags));
699       stream->pending_tags = NULL;
700     }
701
702     if (G_UNLIKELY (stream->send_global_tags && qtdemux->tag_list)) {
703       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
704           qtdemux->tag_list);
705       gst_pad_push_event (stream->pad,
706           gst_event_new_tag (gst_tag_list_copy (qtdemux->tag_list)));
707       stream->send_global_tags = FALSE;
708     }
709   }
710 }
711
712 /* push event on all source pads; takes ownership of the event */
713 static void
714 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
715 {
716   guint n;
717
718   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
719       GST_EVENT_TYPE_NAME (event));
720
721   for (n = 0; n < qtdemux->n_streams; n++) {
722     GstPad *pad;
723
724     if ((pad = qtdemux->streams[n]->pad))
725       gst_pad_push_event (pad, gst_event_ref (event));
726   }
727   gst_event_unref (event);
728 }
729
730 /* push a pending newsegment event, if any from the streaming thread */
731 static void
732 gst_qtdemux_push_pending_newsegment (GstQTDemux * qtdemux)
733 {
734   if (qtdemux->pending_newsegment) {
735     gst_qtdemux_push_event (qtdemux, qtdemux->pending_newsegment);
736     qtdemux->pending_newsegment = NULL;
737   }
738 }
739
740 typedef struct
741 {
742   guint64 media_time;
743 } FindData;
744
745 static gint
746 find_func (QtDemuxSample * s1, guint64 * media_time, gpointer user_data)
747 {
748   if (s1->timestamp > *media_time)
749     return 1;
750
751   return -1;
752 }
753
754 /* find the index of the sample that includes the data for @media_time using a
755  * binary search
756  *
757  * Returns the index of the sample.
758  */
759 static guint32
760 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
761     guint64 media_time)
762 {
763   QtDemuxSample *result;
764   guint32 index;
765
766   /* convert media_time to mov format */
767   media_time = gst_util_uint64_scale (media_time, str->timescale, GST_SECOND);
768
769   result = gst_util_array_binary_search (str->samples, str->n_samples,
770       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
771       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
772
773   if (G_LIKELY (result))
774     index = result - str->samples;
775   else
776     index = 0;
777
778   return index;
779 }
780
781 /* find the index of the sample that includes the data for @media_time using a
782  * linear search
783  *
784  * Returns the index of the sample.
785  */
786 static guint32
787 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
788     guint64 media_time)
789 {
790   QtDemuxSample *result = str->samples;
791   guint32 index = 0;
792
793   /* convert media_time to mov format */
794   media_time = gst_util_uint64_scale (media_time, str->timescale, GST_SECOND);
795
796   if (media_time == result->timestamp)
797     return index;
798
799   result++;
800   while (index < str->n_samples - 1) {
801     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
802       goto parse_failed;
803
804     if (media_time < result->timestamp)
805       break;
806
807     index++;
808     result++;
809   }
810   return index;
811
812   /* ERRORS */
813 parse_failed:
814   {
815     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
816     return -1;
817   }
818 }
819
820 /* find the index of the keyframe needed to decode the sample at @index
821  * of stream @str.
822  *
823  * Returns the index of the keyframe.
824  */
825 static guint32
826 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
827     guint32 index)
828 {
829   guint32 new_index = index;
830
831   if (index >= str->n_samples) {
832     new_index = str->n_samples;
833     goto beach;
834   }
835
836   /* all keyframes, return index */
837   if (str->all_keyframe) {
838     new_index = index;
839     goto beach;
840   }
841
842   /* else go back until we have a keyframe */
843   while (TRUE) {
844     if (str->samples[new_index].keyframe)
845       break;
846
847     if (new_index == 0)
848       break;
849
850     new_index--;
851   }
852
853 beach:
854   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index before index %u "
855       "gave %u", index, new_index);
856
857   return new_index;
858 }
859
860 /* find the segment for @time_position for @stream
861  *
862  * Returns -1 if the segment cannot be found.
863  */
864 static guint32
865 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
866     guint64 time_position)
867 {
868   gint i;
869   guint32 seg_idx;
870
871   GST_LOG_OBJECT (qtdemux, "finding segment for %" GST_TIME_FORMAT,
872       GST_TIME_ARGS (time_position));
873
874   /* find segment corresponding to time_position if we are looking
875    * for a segment. */
876   seg_idx = -1;
877   for (i = 0; i < stream->n_segments; i++) {
878     QtDemuxSegment *segment = &stream->segments[i];
879
880     GST_LOG_OBJECT (qtdemux,
881         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
882         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
883
884     /* For the last segment we include stop_time in the last segment */
885     if (i < stream->n_segments - 1) {
886       if (segment->time <= time_position && time_position < segment->stop_time) {
887         GST_LOG_OBJECT (qtdemux, "segment %d matches", i);
888         seg_idx = i;
889         break;
890       }
891     } else {
892       if (segment->time <= time_position && time_position <= segment->stop_time) {
893         GST_LOG_OBJECT (qtdemux, "segment %d matches", i);
894         seg_idx = i;
895         break;
896       }
897     }
898   }
899   return seg_idx;
900 }
901
902 /* move the stream @str to the sample position @index.
903  *
904  * Updates @str->sample_index and marks discontinuity if needed.
905  */
906 static void
907 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
908     guint32 index)
909 {
910   /* no change needed */
911   if (index == str->sample_index)
912     return;
913
914   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
915       str->n_samples);
916
917   /* position changed, we have a discont */
918   str->sample_index = index;
919   /* Each time we move in the stream we store the position where we are 
920    * starting from */
921   str->from_sample = index;
922   str->discont = TRUE;
923 }
924
925 static void
926 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
927     gint64 * key_time, gint64 * key_offset)
928 {
929   guint64 min_offset;
930   gint64 min_byte_offset = -1;
931   gint n;
932
933   min_offset = desired_time;
934
935   /* for each stream, find the index of the sample in the segment
936    * and move back to the previous keyframe. */
937   for (n = 0; n < qtdemux->n_streams; n++) {
938     QtDemuxStream *str;
939     guint32 index, kindex;
940     guint32 seg_idx;
941     guint64 media_start;
942     guint64 media_time;
943     guint64 seg_time;
944     QtDemuxSegment *seg;
945
946     str = qtdemux->streams[n];
947
948     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
949     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
950
951     /* segment not found, continue with normal flow */
952     if (seg_idx == -1)
953       continue;
954
955     /* get segment and time in the segment */
956     seg = &str->segments[seg_idx];
957     seg_time = desired_time - seg->time;
958
959     /* get the media time in the segment */
960     media_start = seg->media_start + seg_time;
961
962     /* get the index of the sample with media time */
963     index = gst_qtdemux_find_index (qtdemux, str, media_start);
964     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u",
965         GST_TIME_ARGS (media_start), index);
966
967     /* find previous keyframe */
968     kindex = gst_qtdemux_find_keyframe (qtdemux, str, index);
969
970     /* if the keyframe is at a different position, we need to update the
971      * requested seek time */
972     if (index != kindex) {
973       index = kindex;
974
975       /* get timestamp of keyframe */
976       media_time =
977           gst_util_uint64_scale (str->samples[kindex].timestamp, GST_SECOND,
978           str->timescale);
979       GST_DEBUG_OBJECT (qtdemux, "keyframe at %u with time %" GST_TIME_FORMAT,
980           kindex, GST_TIME_ARGS (media_time));
981
982       /* keyframes in the segment get a chance to change the
983        * desired_offset. keyframes out of the segment are
984        * ignored. */
985       if (media_time >= seg->media_start) {
986         guint64 seg_time;
987
988         /* this keyframe is inside the segment, convert back to
989          * segment time */
990         seg_time = (media_time - seg->media_start) + seg->time;
991         if (seg_time < min_offset)
992           min_offset = seg_time;
993       }
994     }
995
996     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
997       min_byte_offset = str->samples[index].offset;
998   }
999
1000   if (key_time)
1001     *key_time = min_offset;
1002   if (key_offset)
1003     *key_offset = min_byte_offset;
1004 }
1005
1006 static gboolean
1007 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1008     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1009 {
1010   gboolean res;
1011   GstFormat fmt;
1012
1013   g_return_val_if_fail (format != NULL, FALSE);
1014   g_return_val_if_fail (cur != NULL, FALSE);
1015   g_return_val_if_fail (stop != NULL, FALSE);
1016
1017   if (*format == GST_FORMAT_TIME)
1018     return TRUE;
1019
1020   fmt = GST_FORMAT_TIME;
1021   res = TRUE;
1022   if (cur_type != GST_SEEK_TYPE_NONE)
1023     res = gst_pad_query_convert (pad, *format, *cur, &fmt, cur);
1024   if (res && stop_type != GST_SEEK_TYPE_NONE)
1025     res = gst_pad_query_convert (pad, *format, *stop, &fmt, stop);
1026
1027   if (res)
1028     *format = GST_FORMAT_TIME;
1029
1030   return res;
1031 }
1032
1033 /* perform seek in push based mode:
1034    find BYTE position to move to based on time and delegate to upstream
1035 */
1036 static gboolean
1037 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1038 {
1039   gdouble rate;
1040   GstFormat format;
1041   GstSeekFlags flags;
1042   GstSeekType cur_type, stop_type;
1043   gint64 cur, stop;
1044   gboolean res;
1045   gint64 byte_cur;
1046
1047   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1048
1049   gst_event_parse_seek (event, &rate, &format, &flags,
1050       &cur_type, &cur, &stop_type, &stop);
1051
1052   /* FIXME, always play to the end */
1053   stop = -1;
1054
1055   /* only forward streaming and seeking is possible */
1056   if (rate <= 0)
1057     goto unsupported_seek;
1058
1059   /* convert to TIME if needed and possible */
1060   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1061           stop_type, &stop))
1062     goto no_format;
1063
1064   /* find reasonable corresponding BYTE position,
1065    * also try to mind about keyframes, since we can not go back a bit for them
1066    * later on */
1067   gst_qtdemux_adjust_seek (qtdemux, cur, NULL, &byte_cur);
1068
1069   if (byte_cur == -1)
1070     goto abort_seek;
1071
1072   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1073       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1074       stop);
1075
1076   /* BYTE seek event */
1077   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1078       stop_type, stop);
1079   res = gst_pad_push_event (qtdemux->sinkpad, event);
1080
1081   return res;
1082
1083   /* ERRORS */
1084 abort_seek:
1085   {
1086     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1087         "seek aborted.");
1088     return FALSE;
1089   }
1090 unsupported_seek:
1091   {
1092     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1093     return FALSE;
1094   }
1095 no_format:
1096   {
1097     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1098     return FALSE;
1099   }
1100 }
1101
1102 /* perform the seek.
1103  *
1104  * We set all segment_indexes in the streams to unknown and
1105  * adjust the time_position to the desired position. this is enough
1106  * to trigger a segment switch in the streaming thread to start
1107  * streaming from the desired position.
1108  *
1109  * Keyframe seeking is a little more complicated when dealing with
1110  * segments. Ideally we want to move to the previous keyframe in
1111  * the segment but there might not be a keyframe in the segment. In
1112  * fact, none of the segments could contain a keyframe. We take a
1113  * practical approach: seek to the previous keyframe in the segment,
1114  * if there is none, seek to the beginning of the segment.
1115  *
1116  * Called with STREAM_LOCK
1117  */
1118 static gboolean
1119 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment)
1120 {
1121   gint64 desired_offset;
1122   gint n;
1123
1124   desired_offset = segment->last_stop;
1125
1126   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1127       GST_TIME_ARGS (desired_offset));
1128
1129   if (segment->flags & GST_SEEK_FLAG_KEY_UNIT) {
1130     gint64 min_offset;
1131
1132     gst_qtdemux_adjust_seek (qtdemux, desired_offset, &min_offset, NULL);
1133     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1134         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1135     desired_offset = min_offset;
1136   }
1137
1138   /* and set all streams to the final position */
1139   for (n = 0; n < qtdemux->n_streams; n++) {
1140     QtDemuxStream *stream = qtdemux->streams[n];
1141
1142     stream->time_position = desired_offset;
1143     stream->sample_index = -1;
1144     stream->segment_index = -1;
1145     stream->last_ret = GST_FLOW_OK;
1146     stream->sent_eos = FALSE;
1147   }
1148   segment->last_stop = desired_offset;
1149   segment->time = desired_offset;
1150
1151   /* we stop at the end */
1152   if (segment->stop == -1)
1153     segment->stop = segment->duration;
1154
1155   return TRUE;
1156 }
1157
1158 /* do a seek in pull based mode */
1159 static gboolean
1160 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1161 {
1162   gdouble rate;
1163   GstFormat format;
1164   GstSeekFlags flags;
1165   GstSeekType cur_type, stop_type;
1166   gint64 cur, stop;
1167   gboolean flush;
1168   gboolean update;
1169   GstSegment seeksegment;
1170   int i;
1171
1172   if (event) {
1173     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1174
1175     gst_event_parse_seek (event, &rate, &format, &flags,
1176         &cur_type, &cur, &stop_type, &stop);
1177
1178     /* we have to have a format as the segment format. Try to convert
1179      * if not. */
1180     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1181             stop_type, &stop))
1182       goto no_format;
1183
1184     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1185   } else {
1186     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1187     flags = 0;
1188   }
1189
1190   flush = flags & GST_SEEK_FLAG_FLUSH;
1191
1192   /* stop streaming, either by flushing or by pausing the task */
1193   if (flush) {
1194     /* unlock upstream pull_range */
1195     gst_pad_push_event (qtdemux->sinkpad, gst_event_new_flush_start ());
1196     /* make sure out loop function exits */
1197     gst_qtdemux_push_event (qtdemux, gst_event_new_flush_start ());
1198   } else {
1199     /* non flushing seek, pause the task */
1200     gst_pad_pause_task (qtdemux->sinkpad);
1201   }
1202
1203   /* wait for streaming to finish */
1204   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1205
1206   /* copy segment, we need this because we still need the old
1207    * segment when we close the current segment. */
1208   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1209
1210   if (event) {
1211     /* configure the segment with the seek variables */
1212     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1213     gst_segment_set_seek (&seeksegment, rate, format, flags,
1214         cur_type, cur, stop_type, stop, &update);
1215   }
1216
1217   /* now do the seek, this actually never returns FALSE */
1218   gst_qtdemux_perform_seek (qtdemux, &seeksegment);
1219
1220   /* prepare for streaming again */
1221   if (flush) {
1222     gst_pad_push_event (qtdemux->sinkpad, gst_event_new_flush_stop ());
1223     gst_qtdemux_push_event (qtdemux, gst_event_new_flush_stop ());
1224   } else if (qtdemux->segment_running) {
1225     /* we are running the current segment and doing a non-flushing seek,
1226      * close the segment first based on the last_stop. */
1227     GST_DEBUG_OBJECT (qtdemux, "closing running segment %" G_GINT64_FORMAT
1228         " to %" G_GINT64_FORMAT, qtdemux->segment.start,
1229         qtdemux->segment.last_stop);
1230
1231     if (qtdemux->segment.rate >= 0) {
1232       /* FIXME, rate is the product of the global rate and the (quicktime)
1233        * segment rate. */
1234       qtdemux->pending_newsegment = gst_event_new_new_segment (TRUE,
1235           qtdemux->segment.rate, qtdemux->segment.format,
1236           qtdemux->segment.start, qtdemux->segment.last_stop,
1237           qtdemux->segment.time);
1238     } else {                    /* For Reverse Playback */
1239       guint64 stop;
1240
1241       if ((stop = qtdemux->segment.stop) == -1)
1242         stop = qtdemux->segment.duration;
1243       /* for reverse playback, we played from stop to last_stop. */
1244       qtdemux->pending_newsegment = gst_event_new_new_segment (TRUE,
1245           qtdemux->segment.rate, qtdemux->segment.format,
1246           qtdemux->segment.last_stop, stop, qtdemux->segment.last_stop);
1247     }
1248   }
1249
1250   /* commit the new segment */
1251   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1252
1253   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1254     gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
1255         gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1256             qtdemux->segment.format, qtdemux->segment.last_stop));
1257   }
1258
1259   /* restart streaming, NEWSEGMENT will be sent from the streaming
1260    * thread. */
1261   qtdemux->segment_running = TRUE;
1262   for (i = 0; i < qtdemux->n_streams; i++)
1263     qtdemux->streams[i]->last_ret = GST_FLOW_OK;
1264
1265   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1266       qtdemux->sinkpad);
1267
1268   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1269
1270   return TRUE;
1271
1272   /* ERRORS */
1273 no_format:
1274   {
1275     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1276     return FALSE;
1277   }
1278 }
1279
1280 static gboolean
1281 qtdemux_ensure_index (GstQTDemux * qtdemux)
1282 {
1283   guint i;
1284
1285   /* Build complete index */
1286   for (i = 0; i < qtdemux->n_streams; i++) {
1287     QtDemuxStream *stream = qtdemux->streams[i];
1288
1289     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1))
1290       goto parse_error;
1291   }
1292   return TRUE;
1293
1294   /* ERRORS */
1295 parse_error:
1296   {
1297     GST_LOG_OBJECT (qtdemux,
1298         "Building complete index of stream %u for seeking failed!", i);
1299     return FALSE;
1300   }
1301 }
1302
1303 static gboolean
1304 gst_qtdemux_handle_src_event (GstPad * pad, GstEvent * event)
1305 {
1306   gboolean res = TRUE;
1307   GstQTDemux *qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
1308
1309   switch (GST_EVENT_TYPE (event)) {
1310     case GST_EVENT_SEEK:
1311     {
1312       GstClockTime ts = gst_util_get_timestamp ();
1313       /* Build complete index for seeking */
1314       if (!qtdemux_ensure_index (qtdemux))
1315         goto index_failed;
1316       ts = gst_util_get_timestamp () - ts;
1317       GST_INFO_OBJECT (qtdemux,
1318           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1319     }
1320       if (qtdemux->pullbased) {
1321         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1322       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams) {
1323         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1324       } else {
1325         GST_DEBUG_OBJECT (qtdemux,
1326             "ignoring seek in push mode in current state");
1327         res = FALSE;
1328       }
1329       gst_event_unref (event);
1330       break;
1331     case GST_EVENT_QOS:
1332     case GST_EVENT_NAVIGATION:
1333       res = FALSE;
1334       gst_event_unref (event);
1335       break;
1336     default:
1337       res = gst_pad_event_default (pad, event);
1338       break;
1339   }
1340
1341   gst_object_unref (qtdemux);
1342
1343   return res;
1344
1345   /* ERRORS */
1346 index_failed:
1347   {
1348     GST_ERROR_OBJECT (qtdemux, "Index failed");
1349     gst_event_unref (event);
1350     return FALSE;
1351   }
1352 }
1353
1354 /* stream/index return sample that is min/max w.r.t. byte position,
1355  * time is min/max w.r.t. time of samples,
1356  * the latter need not be time of the former sample */
1357 static void
1358 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1359     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1360 {
1361   gint i, n, index;
1362   guint32 ts_timescale = -1;    /* the timescale corresponding to min_time */
1363   gint64 time, min_time;
1364   QtDemuxStream *stream;
1365
1366   min_time = -1;
1367   stream = NULL;
1368   index = -1;
1369
1370   for (n = 0; n < qtdemux->n_streams; ++n) {
1371     QtDemuxStream *str;
1372     gint inc;
1373     gboolean set_sample;
1374
1375
1376     str = qtdemux->streams[n];
1377     set_sample = !set;
1378
1379     if (fw) {
1380       i = 0;
1381       inc = 1;
1382     } else {
1383       i = str->n_samples - 1;
1384       inc = -1;
1385     }
1386     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1387       if (str->samples[i].size &&
1388           ((fw && (str->samples[i].offset >= byte_pos)) ||
1389               (!fw &&
1390                   (str->samples[i].offset + str->samples[i].size <=
1391                       byte_pos)))) {
1392         /* move stream to first available sample */
1393         if (set) {
1394           gst_qtdemux_move_stream (qtdemux, str, i);
1395           set_sample = TRUE;
1396         }
1397         /* determine min/max time */
1398         time = str->samples[i].timestamp + str->samples[i].pts_offset;
1399         if (min_time == -1 || (fw && min_time > time) ||
1400             (!fw && min_time < time)) {
1401           min_time = time;
1402           ts_timescale = str->timescale;
1403         }
1404         /* determine stream with leading sample, to get its position */
1405         if (!stream || (fw
1406                 && (str->samples[i].offset < stream->samples[index].offset))
1407             || (!fw
1408                 && (str->samples[i].offset > stream->samples[index].offset))) {
1409           stream = str;
1410           index = i;
1411         }
1412         break;
1413       }
1414     }
1415     /* no sample for this stream, mark eos */
1416     if (!set_sample)
1417       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1418   }
1419
1420   if (_time && ts_timescale != -1)
1421     *_time = gst_util_uint64_scale (min_time, GST_SECOND, ts_timescale);
1422   if (_stream)
1423     *_stream = stream;
1424   if (_index)
1425     *_index = index;
1426 }
1427
1428 static gboolean
1429 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstEvent * event)
1430 {
1431   GstQTDemux *demux = GST_QTDEMUX (GST_PAD_PARENT (sinkpad));
1432   gboolean res;
1433
1434   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
1435
1436   switch (GST_EVENT_TYPE (event)) {
1437     case GST_EVENT_NEWSEGMENT:
1438     {
1439       GstFormat format;
1440       gdouble rate, arate;
1441       gint64 start, stop, time, offset = 0;
1442       QtDemuxStream *stream;
1443       gint idx;
1444       gboolean update;
1445       GstSegment segment;
1446
1447       /* some debug output */
1448       gst_segment_init (&segment, GST_FORMAT_UNDEFINED);
1449       gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
1450           &start, &stop, &time);
1451       gst_segment_set_newsegment_full (&segment, update, rate, arate, format,
1452           start, stop, time);
1453       GST_DEBUG_OBJECT (demux,
1454           "received format %d newsegment %" GST_SEGMENT_FORMAT, format,
1455           &segment);
1456
1457       /* chain will send initial newsegment after pads have been added */
1458       if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
1459         GST_DEBUG_OBJECT (demux, "still starting, eating event");
1460         goto exit;
1461       }
1462
1463       /* we only expect a BYTE segment, e.g. following a seek */
1464       if (format == GST_FORMAT_BYTES) {
1465         if (start > 0) {
1466           offset = start;
1467           gst_qtdemux_find_sample (demux, start, TRUE, FALSE, NULL, NULL,
1468               &start);
1469           start = MAX (start, 0);
1470         }
1471         if (stop > 0) {
1472           gst_qtdemux_find_sample (demux, stop, FALSE, FALSE, NULL, NULL,
1473               &stop);
1474           stop = MAX (stop, 0);
1475         }
1476       } else {
1477         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
1478         goto exit;
1479       }
1480
1481       /* accept upstream's notion of segment and distribute along */
1482       gst_segment_set_newsegment_full (&demux->segment, update, rate, arate,
1483           GST_FORMAT_TIME, start, stop, start);
1484       GST_DEBUG_OBJECT (demux, "Pushing newseg update %d, rate %g, "
1485           "applied rate %g, format %d, start %" GST_TIME_FORMAT ", "
1486           "stop %" GST_TIME_FORMAT, update, rate, arate, GST_FORMAT_TIME,
1487           GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
1488       gst_qtdemux_push_event (demux,
1489           gst_event_new_new_segment_full (update, rate, arate, GST_FORMAT_TIME,
1490               start, stop, start));
1491
1492       /* clear leftover in current segment, if any */
1493       gst_adapter_clear (demux->adapter);
1494       /* set up streaming thread */
1495       gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx, NULL);
1496       demux->offset = offset;
1497       if (stream) {
1498         demux->todrop = stream->samples[idx].offset - offset;
1499         demux->neededbytes = demux->todrop + stream->samples[idx].size;
1500       } else {
1501         /* set up for EOS */
1502         demux->neededbytes = -1;
1503         demux->todrop = 0;
1504       }
1505     exit:
1506       gst_event_unref (event);
1507       res = TRUE;
1508       goto drop;
1509       break;
1510     }
1511     case GST_EVENT_FLUSH_STOP:
1512     {
1513       gint i;
1514
1515       /* clean up, force EOS if no more info follows */
1516       gst_adapter_clear (demux->adapter);
1517       demux->offset = 0;
1518       demux->neededbytes = -1;
1519       /* reset flow return, e.g. following seek */
1520       for (i = 0; i < demux->n_streams; i++) {
1521         demux->streams[i]->last_ret = GST_FLOW_OK;
1522         demux->streams[i]->sent_eos = FALSE;
1523       }
1524       break;
1525     }
1526     case GST_EVENT_EOS:
1527       /* If we are in push mode, and get an EOS before we've seen any streams,
1528        * then error out - we have nowhere to send the EOS */
1529       if (!demux->pullbased && demux->n_streams == 0) {
1530         GST_ELEMENT_ERROR (demux, STREAM, DECODE,
1531             (_("This file contains no playable streams.")),
1532             ("no known streams found"));
1533       }
1534       break;
1535     default:
1536       break;
1537   }
1538
1539   res = gst_pad_event_default (demux->sinkpad, event);
1540
1541 drop:
1542   return res;
1543 }
1544
1545 static void
1546 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
1547 {
1548   GstQTDemux *demux = GST_QTDEMUX (element);
1549
1550   GST_OBJECT_LOCK (demux);
1551   if (demux->element_index)
1552     gst_object_unref (demux->element_index);
1553   if (index) {
1554     demux->element_index = gst_object_ref (index);
1555   } else {
1556     demux->element_index = NULL;
1557   }
1558   GST_OBJECT_UNLOCK (demux);
1559   /* object lock might be taken again */
1560   if (index)
1561     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
1562   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT, demux->element_index);
1563 }
1564
1565 static GstIndex *
1566 gst_qtdemux_get_index (GstElement * element)
1567 {
1568   GstIndex *result = NULL;
1569   GstQTDemux *demux = GST_QTDEMUX (element);
1570
1571   GST_OBJECT_LOCK (demux);
1572   if (demux->element_index)
1573     result = gst_object_ref (demux->element_index);
1574   GST_OBJECT_UNLOCK (demux);
1575
1576   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
1577
1578   return result;
1579 }
1580
1581 static void
1582 gst_qtdemux_stbl_free (QtDemuxStream * stream)
1583 {
1584   g_free ((gpointer) stream->stco.data);
1585   g_free ((gpointer) stream->stsz.data);
1586   g_free ((gpointer) stream->stsc.data);
1587   g_free ((gpointer) stream->stts.data);
1588   g_free ((gpointer) stream->stss.data);
1589   g_free ((gpointer) stream->stps.data);
1590   g_free ((gpointer) stream->ctts.data);
1591 }
1592
1593 static GstStateChangeReturn
1594 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
1595 {
1596   GstQTDemux *qtdemux = GST_QTDEMUX (element);
1597   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
1598
1599   switch (transition) {
1600     case GST_STATE_CHANGE_PAUSED_TO_READY:
1601       break;
1602     default:
1603       break;
1604   }
1605
1606   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1607
1608   switch (transition) {
1609     case GST_STATE_CHANGE_PAUSED_TO_READY:{
1610       gint n;
1611
1612       qtdemux->state = QTDEMUX_STATE_INITIAL;
1613       qtdemux->neededbytes = 16;
1614       qtdemux->todrop = 0;
1615       qtdemux->pullbased = FALSE;
1616       qtdemux->offset = 0;
1617       qtdemux->first_mdat = -1;
1618       qtdemux->mdatoffset = GST_CLOCK_TIME_NONE;
1619       if (qtdemux->mdatbuffer)
1620         gst_buffer_unref (qtdemux->mdatbuffer);
1621       qtdemux->mdatbuffer = NULL;
1622       if (qtdemux->comp_brands)
1623         gst_buffer_unref (qtdemux->comp_brands);
1624       qtdemux->comp_brands = NULL;
1625       if (qtdemux->tag_list)
1626         gst_tag_list_free (qtdemux->tag_list);
1627       qtdemux->tag_list = NULL;
1628       if (qtdemux->element_index)
1629         gst_object_unref (qtdemux->element_index);
1630       qtdemux->element_index = NULL;
1631       gst_adapter_clear (qtdemux->adapter);
1632       for (n = 0; n < qtdemux->n_streams; n++) {
1633         QtDemuxStream *stream = qtdemux->streams[n];
1634
1635         while (stream->buffers) {
1636           gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
1637           stream->buffers =
1638               g_slist_delete_link (stream->buffers, stream->buffers);
1639         }
1640         if (stream->pad)
1641           gst_element_remove_pad (element, stream->pad);
1642         if (stream->samples)
1643           g_free (stream->samples);
1644         if (stream->caps)
1645           gst_caps_unref (stream->caps);
1646         if (stream->segments)
1647           g_free (stream->segments);
1648         if (stream->pending_tags)
1649           gst_tag_list_free (stream->pending_tags);
1650         /* free stbl sub-atoms */
1651         gst_qtdemux_stbl_free (stream);
1652         g_free (stream);
1653       }
1654       qtdemux->major_brand = 0;
1655       qtdemux->n_streams = 0;
1656       qtdemux->n_video_streams = 0;
1657       qtdemux->n_audio_streams = 0;
1658       qtdemux->n_sub_streams = 0;
1659       gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
1660       break;
1661     }
1662     default:
1663       break;
1664   }
1665
1666   return result;
1667 }
1668
1669 static void
1670 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
1671 {
1672   /* only consider at least a sufficiently complete ftyp atom */
1673   if (length >= 20) {
1674     GstBuffer *buf;
1675
1676     qtdemux->major_brand = QT_FOURCC (buffer + 8);
1677     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
1678         GST_FOURCC_ARGS (qtdemux->major_brand));
1679     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
1680     memcpy (GST_BUFFER_DATA (buf), buffer + 16, GST_BUFFER_SIZE (buf));
1681   }
1682 }
1683
1684 static void
1685 extract_initial_length_and_fourcc (const guint8 * data, guint64 * plength,
1686     guint32 * pfourcc)
1687 {
1688   guint64 length;
1689   guint32 fourcc;
1690
1691   length = QT_UINT32 (data);
1692   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
1693   fourcc = QT_FOURCC (data + 4);
1694   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
1695
1696   if (length == 0) {
1697     length = G_MAXUINT32;
1698   } else if (length == 1) {
1699     /* this means we have an extended size, which is the 64 bit value of
1700      * the next 8 bytes */
1701     length = QT_UINT64 (data + 8);
1702     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
1703   }
1704
1705   if (plength)
1706     *plength = length;
1707   if (pfourcc)
1708     *pfourcc = fourcc;
1709 }
1710
1711 static GstFlowReturn
1712 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
1713 {
1714   guint64 length = 0;
1715   guint32 fourcc = 0;
1716   GstBuffer *buf = NULL;
1717   GstFlowReturn ret = GST_FLOW_OK;
1718   guint64 cur_offset = qtdemux->offset;
1719
1720   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
1721   if (G_UNLIKELY (ret != GST_FLOW_OK))
1722     goto beach;
1723   if (G_LIKELY (GST_BUFFER_SIZE (buf) == 16))
1724     extract_initial_length_and_fourcc (GST_BUFFER_DATA (buf), &length, &fourcc);
1725   gst_buffer_unref (buf);
1726
1727   if (G_UNLIKELY (length == 0)) {
1728     GST_ELEMENT_ERROR (qtdemux, STREAM, DECODE,
1729         (_("This file is invalid and cannot be played.")),
1730         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
1731             GST_FOURCC_ARGS (fourcc)));
1732     ret = GST_FLOW_ERROR;
1733     goto beach;
1734   }
1735
1736   switch (fourcc) {
1737     case FOURCC_mdat:
1738     case FOURCC_free:
1739     case FOURCC_wide:
1740     case FOURCC_PICT:
1741     case FOURCC_pnot:
1742     {
1743       GST_LOG_OBJECT (qtdemux,
1744           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
1745           GST_FOURCC_ARGS (fourcc), cur_offset);
1746       qtdemux->offset += length;
1747       break;
1748     }
1749     case FOURCC_moov:
1750     {
1751       GstBuffer *moov;
1752
1753       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
1754       if (ret != GST_FLOW_OK)
1755         goto beach;
1756       if (length != GST_BUFFER_SIZE (moov)) {
1757         /* Some files have a 'moov' atom at the end of the file which contains
1758          * a terminal 'free' atom where the body of the atom is missing.
1759          * Check for, and permit, this special case.
1760          */
1761         if (GST_BUFFER_SIZE (moov) >= 8) {
1762           guint8 *final_data = GST_BUFFER_DATA (moov) +
1763               (GST_BUFFER_SIZE (moov) - 8);
1764           guint32 final_length = QT_UINT32 (final_data);
1765           guint32 final_fourcc = QT_FOURCC (final_data + 4);
1766           if (final_fourcc == FOURCC_free &&
1767               GST_BUFFER_SIZE (moov) + final_length - 8 == length) {
1768             /* Ok, we've found that special case. Allocate a new buffer with
1769              * that free atom actually present. */
1770             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
1771             gst_buffer_copy_metadata (newmoov, moov,
1772                 GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS |
1773                 GST_BUFFER_COPY_CAPS);
1774             memcpy (GST_BUFFER_DATA (newmoov), GST_BUFFER_DATA (moov),
1775                 GST_BUFFER_SIZE (moov));
1776             memset (GST_BUFFER_DATA (newmoov) + GST_BUFFER_SIZE (moov), 0,
1777                 final_length - 8);
1778             gst_buffer_unref (moov);
1779             moov = newmoov;
1780           }
1781         }
1782       }
1783
1784       if (length != GST_BUFFER_SIZE (moov)) {
1785         GST_ELEMENT_ERROR (qtdemux, STREAM, DECODE,
1786             (_("This file is incomplete and cannot be played.")),
1787             ("We got less than expected (received %u, wanted %u, offset %"
1788                 G_GUINT64_FORMAT ")",
1789                 GST_BUFFER_SIZE (moov), (guint) length, cur_offset));
1790         ret = GST_FLOW_ERROR;
1791         goto beach;
1792       }
1793       qtdemux->offset += length;
1794
1795       qtdemux_parse_moov (qtdemux, GST_BUFFER_DATA (moov), length);
1796       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
1797
1798       qtdemux_parse_tree (qtdemux);
1799       g_node_destroy (qtdemux->moov_node);
1800       gst_buffer_unref (moov);
1801       qtdemux->moov_node = NULL;
1802       qtdemux->state = QTDEMUX_STATE_MOVIE;
1803       GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
1804           qtdemux->state);
1805       break;
1806     }
1807     case FOURCC_ftyp:
1808     {
1809       GstBuffer *ftyp;
1810
1811       /* extract major brand; might come in handy for ISO vs QT issues */
1812       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
1813       if (ret != GST_FLOW_OK)
1814         goto beach;
1815       qtdemux->offset += length;
1816       qtdemux_parse_ftyp (qtdemux, GST_BUFFER_DATA (ftyp),
1817           GST_BUFFER_SIZE (ftyp));
1818       gst_buffer_unref (ftyp);
1819       break;
1820     }
1821     default:
1822     {
1823       GstBuffer *unknown;
1824
1825       GST_LOG_OBJECT (qtdemux,
1826           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
1827           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
1828           cur_offset);
1829       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
1830       if (ret != GST_FLOW_OK)
1831         goto beach;
1832       GST_MEMDUMP ("Unknown tag", GST_BUFFER_DATA (unknown),
1833           GST_BUFFER_SIZE (unknown));
1834       gst_buffer_unref (unknown);
1835       qtdemux->offset += length;
1836       break;
1837     }
1838   }
1839
1840 beach:
1841   return ret;
1842 }
1843
1844 /* Seeks to the previous keyframe of the indexed stream and 
1845  * aligns other streams with respect to the keyframe timestamp 
1846  * of indexed stream. Only called in case of Reverse Playback
1847  */
1848 static GstFlowReturn
1849 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
1850 {
1851   guint8 n = 0;
1852   guint32 seg_idx = 0, k_index = 0;
1853   guint64 k_pos = 0, last_stop = 0;
1854   QtDemuxSegment *seg = NULL;
1855   QtDemuxStream *ref_str = NULL;
1856   guint64 seg_media_start_mov;  /* segment media start time in mov format */
1857
1858   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
1859    * and finally align all the other streams on that timestamp with their 
1860    * respective keyframes */
1861   for (n = 0; n < qtdemux->n_streams; n++) {
1862     QtDemuxStream *str = qtdemux->streams[n];
1863
1864     seg_idx = gst_qtdemux_find_segment (qtdemux, str,
1865         qtdemux->segment.last_stop);
1866
1867     /* segment not found, continue with normal flow */
1868     if (seg_idx == -1)
1869       continue;
1870
1871     /* No candidate yet, take that one */
1872     if (!ref_str) {
1873       ref_str = str;
1874       continue;
1875     }
1876
1877     /* So that stream has a segment, we prefer video streams */
1878     if (str->subtype == FOURCC_vide) {
1879       ref_str = str;
1880       break;
1881     }
1882   }
1883
1884   if (G_UNLIKELY (!ref_str)) {
1885     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
1886     goto eos;
1887   }
1888
1889   if (G_UNLIKELY (!ref_str->from_sample)) {
1890     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
1891     goto eos;
1892   }
1893
1894   /* So that stream has been playing from from_sample to to_sample. We will
1895    * get the timestamp of the previous sample and search for a keyframe before
1896    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
1897   if (ref_str->subtype == FOURCC_vide) {
1898     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
1899         ref_str->from_sample - 1);
1900   } else {
1901     k_index = ref_str->from_sample - 10;
1902   }
1903
1904   /* get current segment for that stream */
1905   seg = &ref_str->segments[ref_str->segment_index];
1906   /* convert seg->media_start to mov format time for timestamp comparison */
1907   seg_media_start_mov =
1908       gst_util_uint64_scale (seg->media_start, ref_str->timescale, GST_SECOND);
1909   /* Crawl back through segments to find the one containing this I frame */
1910   while (ref_str->samples[k_index].timestamp < seg_media_start_mov) {
1911     GST_DEBUG_OBJECT (qtdemux, "keyframe position is out of segment %u",
1912         ref_str->segment_index);
1913     if (G_UNLIKELY (!ref_str->segment_index)) {
1914       /* Reached first segment, let's consider it's EOS */
1915       goto eos;
1916     }
1917     ref_str->segment_index--;
1918     seg = &ref_str->segments[ref_str->segment_index];
1919   }
1920   /* Calculate time position of the keyframe and where we should stop */
1921   k_pos =
1922       (gst_util_uint64_scale (ref_str->samples[k_index].timestamp, GST_SECOND,
1923           ref_str->timescale) - seg->media_start) + seg->time;
1924   last_stop =
1925       gst_util_uint64_scale (ref_str->samples[ref_str->from_sample].timestamp,
1926       GST_SECOND, ref_str->timescale);
1927   last_stop = (last_stop - seg->media_start) + seg->time;
1928
1929   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
1930       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
1931       k_index, GST_TIME_ARGS (k_pos));
1932
1933   /* Set last_stop with the keyframe timestamp we pushed of that stream */
1934   gst_segment_set_last_stop (&qtdemux->segment, GST_FORMAT_TIME, last_stop);
1935   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
1936       GST_TIME_ARGS (last_stop));
1937
1938   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
1939     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
1940     goto eos;
1941   }
1942
1943   /* Align them all on this */
1944   for (n = 0; n < qtdemux->n_streams; n++) {
1945     guint32 index = 0;
1946     guint64 media_start = 0, seg_time = 0;
1947     QtDemuxStream *str = qtdemux->streams[n];
1948
1949     seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
1950     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1951
1952     /* segment not found, continue with normal flow */
1953     if (seg_idx == -1)
1954       continue;
1955
1956     /* get segment and time in the segment */
1957     seg = &str->segments[seg_idx];
1958     seg_time = k_pos - seg->time;
1959
1960     /* get the media time in the segment */
1961     media_start = seg->media_start + seg_time;
1962
1963     /* get the index of the sample with media time */
1964     index = gst_qtdemux_find_index (qtdemux, str, media_start);
1965     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u",
1966         GST_TIME_ARGS (media_start), index);
1967
1968     /* find previous keyframe */
1969     k_index = gst_qtdemux_find_keyframe (qtdemux, str, index);
1970
1971     /* Remember until where we want to go */
1972     str->to_sample = str->from_sample - 1;
1973     /* Define our time position */
1974     str->time_position =
1975         (gst_util_uint64_scale (str->samples[k_index].timestamp, GST_SECOND,
1976             str->timescale) - seg->media_start) + seg->time;
1977     /* Now seek back in time */
1978     gst_qtdemux_move_stream (qtdemux, str, k_index);
1979     GST_DEBUG_OBJECT (qtdemux, "keyframe at %u, time position %"
1980         GST_TIME_FORMAT " playing from sample %u to %u", k_index,
1981         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
1982   }
1983
1984   return GST_FLOW_OK;
1985
1986 eos:
1987   return GST_FLOW_UNEXPECTED;
1988 }
1989
1990 /* activate the given segment number @seg_idx of @stream at time @offset.
1991  * @offset is an absolute global position over all the segments.
1992  *
1993  * This will push out a NEWSEGMENT event with the right values and
1994  * position the stream index to the first decodable sample before
1995  * @offset.
1996  */
1997 static gboolean
1998 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1999     guint32 seg_idx, guint64 offset)
2000 {
2001   GstEvent *event;
2002   QtDemuxSegment *segment;
2003   guint32 index, kf_index;
2004   guint64 seg_time;
2005   guint64 start, stop, time;
2006   gdouble rate;
2007
2008   GST_LOG_OBJECT (qtdemux, "activate segment %d, offset %" G_GUINT64_FORMAT,
2009       seg_idx, offset);
2010
2011   /* update the current segment */
2012   stream->segment_index = seg_idx;
2013
2014   /* get the segment */
2015   segment = &stream->segments[seg_idx];
2016
2017   if (G_UNLIKELY (offset < segment->time)) {
2018     GST_WARNING_OBJECT (qtdemux, "offset < segment->time %" G_GUINT64_FORMAT,
2019         segment->time);
2020     return FALSE;
2021   }
2022
2023   /* get time in this segment */
2024   seg_time = offset - segment->time;
2025
2026   GST_LOG_OBJECT (qtdemux, "seg_time %" GST_TIME_FORMAT,
2027       GST_TIME_ARGS (seg_time));
2028
2029   if (G_UNLIKELY (seg_time > segment->duration)) {
2030     GST_LOG_OBJECT (qtdemux, "seg_time > segment->duration %" GST_TIME_FORMAT,
2031         GST_TIME_ARGS (segment->duration));
2032     return FALSE;
2033   }
2034
2035   /* qtdemux->segment.stop is in outside-time-realm, whereas
2036    * segment->media_stop is in track-time-realm.
2037    * 
2038    * In order to compare the two, we need to bring segment.stop
2039    * into the track-time-realm */
2040
2041   if (qtdemux->segment.stop == -1)
2042     stop = segment->media_stop;
2043   else
2044     stop =
2045         MIN (segment->media_stop,
2046         qtdemux->segment.stop - segment->time + segment->media_start);
2047
2048   if (qtdemux->segment.rate >= 0) {
2049     start = MIN (segment->media_start + seg_time, stop);
2050     time = offset;
2051   } else {
2052     start = segment->media_start;
2053     stop = MIN (segment->media_start + seg_time, stop);
2054     time = segment->time;
2055   }
2056
2057   GST_DEBUG_OBJECT (qtdemux, "newsegment %d from %" GST_TIME_FORMAT
2058       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
2059       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
2060
2061   /* combine global rate with that of the segment */
2062   rate = segment->rate * qtdemux->segment.rate;
2063
2064   /* update the segment values used for clipping */
2065   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
2066   gst_segment_set_newsegment (&stream->segment, FALSE, rate, GST_FORMAT_TIME,
2067       start, stop, time);
2068
2069   /* now prepare and send the segment */
2070   if (stream->pad) {
2071     event = gst_event_new_new_segment (FALSE, rate, GST_FORMAT_TIME,
2072         start, stop, time);
2073     gst_pad_push_event (stream->pad, event);
2074     /* assume we can send more data now */
2075     stream->last_ret = GST_FLOW_OK;
2076     /* clear to send tags on this pad now */
2077     gst_qtdemux_push_tags (qtdemux, stream);
2078   }
2079
2080   /* and move to the keyframe before the indicated media time of the
2081    * segment */
2082   if (qtdemux->segment.rate >= 0) {
2083     index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
2084     stream->to_sample = stream->n_samples;
2085     GST_DEBUG_OBJECT (qtdemux, "moving data pointer to %" GST_TIME_FORMAT
2086         ", index: %u, pts %" GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
2087         GST_TIME_ARGS (gst_util_uint64_scale (stream->samples[index].timestamp,
2088                 GST_SECOND, stream->timescale)));
2089   } else {
2090     index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
2091     stream->to_sample = index;
2092     GST_DEBUG_OBJECT (qtdemux, "moving data pointer to %" GST_TIME_FORMAT
2093         ", index: %u, pts %" GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
2094         GST_TIME_ARGS (gst_util_uint64_scale (stream->samples[index].timestamp,
2095                 GST_SECOND, stream->timescale)));
2096   }
2097
2098   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
2099    * encountered an error and printed a message so we return appropriately */
2100   if (index == -1)
2101     return FALSE;
2102
2103   /* we're at the right spot */
2104   if (index == stream->sample_index) {
2105     GST_DEBUG_OBJECT (qtdemux, "we are at the right index");
2106     return TRUE;
2107   }
2108
2109   /* find keyframe of the target index */
2110   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index);
2111
2112 /* *INDENT-OFF* */
2113 /* indent does stupid stuff with stream->samples[].timestamp */
2114
2115   /* if we move forwards, we don't have to go back to the previous
2116    * keyframe since we already sent that. We can also just jump to
2117    * the keyframe right before the target index if there is one. */
2118   if (index > stream->sample_index) {
2119     /* moving forwards check if we move past a keyframe */
2120     if (kf_index > stream->sample_index) {
2121       GST_DEBUG_OBJECT (qtdemux,
2122           "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT, kf_index,
2123           GST_TIME_ARGS (gst_util_uint64_scale (
2124                   stream->samples[kf_index].timestamp,
2125                   GST_SECOND, stream->timescale)));
2126       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
2127     } else {
2128       GST_DEBUG_OBJECT (qtdemux,
2129           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT
2130           " already sent", kf_index,
2131           GST_TIME_ARGS (gst_util_uint64_scale (
2132                   stream->samples[kf_index].timestamp,
2133                   GST_SECOND, stream->timescale)));
2134     }
2135   } else {
2136     GST_DEBUG_OBJECT (qtdemux,
2137         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT, kf_index,
2138         GST_TIME_ARGS (gst_util_uint64_scale (
2139                 stream->samples[kf_index].timestamp,
2140                 GST_SECOND, stream->timescale)));
2141     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
2142   }
2143
2144 /* *INDENT-ON* */
2145
2146   return TRUE;
2147 }
2148
2149 /* prepare to get the current sample of @stream, getting essential values.
2150  *
2151  * This function will also prepare and send the segment when needed.
2152  *
2153  * Return FALSE if the stream is EOS.
2154  */
2155 static gboolean
2156 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
2157     QtDemuxStream * stream, guint64 * offset, guint * size, guint64 * timestamp,
2158     guint64 * duration, gboolean * keyframe)
2159 {
2160   QtDemuxSample *sample;
2161   guint64 time_position;
2162   guint32 seg_idx;
2163
2164   g_return_val_if_fail (stream != NULL, FALSE);
2165
2166   time_position = stream->time_position;
2167   if (G_UNLIKELY (time_position == -1))
2168     goto eos;
2169
2170   seg_idx = stream->segment_index;
2171   if (G_UNLIKELY (seg_idx == -1)) {
2172     /* find segment corresponding to time_position if we are looking
2173      * for a segment. */
2174     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
2175
2176     /* nothing found, we're really eos */
2177     if (seg_idx == -1)
2178       goto eos;
2179   }
2180
2181   /* different segment, activate it, sample_index will be set. */
2182   if (G_UNLIKELY (stream->segment_index != seg_idx))
2183     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
2184
2185   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
2186       stream->sample_index, stream->n_samples);
2187
2188   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
2189     goto eos;
2190
2191   /* now get the info for the sample we're at */
2192   sample = &stream->samples[stream->sample_index];
2193
2194   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
2195     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
2196         stream->sample_index);
2197     return FALSE;
2198   }
2199
2200   *timestamp = QTSAMPLE_PTS (stream, sample);
2201   *offset = sample->offset;
2202   *size = sample->size;
2203   *duration = QTSAMPLE_DUR_PTS (stream, sample, *timestamp);
2204   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
2205
2206   /* update dummy segment duration */
2207   if (stream->sample_index == stream->n_samples - 1 && stream->n_segments == 1) {
2208     stream->segments[0].duration = stream->segments[0].stop_time =
2209         stream->segments[0].media_stop = *timestamp + *duration;
2210   }
2211
2212   return TRUE;
2213
2214   /* special cases */
2215 eos:
2216   {
2217     stream->time_position = -1;
2218     return FALSE;
2219   }
2220 }
2221
2222 /* move to the next sample in @stream.
2223  *
2224  * Moves to the next segment when needed.
2225  */
2226 static void
2227 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
2228 {
2229   QtDemuxSample *sample;
2230   QtDemuxSegment *segment;
2231
2232   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
2233     /* Mark the stream as EOS */
2234     GST_DEBUG_OBJECT (qtdemux,
2235         "reached max allowed sample %u, mark EOS", stream->to_sample);
2236     stream->time_position = -1;
2237     return;
2238   }
2239
2240   /* move to next sample */
2241   stream->sample_index++;
2242
2243   /* get current segment */
2244   segment = &stream->segments[stream->segment_index];
2245
2246   /* reached the last sample, we need the next segment */
2247   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
2248     goto next_segment;
2249
2250   /* get next sample */
2251   sample = &stream->samples[stream->sample_index];
2252
2253   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
2254     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
2255         stream->sample_index);
2256     return;
2257   }
2258
2259   /* see if we are past the segment */
2260   if (G_UNLIKELY (gst_util_uint64_scale (sample->timestamp,
2261               GST_SECOND, stream->timescale) >= segment->media_stop))
2262     goto next_segment;
2263
2264   if (gst_util_uint64_scale (sample->timestamp, GST_SECOND,
2265           stream->timescale) >= segment->media_start) {
2266     /* inside the segment, update time_position, looks very familiar to
2267      * GStreamer segments, doesn't it? */
2268     stream->time_position =
2269         (gst_util_uint64_scale (sample->timestamp, GST_SECOND,
2270             stream->timescale) - segment->media_start) + segment->time;
2271   } else {
2272     /* not yet in segment, time does not yet increment. This means
2273      * that we are still prerolling keyframes to the decoder so it can
2274      * decode the first sample of the segment. */
2275     stream->time_position = segment->time;
2276   }
2277   return;
2278
2279   /* move to the next segment */
2280 next_segment:
2281   {
2282     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
2283
2284     if (stream->segment_index == stream->n_segments - 1) {
2285       /* are we at the end of the last segment, we're EOS */
2286       stream->time_position = -1;
2287     } else {
2288       /* else we're only at the end of the current segment */
2289       stream->time_position = segment->stop_time;
2290     }
2291     /* make sure we select a new segment */
2292     stream->segment_index = -1;
2293   }
2294 }
2295
2296 static void
2297 gst_qtdemux_sync_streams (GstQTDemux * demux)
2298 {
2299   gint i;
2300
2301   if (demux->n_streams <= 1)
2302     return;
2303
2304   for (i = 0; i < demux->n_streams; i++) {
2305     QtDemuxStream *stream;
2306     GstClockTime end_time;
2307
2308     stream = demux->streams[i];
2309
2310     if (!stream->pad)
2311       continue;
2312
2313     /* TODO advance time on subtitle streams here, if any some day */
2314
2315     /* some clips/trailers may have unbalanced streams at the end,
2316      * so send EOS on shorter stream to prevent stalling others */
2317
2318     /* do not mess with EOS if SEGMENT seeking */
2319     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
2320       continue;
2321
2322     if (demux->pullbased) {
2323       /* loop mode is sample time based */
2324       if (stream->time_position != -1)
2325         continue;
2326     } else {
2327       /* push mode is byte position based */
2328       if (stream->samples[stream->n_samples - 1].offset >= demux->offset)
2329         continue;
2330     }
2331
2332     if (stream->sent_eos)
2333       continue;
2334
2335     /* only act if some gap */
2336     end_time = stream->segments[stream->n_segments - 1].stop_time;
2337     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
2338         ", stream end: %" GST_TIME_FORMAT,
2339         GST_TIME_ARGS (demux->segment.last_stop), GST_TIME_ARGS (end_time));
2340     if (end_time + 2 * GST_SECOND < demux->segment.last_stop) {
2341       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
2342           GST_PAD_NAME (stream->pad));
2343       stream->sent_eos = TRUE;
2344       gst_pad_push_event (stream->pad, gst_event_new_eos ());
2345     }
2346   }
2347 }
2348
2349 /* UNEXPECTED and NOT_LINKED need to be combined. This means that we return:
2350  *  
2351  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
2352  *  GST_FLOW_UNEXPECTED: when all pads UNEXPECTED or NOT_LINKED.
2353  */
2354 static GstFlowReturn
2355 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
2356     GstFlowReturn ret)
2357 {
2358   gint i;
2359   gboolean unexpected = FALSE, not_linked = TRUE;
2360
2361   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
2362
2363   /* store the value */
2364   stream->last_ret = ret;
2365
2366   for (i = 0; i < demux->n_streams; i++) {
2367     QtDemuxStream *ostream = demux->streams[i];
2368
2369     ret = ostream->last_ret;
2370
2371     /* no unexpected or unlinked, return */
2372     if (G_LIKELY (ret != GST_FLOW_UNEXPECTED && ret != GST_FLOW_NOT_LINKED))
2373       goto done;
2374
2375     /* we check to see if we have at least 1 unexpected or all unlinked */
2376     unexpected |= (ret == GST_FLOW_UNEXPECTED);
2377     not_linked &= (ret == GST_FLOW_NOT_LINKED);
2378   }
2379
2380   /* when we get here, we all have unlinked or unexpected */
2381   if (not_linked)
2382     ret = GST_FLOW_NOT_LINKED;
2383   else if (unexpected)
2384     ret = GST_FLOW_UNEXPECTED;
2385 done:
2386   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
2387   return ret;
2388 }
2389
2390 /* the input buffer metadata must be writable. Returns NULL when the buffer is
2391  * completely cliped */
2392 static GstBuffer *
2393 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
2394     GstBuffer * buf)
2395 {
2396   gint64 start, stop, cstart, cstop, diff;
2397   GstClockTime timestamp = GST_CLOCK_TIME_NONE, duration = GST_CLOCK_TIME_NONE;
2398   guint8 *data;
2399   guint size;
2400   gint num_rate, denom_rate;
2401   gint frame_size;
2402   gboolean clip_data;
2403
2404   data = GST_BUFFER_DATA (buf);
2405   size = GST_BUFFER_SIZE (buf);
2406
2407   /* depending on the type, setup the clip parameters */
2408   if (stream->subtype == FOURCC_soun) {
2409     frame_size = stream->bytes_per_frame;
2410     num_rate = GST_SECOND;
2411     denom_rate = (gint) stream->rate;
2412     clip_data = TRUE;
2413   } else if (stream->subtype == FOURCC_vide) {
2414     frame_size = size;
2415     num_rate = stream->fps_n;
2416     denom_rate = stream->fps_d;
2417     clip_data = FALSE;
2418   } else
2419     goto wrong_type;
2420
2421   /* we can only clip if we have a valid timestamp */
2422   timestamp = GST_BUFFER_TIMESTAMP (buf);
2423   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (timestamp)))
2424     goto no_timestamp;
2425
2426   if (G_LIKELY (GST_BUFFER_DURATION_IS_VALID (buf))) {
2427     duration = GST_BUFFER_DURATION (buf);
2428   } else {
2429     duration =
2430         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
2431   }
2432
2433   start = timestamp;
2434   stop = start + duration;
2435
2436   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
2437               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
2438     goto clipped;
2439
2440   /* see if some clipping happened */
2441   diff = cstart - start;
2442   if (diff > 0) {
2443     timestamp = cstart;
2444     duration -= diff;
2445
2446     if (clip_data) {
2447       /* bring clipped time to samples and to bytes */
2448       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
2449       diff *= frame_size;
2450
2451       GST_DEBUG_OBJECT (qtdemux,
2452           "clipping start to %" GST_TIME_FORMAT " %"
2453           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
2454
2455       data += diff;
2456       size -= diff;
2457     }
2458   }
2459   diff = stop - cstop;
2460   if (diff > 0) {
2461     duration -= diff;
2462
2463     if (clip_data) {
2464       /* bring clipped time to samples and then to bytes */
2465       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
2466       diff *= frame_size;
2467       GST_DEBUG_OBJECT (qtdemux,
2468           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
2469           " bytes", GST_TIME_ARGS (cstop), diff);
2470       size -= diff;
2471     }
2472   }
2473
2474   GST_BUFFER_TIMESTAMP (buf) = timestamp;
2475   GST_BUFFER_DURATION (buf) = duration;
2476   GST_BUFFER_SIZE (buf) = size;
2477   GST_BUFFER_DATA (buf) = data;
2478
2479   return buf;
2480
2481   /* dropped buffer */
2482 wrong_type:
2483   {
2484     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
2485     return buf;
2486   }
2487 no_timestamp:
2488   {
2489     GST_DEBUG_OBJECT (qtdemux, "no timestamp on buffer");
2490     return buf;
2491   }
2492 clipped:
2493   {
2494     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
2495     gst_buffer_unref (buf);
2496     return NULL;
2497   }
2498 }
2499
2500 /* the input buffer metadata must be writable,
2501  * but time/duration etc not yet set and need not be preserved */
2502 static GstBuffer *
2503 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
2504     GstBuffer * buf)
2505 {
2506   guint8 *data;
2507   guint size, nsize = 0;
2508   gchar *str;
2509
2510   data = GST_BUFFER_DATA (buf);
2511   size = GST_BUFFER_SIZE (buf);
2512
2513   /* not many cases for now */
2514   if (G_UNLIKELY (stream->fourcc == FOURCC_mp4s)) {
2515     /* send a one time dvd clut event */
2516     if (stream->pending_event && stream->pad)
2517       gst_pad_push_event (stream->pad, stream->pending_event);
2518     stream->pending_event = NULL;
2519     /* no further processing needed */
2520     stream->need_process = FALSE;
2521   }
2522
2523   if (G_UNLIKELY (stream->subtype != FOURCC_text)) {
2524     return buf;
2525   }
2526
2527   if (G_LIKELY (size >= 2)) {
2528     nsize = GST_READ_UINT16_BE (data);
2529     nsize = MIN (nsize, size - 2);
2530   }
2531
2532   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%d", nsize, size);
2533
2534   /* takes care of UTF-8 validation or UTF-16 recognition,
2535    * no other encoding expected */
2536   str = gst_tag_freeform_string_to_utf8 ((gchar *) data + 2, nsize, NULL);
2537   if (str) {
2538     gst_buffer_unref (buf);
2539     buf = gst_buffer_new ();
2540     GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = (guint8 *) str;
2541     GST_BUFFER_SIZE (buf) = strlen (str);
2542   } else {
2543     /* may be 0-size subtitle, which is also sent to keep pipeline going */
2544     GST_BUFFER_DATA (buf) = data + 2;
2545     GST_BUFFER_SIZE (buf) = nsize;
2546   }
2547
2548   /* FIXME ? convert optional subsequent style info to markup */
2549
2550   return buf;
2551 }
2552
2553 /* Sets a buffer's attributes properly and pushes it downstream.
2554  * Also checks for additional actions and custom processing that may
2555  * need to be done first.
2556  */
2557 static gboolean
2558 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
2559     QtDemuxStream * stream, GstBuffer * buf,
2560     guint64 timestamp, guint64 duration, gboolean keyframe, guint64 position,
2561     guint64 byte_position)
2562 {
2563   GstFlowReturn ret = GST_FLOW_OK;
2564
2565   if (G_UNLIKELY (stream->fourcc == FOURCC_rtsp)) {
2566     GstMessage *m;
2567     gchar *url;
2568
2569     url = g_strndup ((gchar *) GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
2570
2571     /* we have RTSP redirect now */
2572     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
2573         gst_structure_new ("redirect",
2574             "new-location", G_TYPE_STRING, url, NULL));
2575     g_free (url);
2576
2577     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
2578   }
2579
2580   /* position reporting */
2581   if (qtdemux->segment.rate >= 0) {
2582     gst_segment_set_last_stop (&qtdemux->segment, GST_FORMAT_TIME, position);
2583     gst_qtdemux_sync_streams (qtdemux);
2584   }
2585
2586   if (G_UNLIKELY (!stream->pad)) {
2587     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
2588     gst_buffer_unref (buf);
2589     goto exit;
2590   }
2591
2592   /* send out pending buffers */
2593   while (stream->buffers) {
2594     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
2595
2596     if (G_UNLIKELY (stream->discont)) {
2597       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
2598       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
2599       stream->discont = FALSE;
2600     }
2601     gst_buffer_set_caps (buffer, stream->caps);
2602
2603     gst_pad_push (stream->pad, buffer);
2604
2605     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2606   }
2607
2608   /* we're going to modify the metadata */
2609   buf = gst_buffer_make_metadata_writable (buf);
2610
2611   if (G_UNLIKELY (stream->need_process))
2612     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
2613
2614   GST_BUFFER_TIMESTAMP (buf) = timestamp;
2615   GST_BUFFER_DURATION (buf) = duration;
2616   GST_BUFFER_OFFSET (buf) = -1;
2617   GST_BUFFER_OFFSET_END (buf) = -1;
2618
2619   if (G_UNLIKELY (stream->padding)) {
2620     GST_BUFFER_DATA (buf) += stream->padding;
2621     GST_BUFFER_SIZE (buf) -= stream->padding;
2622   }
2623
2624   if (G_UNLIKELY (qtdemux->element_index)) {
2625     GstClockTime stream_time;
2626
2627     stream_time =
2628         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
2629         timestamp);
2630     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
2631       GST_LOG_OBJECT (qtdemux,
2632           "adding association %" GST_TIME_FORMAT "-> %"
2633           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
2634       gst_index_add_association (qtdemux->element_index,
2635           qtdemux->index_id,
2636           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
2637           GST_ASSOCIATION_FLAG_NONE, GST_FORMAT_TIME, stream_time,
2638           GST_FORMAT_BYTES, byte_position, NULL);
2639     }
2640   }
2641
2642   if (stream->need_clip)
2643     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
2644
2645   if (G_UNLIKELY (buf == NULL))
2646     goto exit;
2647
2648   if (G_UNLIKELY (stream->discont)) {
2649     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
2650     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
2651     stream->discont = FALSE;
2652   }
2653
2654   if (!keyframe)
2655     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
2656
2657   gst_buffer_set_caps (buf, stream->caps);
2658
2659   GST_LOG_OBJECT (qtdemux,
2660       "Pushing buffer with time %" GST_TIME_FORMAT ", duration %"
2661       GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
2662       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_PAD_NAME (stream->pad));
2663
2664   ret = gst_pad_push (stream->pad, buf);
2665
2666 exit:
2667   return ret;
2668 }
2669
2670 static GstFlowReturn
2671 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
2672 {
2673   GstFlowReturn ret = GST_FLOW_OK;
2674   GstBuffer *buf = NULL;
2675   QtDemuxStream *stream;
2676   guint64 min_time;
2677   guint64 offset = 0;
2678   guint64 timestamp = GST_CLOCK_TIME_NONE;
2679   guint64 duration = 0;
2680   gboolean keyframe = FALSE;
2681   guint size = 0;
2682   gint index;
2683   gint i;
2684
2685   gst_qtdemux_push_pending_newsegment (qtdemux);
2686
2687   /* Figure out the next stream sample to output, min_time is expressed in
2688    * global time and runs over the edit list segments. */
2689   min_time = G_MAXUINT64;
2690   index = -1;
2691   for (i = 0; i < qtdemux->n_streams; i++) {
2692     guint64 position;
2693
2694     stream = qtdemux->streams[i];
2695     position = stream->time_position;
2696
2697     /* position of -1 is EOS */
2698     if (position != -1 && position < min_time) {
2699       min_time = position;
2700       index = i;
2701     }
2702   }
2703   /* all are EOS */
2704   if (G_UNLIKELY (index == -1)) {
2705     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
2706     goto eos;
2707   }
2708
2709   /* check for segment end */
2710   if (G_UNLIKELY (qtdemux->segment.stop != -1
2711           && qtdemux->segment.stop < min_time)) {
2712     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
2713     goto eos;
2714   }
2715
2716   stream = qtdemux->streams[index];
2717
2718   /* fetch info for the current sample of this stream */
2719   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &offset,
2720               &size, &timestamp, &duration, &keyframe)))
2721     goto eos_stream;
2722
2723   GST_LOG_OBJECT (qtdemux,
2724       "pushing from stream %d, offset %" G_GUINT64_FORMAT
2725       ", size %d, timestamp=%" GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT,
2726       index, offset, size, GST_TIME_ARGS (timestamp), GST_TIME_ARGS (duration));
2727
2728   /* hmm, empty sample, skip and move to next sample */
2729   if (G_UNLIKELY (size <= 0))
2730     goto next;
2731
2732   /* last pushed sample was out of boundary, goto next sample */
2733   if (G_UNLIKELY (stream->last_ret == GST_FLOW_UNEXPECTED))
2734     goto next;
2735
2736   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
2737       offset);
2738
2739   ret = gst_qtdemux_pull_atom (qtdemux, offset, size, &buf);
2740   if (G_UNLIKELY (ret != GST_FLOW_OK))
2741     goto beach;
2742
2743   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
2744       timestamp, duration, keyframe, min_time, offset);
2745
2746   /* combine flows */
2747   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
2748   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
2749    * we have no more data for the pad to push */
2750   if (ret == GST_FLOW_UNEXPECTED)
2751     ret = GST_FLOW_OK;
2752
2753 next:
2754   gst_qtdemux_advance_sample (qtdemux, stream);
2755
2756 beach:
2757   return ret;
2758
2759   /* special cases */
2760 eos:
2761   {
2762     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
2763     ret = GST_FLOW_UNEXPECTED;
2764     goto beach;
2765   }
2766 eos_stream:
2767   {
2768     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
2769     /* EOS will be raised if all are EOS */
2770     ret = GST_FLOW_OK;
2771     goto beach;
2772   }
2773 }
2774
2775 static void
2776 gst_qtdemux_loop (GstPad * pad)
2777 {
2778   GstQTDemux *qtdemux;
2779   guint64 cur_offset;
2780   GstFlowReturn ret;
2781
2782   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
2783
2784   cur_offset = qtdemux->offset;
2785   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %d",
2786       cur_offset, qtdemux->state);
2787
2788   switch (qtdemux->state) {
2789     case QTDEMUX_STATE_INITIAL:
2790     case QTDEMUX_STATE_HEADER:
2791       ret = gst_qtdemux_loop_state_header (qtdemux);
2792       break;
2793     case QTDEMUX_STATE_MOVIE:
2794       ret = gst_qtdemux_loop_state_movie (qtdemux);
2795       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_UNEXPECTED) {
2796         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
2797       }
2798       break;
2799     default:
2800       /* ouch */
2801       goto invalid_state;
2802   }
2803
2804   /* if something went wrong, pause */
2805   if (ret != GST_FLOW_OK)
2806     goto pause;
2807
2808 done:
2809   gst_object_unref (qtdemux);
2810   return;
2811
2812   /* ERRORS */
2813 invalid_state:
2814   {
2815     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
2816         (NULL), ("streaming stopped, invalid state"));
2817     qtdemux->segment_running = FALSE;
2818     gst_pad_pause_task (pad);
2819     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
2820     goto done;
2821   }
2822 pause:
2823   {
2824     const gchar *reason = gst_flow_get_name (ret);
2825
2826     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
2827
2828     qtdemux->segment_running = FALSE;
2829     gst_pad_pause_task (pad);
2830
2831     /* fatal errors need special actions */
2832     if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) {
2833       /* check EOS */
2834       if (ret == GST_FLOW_UNEXPECTED) {
2835         if (qtdemux->n_streams == 0) {
2836           /* we have no streams, post an error */
2837           GST_ELEMENT_ERROR (qtdemux, STREAM, DECODE,
2838               (_("This file contains no playable streams.")),
2839               ("no known streams found"));
2840         }
2841         if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
2842           gint64 stop;
2843
2844           /* FIXME: I am not sure this is the right fix. If the sinks are
2845            * supposed to detect the segment is complete and accumulate 
2846            * automatically, it does not seem to work here. Need more work */
2847           qtdemux->segment_running = TRUE;
2848
2849           if ((stop = qtdemux->segment.stop) == -1)
2850             stop = qtdemux->segment.duration;
2851
2852           if (qtdemux->segment.rate >= 0) {
2853             GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
2854             gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
2855                 gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
2856                     GST_FORMAT_TIME, stop));
2857           } else {
2858             /*  For Reverse Playback */
2859             GST_LOG_OBJECT (qtdemux,
2860                 "Sending segment done, at start of segment");
2861             gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
2862                 gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
2863                     GST_FORMAT_TIME, qtdemux->segment.start));
2864           }
2865         } else {
2866           GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
2867           gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
2868         }
2869       } else {
2870         GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
2871             (NULL), ("streaming stopped, reason %s", reason));
2872         gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
2873       }
2874     }
2875     goto done;
2876   }
2877 }
2878
2879 /*
2880  * next_entry_size
2881  *
2882  * Returns the size of the first entry at the current offset.
2883  * If -1, there are none (which means EOS or empty file).
2884  */
2885 static guint64
2886 next_entry_size (GstQTDemux * demux)
2887 {
2888   QtDemuxStream *stream;
2889   int i;
2890   int smallidx = -1;
2891   guint64 smalloffs = (guint64) - 1;
2892   QtDemuxSample *sample;
2893
2894   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
2895       demux->offset);
2896
2897   for (i = 0; i < demux->n_streams; i++) {
2898     stream = demux->streams[i];
2899
2900     if (stream->sample_index == -1)
2901       stream->sample_index = 0;
2902
2903     if (stream->sample_index >= stream->n_samples) {
2904       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
2905       continue;
2906     }
2907
2908     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
2909       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
2910           stream->sample_index);
2911       return -1;
2912     }
2913
2914     sample = &stream->samples[stream->sample_index];
2915
2916     GST_LOG_OBJECT (demux,
2917         "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
2918         " / size:%" G_GUINT32_FORMAT ")", i, stream->sample_index,
2919         sample->offset, sample->size);
2920
2921     if (((smalloffs == -1)
2922             || (sample->offset < smalloffs)) && (sample->size)) {
2923       smallidx = i;
2924       smalloffs = sample->offset;
2925     }
2926   }
2927
2928   GST_LOG_OBJECT (demux,
2929       "stream %d offset %" G_GUINT64_FORMAT " demux->offset :%"
2930       G_GUINT64_FORMAT, smallidx, smalloffs, demux->offset);
2931
2932   if (smallidx == -1)
2933     return -1;
2934
2935   stream = demux->streams[smallidx];
2936   sample = &stream->samples[stream->sample_index];
2937
2938   if (sample->offset >= demux->offset) {
2939     demux->todrop = sample->offset - demux->offset;
2940     return sample->size + demux->todrop;
2941   }
2942
2943   GST_DEBUG_OBJECT (demux,
2944       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
2945   return -1;
2946 }
2947
2948 static void
2949 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
2950 {
2951   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
2952
2953   gst_element_post_message (GST_ELEMENT_CAST (demux),
2954       gst_message_new_element (GST_OBJECT_CAST (demux),
2955           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
2956 }
2957
2958 static gboolean
2959 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
2960 {
2961   GstEvent *event;
2962   gboolean res = 0;
2963
2964   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
2965
2966   event =
2967       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
2968       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
2969       GST_SEEK_TYPE_NONE, -1);
2970
2971   res = gst_pad_push_event (demux->sinkpad, event);
2972
2973   return res;
2974 }
2975
2976 /* FIXME, unverified after edit list updates */
2977 static GstFlowReturn
2978 gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
2979 {
2980   GstQTDemux *demux;
2981   GstFlowReturn ret = GST_FLOW_OK;
2982
2983   demux = GST_QTDEMUX (gst_pad_get_parent (sinkpad));
2984
2985   gst_adapter_push (demux->adapter, inbuf);
2986
2987   /* we never really mean to buffer that much */
2988   if (demux->neededbytes == -1)
2989     goto eos;
2990
2991   GST_DEBUG_OBJECT (demux, "pushing in inbuf %p, neededbytes:%u, available:%u",
2992       inbuf, demux->neededbytes, gst_adapter_available (demux->adapter));
2993
2994   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
2995       (ret == GST_FLOW_OK)) {
2996
2997     GST_DEBUG_OBJECT (demux,
2998         "state:%d , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT,
2999         demux->state, demux->neededbytes, demux->offset);
3000
3001     switch (demux->state) {
3002       case QTDEMUX_STATE_INITIAL:{
3003         const guint8 *data;
3004         guint32 fourcc;
3005         guint64 size;
3006
3007         /* prepare newsegment to send when streaming actually starts */
3008         if (!demux->pending_newsegment) {
3009           demux->pending_newsegment =
3010               gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
3011               0, GST_CLOCK_TIME_NONE, 0);
3012         }
3013
3014         data = gst_adapter_peek (demux->adapter, demux->neededbytes);
3015
3016         /* get fourcc/length, set neededbytes */
3017         extract_initial_length_and_fourcc ((guint8 *) data, &size, &fourcc);
3018         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
3019             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
3020         if (size == 0) {
3021           GST_ELEMENT_ERROR (demux, STREAM, DECODE,
3022               (_("This file is invalid and cannot be played.")),
3023               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
3024                   GST_FOURCC_ARGS (fourcc)));
3025           ret = GST_FLOW_ERROR;
3026           break;
3027         }
3028         if (fourcc == FOURCC_mdat) {
3029           if (demux->n_streams > 0) {
3030             /* we have the headers, start playback */
3031             demux->state = QTDEMUX_STATE_MOVIE;
3032             demux->neededbytes = next_entry_size (demux);
3033           } else {
3034             /* no headers yet, try to get them */
3035             guint bs;
3036             gboolean res;
3037             guint64 old, target;
3038
3039           buffer_data:
3040             old = demux->offset;
3041             target = old + size;
3042
3043             /* try to jump over the atom with a seek */
3044             res = qtdemux_seek_offset (demux, target);
3045
3046             if (res) {
3047               GST_DEBUG_OBJECT (demux, "seek success");
3048               /* remember the offset fo the first mdat so we can seek back to it
3049                * after we have the headers */
3050               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
3051                 demux->first_mdat = old;
3052                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
3053                     demux->first_mdat);
3054               }
3055               /* seek worked, continue reading */
3056               demux->offset = target;
3057               demux->neededbytes = 16;
3058               demux->state = QTDEMUX_STATE_INITIAL;
3059             } else {
3060               /* seek failed, need to buffer */
3061               demux->offset = old;
3062               GST_DEBUG_OBJECT (demux, "seek failed");
3063               /* there may be multiple mdat (or alike) buffers */
3064               /* sanity check */
3065               if (demux->mdatbuffer)
3066                 bs = GST_BUFFER_SIZE (demux->mdatbuffer);
3067               else
3068                 bs = 0;
3069               if (size + bs > 10 * (1 << 20))
3070                 goto no_moov;
3071               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
3072               demux->neededbytes = size;
3073               if (!demux->mdatbuffer)
3074                 demux->mdatoffset = demux->offset;
3075             }
3076           }
3077         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
3078           GST_ELEMENT_ERROR (demux, STREAM, DECODE,
3079               (_("This file is invalid and cannot be played.")),
3080               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
3081                   GST_FOURCC_ARGS (fourcc), size));
3082           ret = GST_FLOW_ERROR;
3083           break;
3084         } else {
3085           /* this means we already started buffering and still no moov header,
3086            * let's continue buffering everything till we get moov */
3087           if (demux->mdatbuffer && (fourcc != FOURCC_moov))
3088             goto buffer_data;
3089           demux->neededbytes = size;
3090           demux->state = QTDEMUX_STATE_HEADER;
3091         }
3092         break;
3093       }
3094       case QTDEMUX_STATE_HEADER:{
3095         const guint8 *data;
3096         guint32 fourcc;
3097
3098         GST_DEBUG_OBJECT (demux, "In header");
3099
3100         data = gst_adapter_peek (demux->adapter, demux->neededbytes);
3101
3102         /* parse the header */
3103         extract_initial_length_and_fourcc (data, NULL, &fourcc);
3104         if (fourcc == FOURCC_moov) {
3105           GST_DEBUG_OBJECT (demux, "Parsing [moov]");
3106
3107           qtdemux_parse_moov (demux, data, demux->neededbytes);
3108           qtdemux_node_dump (demux, demux->moov_node);
3109           qtdemux_parse_tree (demux);
3110
3111           g_node_destroy (demux->moov_node);
3112           demux->moov_node = NULL;
3113           GST_DEBUG_OBJECT (demux, "Finished parsing the header");
3114         } else if (fourcc == FOURCC_ftyp) {
3115           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
3116           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
3117         } else {
3118           GST_WARNING_OBJECT (demux,
3119               "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
3120               GST_FOURCC_ARGS (fourcc));
3121           /* Let's jump that one and go back to initial state */
3122         }
3123
3124         if (demux->mdatbuffer && demux->n_streams) {
3125           GstBuffer *buf;
3126
3127           /* the mdat was before the header */
3128           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
3129               demux->n_streams, demux->mdatbuffer);
3130           /* restore our adapter/offset view of things with upstream;
3131            * put preceding buffered data ahead of current moov data.
3132            * This should also handle evil mdat, moov, mdat cases and alike */
3133           buf = gst_adapter_take_buffer (demux->adapter,
3134               gst_adapter_available (demux->adapter));
3135           gst_adapter_clear (demux->adapter);
3136           gst_adapter_push (demux->adapter, demux->mdatbuffer);
3137           gst_adapter_push (demux->adapter, buf);
3138           demux->mdatbuffer = NULL;
3139           demux->offset = demux->mdatoffset;
3140           demux->neededbytes = next_entry_size (demux);
3141           demux->state = QTDEMUX_STATE_MOVIE;
3142         } else {
3143           GST_DEBUG_OBJECT (demux, "Carrying on normally");
3144           gst_adapter_flush (demux->adapter, demux->neededbytes);
3145
3146           if (demux->first_mdat != -1) {
3147             gboolean res;
3148
3149             /* we need to seek back */
3150             res = qtdemux_seek_offset (demux, demux->first_mdat);
3151             if (res) {
3152               demux->offset = demux->first_mdat;
3153             } else {
3154               GST_DEBUG_OBJECT (demux, "Seek back failed");
3155             }
3156           } else {
3157             demux->offset += demux->neededbytes;
3158           }
3159           demux->neededbytes = 16;
3160           demux->state = QTDEMUX_STATE_INITIAL;
3161         }
3162
3163         break;
3164       }
3165       case QTDEMUX_STATE_BUFFER_MDAT:{
3166         GstBuffer *buf;
3167
3168         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
3169             demux->offset);
3170         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
3171         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
3172             GST_FOURCC_ARGS (QT_FOURCC (GST_BUFFER_DATA (buf) + 4)));
3173         if (demux->mdatbuffer)
3174           demux->mdatbuffer = gst_buffer_join (demux->mdatbuffer, buf);
3175         else
3176           demux->mdatbuffer = buf;
3177         demux->offset += demux->neededbytes;
3178         demux->neededbytes = 16;
3179         demux->state = QTDEMUX_STATE_INITIAL;
3180         gst_qtdemux_post_progress (demux, 1, 1);
3181
3182         break;
3183       }
3184       case QTDEMUX_STATE_MOVIE:{
3185         GstBuffer *outbuf;
3186         QtDemuxStream *stream = NULL;
3187         QtDemuxSample *sample;
3188         int i = -1;
3189         guint64 timestamp, duration, position;
3190         gboolean keyframe;
3191
3192         GST_DEBUG_OBJECT (demux,
3193             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
3194
3195         if (demux->todrop) {
3196           GST_LOG_OBJECT (demux, "Dropping %d bytes", demux->todrop);
3197           gst_adapter_flush (demux->adapter, demux->todrop);
3198           demux->neededbytes -= demux->todrop;
3199           demux->offset += demux->todrop;
3200         }
3201
3202         /* first buffer? */
3203         /* initial newsegment sent here after having added pads,
3204          * possible others in sink_event */
3205         if (G_UNLIKELY (demux->pending_newsegment)) {
3206           gst_qtdemux_push_event (demux, demux->pending_newsegment);
3207           demux->pending_newsegment = NULL;
3208           /* clear to send tags on all streams */
3209           for (i = 0; i < demux->n_streams; i++) {
3210             gst_qtdemux_push_tags (demux, demux->streams[i]);
3211           }
3212         }
3213
3214         /* Figure out which stream this is packet belongs to */
3215         for (i = 0; i < demux->n_streams; i++) {
3216           stream = demux->streams[i];
3217           if (stream->sample_index >= stream->n_samples)
3218             continue;
3219           GST_LOG_OBJECT (demux,
3220               "Checking stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
3221               " / size:%d)", i, stream->sample_index,
3222               stream->samples[stream->sample_index].offset,
3223               stream->samples[stream->sample_index].size);
3224
3225           if (stream->samples[stream->sample_index].offset == demux->offset)
3226             break;
3227         }
3228
3229         if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
3230           goto unknown_stream;
3231
3232         /* Put data in a buffer, set timestamps, caps, ... */
3233         outbuf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
3234         GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
3235             GST_FOURCC_ARGS (stream->fourcc));
3236
3237         g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
3238
3239         sample = &stream->samples[stream->sample_index];
3240
3241         position = QTSAMPLE_DTS (stream, sample);
3242         timestamp = QTSAMPLE_PTS (stream, sample);
3243         duration = QTSAMPLE_DUR_DTS (stream, sample, position);
3244         keyframe = QTSAMPLE_KEYFRAME (stream, sample);
3245
3246         ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
3247             timestamp, duration, keyframe, position, demux->offset);
3248
3249         /* combine flows */
3250         ret = gst_qtdemux_combine_flows (demux, stream, ret);
3251
3252         stream->sample_index++;
3253
3254         /* update current offset and figure out size of next buffer */
3255         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
3256             demux->offset, demux->neededbytes);
3257         demux->offset += demux->neededbytes;
3258         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
3259             demux->offset);
3260
3261         if ((demux->neededbytes = next_entry_size (demux)) == -1)
3262           goto eos;
3263         break;
3264       }
3265       default:
3266         goto invalid_state;
3267     }
3268   }
3269
3270   /* when buffering movie data, at least show user something is happening */
3271   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
3272       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
3273     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
3274         demux->neededbytes);
3275   }
3276 done:
3277   gst_object_unref (demux);
3278
3279   return ret;
3280
3281   /* ERRORS */
3282 unknown_stream:
3283   {
3284     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
3285     ret = GST_FLOW_ERROR;
3286     goto done;
3287   }
3288 eos:
3289   {
3290     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
3291     ret = GST_FLOW_UNEXPECTED;
3292     goto done;
3293   }
3294 invalid_state:
3295   {
3296     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
3297         (NULL), ("qtdemuxer invalid state %d", demux->state));
3298     ret = GST_FLOW_ERROR;
3299     goto done;
3300   }
3301 no_moov:
3302   {
3303     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
3304         (NULL), ("no 'moov' atom within the first 10 MB"));
3305     ret = GST_FLOW_ERROR;
3306     goto done;
3307   }
3308 }
3309
3310 static gboolean
3311 qtdemux_sink_activate (GstPad * sinkpad)
3312 {
3313   if (gst_pad_check_pull_range (sinkpad))
3314     return gst_pad_activate_pull (sinkpad, TRUE);
3315   else
3316     return gst_pad_activate_push (sinkpad, TRUE);
3317 }
3318
3319 static gboolean
3320 qtdemux_sink_activate_pull (GstPad * sinkpad, gboolean active)
3321 {
3322   GstQTDemux *demux = GST_QTDEMUX (GST_PAD_PARENT (sinkpad));
3323
3324   if (active) {
3325     demux->pullbased = TRUE;
3326     demux->segment_running = TRUE;
3327     return gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
3328         sinkpad);
3329   } else {
3330     demux->segment_running = FALSE;
3331     return gst_pad_stop_task (sinkpad);
3332   }
3333 }
3334
3335 static gboolean
3336 qtdemux_sink_activate_push (GstPad * sinkpad, gboolean active)
3337 {
3338   GstQTDemux *demux = GST_QTDEMUX (GST_PAD_PARENT (sinkpad));
3339
3340   demux->pullbased = FALSE;
3341
3342   return TRUE;
3343 }
3344
3345 #ifdef HAVE_ZLIB
3346 static void *
3347 qtdemux_zalloc (void *opaque, unsigned int items, unsigned int size)
3348 {
3349   return g_malloc (items * size);
3350 }
3351
3352 static void
3353 qtdemux_zfree (void *opaque, void *addr)
3354 {
3355   g_free (addr);
3356 }
3357
3358 static void *
3359 qtdemux_inflate (void *z_buffer, guint z_length, guint length)
3360 {
3361   guint8 *buffer;
3362   z_stream *z;
3363   int ret;
3364
3365   z = g_new0 (z_stream, 1);
3366   z->zalloc = qtdemux_zalloc;
3367   z->zfree = qtdemux_zfree;
3368   z->opaque = NULL;
3369
3370   z->next_in = z_buffer;
3371   z->avail_in = z_length;
3372
3373   buffer = (guint8 *) g_malloc (length);
3374   ret = inflateInit (z);
3375   while (z->avail_in > 0) {
3376     if (z->avail_out == 0) {
3377       length += 1024;
3378       buffer = (guint8 *) g_realloc (buffer, length);
3379       z->next_out = buffer + z->total_out;
3380       z->avail_out = 1024;
3381     }
3382     ret = inflate (z, Z_SYNC_FLUSH);
3383     if (ret != Z_OK)
3384       break;
3385   }
3386   if (ret != Z_STREAM_END) {
3387     g_warning ("inflate() returned %d", ret);
3388   }
3389
3390   g_free (z);
3391   return buffer;
3392 }
3393 #endif /* HAVE_ZLIB */
3394
3395 static gboolean
3396 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
3397 {
3398   GNode *cmov;
3399
3400   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
3401
3402   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
3403   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
3404
3405   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
3406   if (cmov) {
3407     guint32 method;
3408     GNode *dcom;
3409     GNode *cmvd;
3410
3411     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
3412     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
3413     if (dcom == NULL || cmvd == NULL)
3414       goto invalid_compression;
3415
3416     method = QT_FOURCC ((guint8 *) dcom->data + 8);
3417     switch (method) {
3418 #ifdef HAVE_ZLIB
3419       case GST_MAKE_FOURCC ('z', 'l', 'i', 'b'):{
3420         guint uncompressed_length;
3421         guint compressed_length;
3422         guint8 *buf;
3423
3424         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
3425         compressed_length = QT_UINT32 ((guint8 *) cmvd->data + 4) - 12;
3426         GST_LOG ("length = %u", uncompressed_length);
3427
3428         buf =
3429             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
3430             compressed_length, uncompressed_length);
3431
3432         qtdemux->moov_node_compressed = qtdemux->moov_node;
3433         qtdemux->moov_node = g_node_new (buf);
3434
3435         qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
3436             uncompressed_length);
3437         break;
3438       }
3439 #endif /* HAVE_ZLIB */
3440       default:
3441         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
3442             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
3443         break;
3444     }
3445   }
3446   return TRUE;
3447
3448   /* ERRORS */
3449 invalid_compression:
3450   {
3451     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
3452     return FALSE;
3453   }
3454 }
3455
3456 static gboolean
3457 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
3458     const guint8 * end)
3459 {
3460   while (G_UNLIKELY (buf < end)) {
3461     GNode *child;
3462     guint32 len;
3463
3464     if (G_UNLIKELY (buf + 4 > end)) {
3465       GST_LOG_OBJECT (qtdemux, "buffer overrun");
3466       break;
3467     }
3468     len = QT_UINT32 (buf);
3469     if (G_UNLIKELY (len == 0)) {
3470       GST_LOG_OBJECT (qtdemux, "empty container");
3471       break;
3472     }
3473     if (G_UNLIKELY (len < 8)) {
3474       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
3475       break;
3476     }
3477     if (G_UNLIKELY (len > (end - buf))) {
3478       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
3479           (gint) (end - buf));
3480       break;
3481     }
3482
3483     child = g_node_new ((guint8 *) buf);
3484     g_node_append (node, child);
3485     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
3486     qtdemux_parse_node (qtdemux, child, buf, len);
3487
3488     buf += len;
3489   }
3490   return TRUE;
3491 }
3492
3493 static gboolean
3494 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
3495     GNode * xdxt)
3496 {
3497   int len = QT_UINT32 (xdxt->data);
3498   guint8 *buf = xdxt->data;
3499   guint8 *end = buf + len;
3500   GstBuffer *buffer;
3501
3502   /* skip size and type */
3503   buf += 8;
3504   end -= 8;
3505
3506   while (buf < end) {
3507     gint size;
3508     guint32 type;
3509
3510     size = QT_UINT32 (buf);
3511     type = QT_FOURCC (buf + 4);
3512
3513     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
3514
3515     if (buf + size > end || size <= 0)
3516       break;
3517
3518     buf += 8;
3519     size -= 8;
3520
3521     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
3522         GST_FOURCC_ARGS (type));
3523
3524     switch (type) {
3525       case FOURCC_tCtH:
3526         buffer = gst_buffer_new_and_alloc (size);
3527         memcpy (GST_BUFFER_DATA (buffer), buf, size);
3528         stream->buffers = g_slist_append (stream->buffers, buffer);
3529         GST_LOG_OBJECT (qtdemux, "parsing theora header");
3530         break;
3531       case FOURCC_tCt_:
3532         buffer = gst_buffer_new_and_alloc (size);
3533         memcpy (GST_BUFFER_DATA (buffer), buf, size);
3534         stream->buffers = g_slist_append (stream->buffers, buffer);
3535         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
3536         break;
3537       case FOURCC_tCtC:
3538         buffer = gst_buffer_new_and_alloc (size);
3539         memcpy (GST_BUFFER_DATA (buffer), buf, size);
3540         stream->buffers = g_slist_append (stream->buffers, buffer);
3541         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
3542         break;
3543       default:
3544         GST_WARNING_OBJECT (qtdemux,
3545             "unknown theora cookie %" GST_FOURCC_FORMAT,
3546             GST_FOURCC_ARGS (type));
3547         break;
3548     }
3549     buf += size;
3550   }
3551   return TRUE;
3552 }
3553
3554 static gboolean
3555 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
3556     guint length)
3557 {
3558   guint32 fourcc = 0;
3559   guint32 node_length = 0;
3560   const QtNodeType *type;
3561   const guint8 *end;
3562
3563   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
3564
3565   if (G_UNLIKELY (length < 8))
3566     goto not_enough_data;
3567
3568   node_length = QT_UINT32 (buffer);
3569   fourcc = QT_FOURCC (buffer + 4);
3570
3571   /* ignore empty nodes */
3572   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
3573     return TRUE;
3574
3575   type = qtdemux_type_get (fourcc);
3576
3577   end = buffer + length;
3578
3579   GST_LOG_OBJECT (qtdemux,
3580       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
3581       GST_FOURCC_ARGS (fourcc), node_length, type->name);
3582
3583   if (node_length > length)
3584     goto broken_atom_size;
3585
3586   if (type->flags & QT_FLAG_CONTAINER) {
3587     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
3588   } else {
3589     switch (fourcc) {
3590       case FOURCC_stsd:
3591       {
3592         if (node_length < 20) {
3593           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
3594           break;
3595         }
3596         GST_DEBUG_OBJECT (qtdemux,
3597             "parsing stsd (sample table, sample description) atom");
3598         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
3599         break;
3600       }
3601       case FOURCC_mp4a:
3602       {
3603         guint32 version;
3604         guint32 offset;
3605
3606         /* There are two things we might encounter here: a true mp4a atom, and
3607            an mp4a entry in an stsd atom. The latter is what we're interested
3608            in, and it looks like an atom, but isn't really one. The true mp4a
3609            atom is short, so we detect it based on length here. */
3610         if (length < 20) {
3611           GST_LOG_OBJECT (qtdemux, "skipping small mp4a box");
3612           break;
3613         }
3614
3615         /* 'version' here is the sound sample description version. Types 0 and
3616            1 are documented in the QTFF reference, but type 2 is not: it's
3617            described in Apple header files instead (struct SoundDescriptionV2
3618            in Movies.h) */
3619         version = QT_UINT16 (buffer + 16);
3620
3621         GST_DEBUG_OBJECT (qtdemux, "mp4a version 0x%08x", version);
3622
3623         /* parse any esds descriptors */
3624         switch (version) {
3625           case 0:
3626             offset = 0x24;
3627             break;
3628           case 1:
3629             offset = 0x34;
3630             break;
3631           case 2:
3632             offset = 0x48;
3633             break;
3634           default:
3635             GST_WARNING_OBJECT (qtdemux, "unhandled mp4a version 0x%08x",
3636                 version);
3637             offset = 0;
3638             break;
3639         }
3640         if (offset)
3641           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
3642         break;
3643       }
3644       case FOURCC_mp4v:
3645       {
3646         const guint8 *buf;
3647         guint32 version;
3648         int tlen;
3649
3650         GST_DEBUG_OBJECT (qtdemux, "parsing in mp4v");
3651         version = QT_UINT32 (buffer + 16);
3652         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
3653         if (1 || version == 0x00000000) {
3654           buf = buffer + 0x32;
3655
3656           /* FIXME Quicktime uses PASCAL string while
3657            * the iso format uses C strings. Check the file
3658            * type before attempting to parse the string here. */
3659           tlen = QT_UINT8 (buf);
3660           GST_DEBUG_OBJECT (qtdemux, "tlen = %d", tlen);
3661           buf++;
3662           GST_DEBUG_OBJECT (qtdemux, "string = %.*s", tlen, (char *) buf);
3663           /* the string has a reserved space of 32 bytes so skip
3664            * the remaining 31 */
3665           buf += 31;
3666           buf += 4;             /* and 4 bytes reserved */
3667
3668           GST_MEMDUMP_OBJECT (qtdemux, "mp4v", buf, end - buf);
3669
3670           qtdemux_parse_container (qtdemux, node, buf, end);
3671         }
3672         break;
3673       }
3674       case FOURCC_avc1:
3675       {
3676         GST_MEMDUMP_OBJECT (qtdemux, "avc1", buffer, end - buffer);
3677         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
3678         break;
3679       }
3680       case FOURCC_mjp2:
3681       {
3682         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
3683         break;
3684       }
3685       case FOURCC_meta:
3686       {
3687         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
3688         qtdemux_parse_container (qtdemux, node, buffer + 12, end);
3689         break;
3690       }
3691       case FOURCC_XiTh:
3692       {
3693         guint32 version;
3694         guint32 offset;
3695
3696         version = QT_UINT32 (buffer + 12);
3697         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
3698
3699         switch (version) {
3700           case 0x00000001:
3701             offset = 0x62;
3702             break;
3703           default:
3704             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
3705             offset = 0;
3706             break;
3707         }
3708         if (offset)
3709           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
3710         break;
3711       }
3712       case FOURCC_in24:
3713       {
3714         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
3715         break;
3716       }
3717       default:
3718         if (!strcmp (type->name, "unknown"))
3719           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
3720         break;
3721     }
3722   }
3723   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT,
3724       GST_FOURCC_ARGS (fourcc));
3725   return TRUE;
3726
3727 /* ERRORS */
3728 not_enough_data:
3729   {
3730     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
3731         (_("This file is corrupt and cannot be played.")),
3732         ("Not enough data for an atom header, got only %u bytes", length));
3733     return FALSE;
3734   }
3735 broken_atom_size:
3736   {
3737     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
3738         (_("This file is corrupt and cannot be played.")),
3739         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
3740             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
3741             length));
3742     return FALSE;
3743   }
3744 }
3745
3746 static GNode *
3747 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
3748 {
3749   GNode *child;
3750   guint8 *buffer;
3751   guint32 child_fourcc;
3752
3753   for (child = g_node_first_child (node); child;
3754       child = g_node_next_sibling (child)) {
3755     buffer = (guint8 *) child->data;
3756
3757     child_fourcc = QT_FOURCC (buffer + 4);
3758
3759     if (G_UNLIKELY (child_fourcc == fourcc)) {
3760       return child;
3761     }
3762   }
3763   return NULL;
3764 }
3765
3766 static GNode *
3767 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
3768     GstByteReader * parser)
3769 {
3770   GNode *child;
3771   guint8 *buffer;
3772   guint32 child_fourcc, child_len;
3773
3774   for (child = g_node_first_child (node); child;
3775       child = g_node_next_sibling (child)) {
3776     buffer = (guint8 *) child->data;
3777
3778     child_len = QT_UINT32 (buffer);
3779     child_fourcc = QT_FOURCC (buffer + 4);
3780
3781     if (G_UNLIKELY (child_fourcc == fourcc)) {
3782       if (G_UNLIKELY (child_len < (4 + 4)))
3783         return NULL;
3784       /* FIXME: must verify if atom length < parent atom length */
3785       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
3786       return child;
3787     }
3788   }
3789   return NULL;
3790 }
3791
3792 static GNode *
3793 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
3794 {
3795   GNode *child;
3796   guint8 *buffer;
3797   guint32 child_fourcc;
3798
3799   for (child = g_node_next_sibling (node); child;
3800       child = g_node_next_sibling (child)) {
3801     buffer = (guint8 *) child->data;
3802
3803     child_fourcc = QT_FOURCC (buffer + 4);
3804
3805     if (child_fourcc == fourcc) {
3806       return child;
3807     }
3808   }
3809   return NULL;
3810 }
3811
3812 static gboolean
3813 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
3814     QtDemuxStream * stream, GstTagList * list)
3815 {
3816   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
3817     goto too_many_streams;
3818
3819   /* consistent default for push based mode */
3820   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
3821   gst_segment_set_newsegment (&stream->segment, FALSE, 1.0, GST_FORMAT_TIME,
3822       0, GST_CLOCK_TIME_NONE, 0);
3823
3824   if (stream->subtype == FOURCC_vide) {
3825     gchar *name = g_strdup_printf ("video_%02d", qtdemux->n_video_streams);
3826
3827     stream->pad =
3828         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
3829     g_free (name);
3830
3831     /* fps is calculated base on the duration of the first frames since
3832      * qt does not have a fixed framerate. */
3833     if ((stream->n_samples == 1) && (stream->min_duration == 0)) {
3834       /* still frame */
3835       stream->fps_n = 0;
3836       stream->fps_d = 1;
3837     } else {
3838       stream->fps_n = stream->timescale;
3839       if (stream->min_duration == 0)
3840         stream->fps_d = 1;
3841       else
3842         stream->fps_d = stream->min_duration;
3843     }
3844
3845     if (stream->caps) {
3846       gboolean gray;
3847       gint depth, palette_count;
3848       const guint32 *palette_data = NULL;
3849
3850       gst_caps_set_simple (stream->caps,
3851           "width", G_TYPE_INT, stream->width,
3852           "height", G_TYPE_INT, stream->height,
3853           "framerate", GST_TYPE_FRACTION, stream->fps_n, stream->fps_d, NULL);
3854
3855       /* iso files:
3856        * calculate pixel-aspect-ratio using display width and height */
3857       if (qtdemux->major_brand != FOURCC_qt__) {
3858         GST_DEBUG_OBJECT (qtdemux,
3859             "video size %dx%d, target display size %dx%d", stream->width,
3860             stream->height, stream->display_width, stream->display_height);
3861
3862         if (stream->display_width > 0 && stream->display_height > 0 &&
3863             stream->width > 0 && stream->height > 0) {
3864           gint n, d;
3865
3866           /* calculate the pixel aspect ratio using the display and pixel w/h */
3867           n = stream->display_width * stream->height;
3868           d = stream->display_height * stream->width;
3869           if (n != d) {
3870             GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
3871             gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
3872                 GST_TYPE_FRACTION, n, d, NULL);
3873           }
3874         }
3875       }
3876
3877       /* qt file might have pasp atom */
3878       if (stream->par_w > 0 && stream->par_h > 0) {
3879         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", stream->par_w, stream->par_h);
3880         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
3881             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
3882       }
3883
3884       depth = stream->bits_per_sample;
3885
3886       /* more than 32 bits means grayscale */
3887       gray = (depth > 32);
3888       /* low 32 bits specify the depth  */
3889       depth &= 0x1F;
3890
3891       /* different number of palette entries is determined by depth. */
3892       palette_count = 0;
3893       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
3894         palette_count = (1 << depth);
3895
3896       switch (palette_count) {
3897         case 0:
3898           break;
3899         case 2:
3900           palette_data = ff_qt_default_palette_2;
3901           break;
3902         case 4:
3903           palette_data = ff_qt_default_palette_4;
3904           break;
3905         case 16:
3906           if (gray)
3907             palette_data = ff_qt_grayscale_palette_16;
3908           else
3909             palette_data = ff_qt_default_palette_16;
3910           break;
3911         case 256:
3912           if (gray)
3913             palette_data = ff_qt_grayscale_palette_256;
3914           else
3915             palette_data = ff_qt_default_palette_256;
3916           break;
3917         default:
3918           GST_ELEMENT_WARNING (qtdemux, STREAM, DECODE,
3919               (_("The video in this file might not play correctly.")),
3920               ("unsupported palette depth %d", depth));
3921           break;
3922       }
3923       if (palette_data) {
3924         GstBuffer *palette;
3925
3926         /* make sure it's not writable. We leave MALLOCDATA to NULL so that we
3927          * don't free any of the buffer data. */
3928         palette = gst_buffer_new ();
3929         GST_BUFFER_FLAG_SET (palette, GST_BUFFER_FLAG_READONLY);
3930         GST_BUFFER_DATA (palette) = (guint8 *) palette_data;
3931         GST_BUFFER_SIZE (palette) = sizeof (guint32) * palette_count;
3932
3933         gst_caps_set_simple (stream->caps, "palette_data",
3934             GST_TYPE_BUFFER, palette, NULL);
3935         gst_buffer_unref (palette);
3936       } else if (palette_count != 0) {
3937         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
3938             (NULL), ("Unsupported palette depth %d. Ignoring stream.", depth));
3939
3940         gst_object_unref (stream->pad);
3941         stream->pad = NULL;
3942       }
3943     }
3944     qtdemux->n_video_streams++;
3945   } else if (stream->subtype == FOURCC_soun) {
3946     gchar *name = g_strdup_printf ("audio_%02d", qtdemux->n_audio_streams);
3947
3948     stream->pad =
3949         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
3950     g_free (name);
3951     if (stream->caps) {
3952       gst_caps_set_simple (stream->caps,
3953           "rate", G_TYPE_INT, (int) stream->rate,
3954           "channels", G_TYPE_INT, stream->n_channels, NULL);
3955     }
3956     qtdemux->n_audio_streams++;
3957   } else if (stream->subtype == FOURCC_strm) {
3958     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
3959   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text) {
3960     gchar *name = g_strdup_printf ("subtitle_%02d", qtdemux->n_sub_streams);
3961
3962     stream->pad =
3963         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
3964     g_free (name);
3965     qtdemux->n_sub_streams++;
3966   } else {
3967     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
3968     goto done;
3969   }
3970
3971   qtdemux->streams[qtdemux->n_streams] = stream;
3972   qtdemux->n_streams++;
3973   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
3974
3975   if (stream->pad) {
3976     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
3977
3978     gst_pad_use_fixed_caps (stream->pad);
3979     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
3980     gst_pad_set_query_type_function (stream->pad,
3981         gst_qtdemux_get_src_query_types);
3982     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
3983
3984     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT, stream->caps);
3985     gst_pad_set_caps (stream->pad, stream->caps);
3986
3987     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
3988         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
3989     gst_pad_set_active (stream->pad, TRUE);
3990     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
3991     if (stream->pending_tags)
3992       gst_tag_list_free (stream->pending_tags);
3993     stream->pending_tags = list;
3994     if (list) {
3995       /* post now, send event on pad later */
3996       GST_DEBUG_OBJECT (qtdemux, "Posting tags %" GST_PTR_FORMAT, list);
3997       gst_element_post_message (GST_ELEMENT (qtdemux),
3998           gst_message_new_tag_full (GST_OBJECT (qtdemux), stream->pad,
3999               gst_tag_list_copy (list)));
4000     }
4001     /* global tags go on each pad anyway */
4002     stream->send_global_tags = TRUE;
4003   }
4004 done:
4005   return TRUE;
4006
4007 too_many_streams:
4008   {
4009     GST_ELEMENT_WARNING (qtdemux, STREAM, DECODE,
4010         (_("This file contains too many streams. Only playing first %d"),
4011             GST_QTDEMUX_MAX_STREAMS), (NULL));
4012     return TRUE;
4013   }
4014 }
4015
4016 /* initialise bytereaders for stbl sub-atoms */
4017 static gboolean
4018 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
4019 {
4020   /* time-to-sample atom */
4021   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
4022     goto corrupt_file;
4023
4024   /* copy atom data into a new buffer for later use */
4025   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
4026
4027   /* skip version + flags */
4028   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
4029       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
4030     goto corrupt_file;
4031   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
4032
4033   /* make sure there's enough data */
4034   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 2 * 4))
4035     goto corrupt_file;
4036
4037   /* sync sample atom */
4038   stream->stps_present = FALSE;
4039   if ((stream->stss_present =
4040           !!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
4041               &stream->stss) ? TRUE : FALSE) == TRUE) {
4042     /* copy atom data into a new buffer for later use */
4043     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
4044
4045     /* skip version + flags */
4046     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
4047         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
4048       goto corrupt_file;
4049
4050     if (stream->n_sample_syncs) {
4051       /* make sure there's enough data */
4052       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
4053         goto corrupt_file;
4054     }
4055
4056     /* partial sync sample atom */
4057     if ((stream->stps_present =
4058             !!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
4059                 &stream->stps) ? TRUE : FALSE) == TRUE) {
4060       /* copy atom data into a new buffer for later use */
4061       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
4062
4063       /* skip version + flags */
4064       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
4065           !gst_byte_reader_get_uint32_be (&stream->stps,
4066               &stream->n_sample_partial_syncs))
4067         goto corrupt_file;
4068
4069       /* if there are no entries, the stss table contains the real
4070        * sync samples */
4071       if (stream->n_sample_partial_syncs) {
4072         /* make sure there's enough data */
4073         if (!qt_atom_parser_has_chunks (&stream->stps,
4074                 stream->n_sample_partial_syncs, 4))
4075           goto corrupt_file;
4076       }
4077     }
4078   }
4079
4080
4081   /* sample-to-chunk atom */
4082   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
4083     goto corrupt_file;
4084
4085   /* copy atom data into a new buffer for later use */
4086   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
4087
4088   /* skip version + flags */
4089   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
4090       !gst_byte_reader_get_uint32_be (&stream->stsc,
4091           &stream->n_samples_per_chunk))
4092     goto corrupt_file;
4093
4094   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
4095       stream->n_samples_per_chunk);
4096
4097   /* make sure there's enough data */
4098   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
4099           12))
4100     goto corrupt_file;
4101
4102
4103   /* sample size */
4104   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
4105     goto corrupt_file;
4106
4107   /* copy atom data into a new buffer for later use */
4108   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
4109
4110   /* skip version + flags */
4111   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
4112       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
4113     goto corrupt_file;
4114
4115
4116   /* chunk offset */
4117   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
4118     stream->co_size = sizeof (guint32);
4119   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
4120           &stream->stco))
4121     stream->co_size = sizeof (guint64);
4122   else
4123     goto corrupt_file;
4124
4125   /* copy atom data into a new buffer for later use */
4126   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
4127
4128   /* skip version + flags */
4129   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
4130     goto corrupt_file;
4131
4132   /* chunks_are_chunks == 0 means treat chunks as samples */
4133   stream->chunks_are_chunks = !stream->sample_size || stream->sampled;
4134   if (stream->chunks_are_chunks) {
4135     /* skip number of entries */
4136     if (!gst_byte_reader_skip (&stream->stco, 4))
4137       goto corrupt_file;
4138
4139     if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
4140       goto corrupt_file;
4141
4142     /* make sure there are enough data in the stsz atom */
4143     if (!stream->sample_size) {
4144       /* different sizes for each sample */
4145       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
4146         goto corrupt_file;
4147     }
4148   } else {
4149     /* treat chunks as samples */
4150     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
4151       goto corrupt_file;
4152   }
4153
4154   if (!stream->n_samples) {
4155     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4156     return FALSE;
4157   }
4158
4159   GST_DEBUG_OBJECT (qtdemux,
4160       "allocating n_samples %u * %" G_GSIZE_FORMAT " = (%u MB)",
4161       stream->n_samples, sizeof (QtDemuxSample),
4162       (guint) (stream->n_samples * sizeof (QtDemuxSample)) >> 20);
4163
4164   if (stream->n_samples >=
4165       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
4166     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
4167         "be larger than %uMB (broken file?)", stream->n_samples,
4168         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
4169     return FALSE;
4170   }
4171
4172   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
4173   if (!stream->samples) {
4174     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
4175         stream->n_samples);
4176     return FALSE;
4177   }
4178
4179
4180   /* composition time-to-sample */
4181   if ((stream->ctts_present =
4182           !!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
4183               &stream->ctts) ? TRUE : FALSE) == TRUE) {
4184     /* copy atom data into a new buffer for later use */
4185     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
4186
4187     /* skip version + flags */
4188     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
4189         || !gst_byte_reader_get_uint32_be (&stream->ctts,
4190             &stream->n_composition_times))
4191       goto corrupt_file;
4192
4193     /* make sure there's enough data */
4194     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
4195             4 + 4))
4196       goto corrupt_file;
4197   }
4198
4199   stream->stbl_index = -1;      /* no samples have yet been parsed */
4200
4201   return TRUE;
4202
4203 corrupt_file:
4204   {
4205     GST_ELEMENT_ERROR (qtdemux, STREAM, DECODE,
4206         (_("This file is corrupt and cannot be played.")), (NULL));
4207     return FALSE;
4208   }
4209 }
4210
4211 /* collect samples from the next sample to be parsed up to sample @n for @stream
4212  * by reading the info from @stbl
4213  *
4214  * This code can be executed from both the streaming thread and the seeking
4215  * thread so it takes the object lock to protect itself
4216  */
4217 static gboolean
4218 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
4219 {
4220   gint i, j, k;
4221   //gint index = 0;
4222   QtDemuxSample *samples, *first, *cur, *last;
4223   guint32 n_samples_per_chunk;
4224   guint32 n_samples;
4225
4226   n_samples = stream->n_samples;
4227
4228   if (n >= n_samples)
4229     goto out_of_samples;
4230
4231   GST_OBJECT_LOCK (qtdemux);
4232   if (n <= stream->stbl_index)
4233     goto already_parsed;
4234
4235   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
4236
4237   /* pointer to the sample table */
4238   samples = stream->samples;
4239
4240   /* starts from -1, moves to the next sample index to parse */
4241   stream->stbl_index++;
4242
4243   /* keep track of the first and last sample to fill */
4244   first = &samples[stream->stbl_index];
4245   last = &samples[n];
4246
4247   if (stream->chunks_are_chunks) {
4248     /* set the sample sizes */
4249     if (stream->sample_size == 0) {
4250       /* different sizes for each sample */
4251       for (cur = first; cur <= last; cur++) {
4252         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
4253         GST_LOG_OBJECT (qtdemux, "sample %d has size %u", cur - samples,
4254             cur->size);
4255       }
4256     } else {
4257       /* samples have the same size */
4258       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
4259       for (cur = first; cur <= last; cur++)
4260         cur->size = stream->sample_size;
4261     }
4262   }
4263
4264   n_samples_per_chunk = stream->n_samples_per_chunk;
4265   cur = first;
4266
4267   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
4268     guint32 last_chunk;
4269
4270     if (stream->stsc_chunk_index >= stream->last_chunk
4271         || stream->stsc_chunk_index < stream->first_chunk) {
4272       stream->first_chunk =
4273           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
4274       stream->samples_per_chunk =
4275           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
4276       gst_byte_reader_skip_unchecked (&stream->stsc, 4);
4277
4278       /* chunk numbers are counted from 1 it seems */
4279       if (G_UNLIKELY (stream->first_chunk == 0))
4280         goto corrupt_file;
4281
4282       --stream->first_chunk;
4283
4284       /* the last chunk of each entry is calculated by taking the first chunk
4285        * of the next entry; except if there is no next, where we fake it with
4286        * INT_MAX */
4287       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
4288         stream->last_chunk = G_MAXUINT32;
4289       } else {
4290         stream->last_chunk =
4291             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
4292         if (G_UNLIKELY (stream->last_chunk == 0))
4293           goto corrupt_file;
4294
4295         --stream->last_chunk;
4296       }
4297
4298       GST_LOG_OBJECT (qtdemux,
4299           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d", i,
4300           stream->first_chunk, stream->last_chunk, stream->samples_per_chunk);
4301
4302       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
4303         goto corrupt_file;
4304
4305       if (stream->last_chunk != G_MAXUINT32) {
4306         if (!qt_atom_parser_peek_sub (&stream->stco,
4307                 stream->first_chunk * stream->co_size,
4308                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
4309                 &stream->co_chunk))
4310           goto corrupt_file;
4311
4312       } else {
4313         stream->co_chunk = stream->stco;
4314         if (!gst_byte_reader_skip (&stream->co_chunk,
4315                 stream->first_chunk * stream->co_size))
4316           goto corrupt_file;
4317       }
4318
4319       stream->stsc_chunk_index = stream->first_chunk;
4320     }
4321
4322     last_chunk = stream->last_chunk;
4323
4324     if (stream->chunks_are_chunks) {
4325       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
4326         guint32 samples_per_chunk;
4327         guint64 chunk_offset;
4328
4329         if (!stream->stsc_sample_index
4330             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
4331                 &stream->chunk_offset))
4332           goto corrupt_file;
4333
4334         samples_per_chunk = stream->samples_per_chunk;
4335         chunk_offset = stream->chunk_offset;
4336
4337         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
4338           GST_LOG_OBJECT (qtdemux, "Creating entry %d with offset %"
4339               G_GUINT64_FORMAT, cur - samples, stream->chunk_offset);
4340
4341           cur->offset = chunk_offset;
4342           chunk_offset += cur->size;
4343           cur++;
4344
4345           if (G_UNLIKELY (cur > last)) {
4346             /* save state */
4347             stream->stsc_sample_index = k + 1;
4348             stream->chunk_offset = chunk_offset;
4349             stream->stsc_chunk_index = j;
4350             goto done2;
4351           }
4352         }
4353         stream->stsc_sample_index = 0;
4354       }
4355       stream->stsc_chunk_index = j;
4356     } else {
4357       cur = &samples[stream->stsc_chunk_index];
4358
4359       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
4360         if (j > n) {
4361           /* save state */
4362           stream->stsc_chunk_index = j;
4363           goto done;
4364         }
4365
4366         cur->offset =
4367             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
4368             stream->co_size);
4369
4370         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
4371             "%" G_GUINT64_FORMAT, j, cur->offset);
4372
4373         if (stream->samples_per_frame * stream->bytes_per_frame) {
4374           cur->size =
4375               (stream->samples_per_chunk * stream->n_channels) /
4376               stream->samples_per_frame * stream->bytes_per_frame;
4377         } else {
4378           cur->size = stream->samples_per_chunk;
4379         }
4380
4381         GST_DEBUG_OBJECT (qtdemux,
4382             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
4383             j, GST_TIME_ARGS (gst_util_uint64_scale (stream->stco_sample_index,
4384                     GST_SECOND, stream->timescale)), cur->size);
4385
4386         cur->timestamp = stream->stco_sample_index;
4387         cur->duration = stream->samples_per_chunk;
4388         cur->keyframe = TRUE;
4389         cur++;
4390
4391         stream->stco_sample_index += stream->samples_per_chunk;
4392       }
4393       stream->stsc_chunk_index = j;
4394     }
4395     stream->stsc_index++;
4396   }
4397
4398   if (!stream->chunks_are_chunks)
4399     goto ctts;
4400 done2:
4401   {
4402     guint32 n_sample_times;
4403
4404     n_sample_times = stream->n_sample_times;
4405     cur = first;
4406
4407     for (i = stream->stts_index; i < n_sample_times; i++) {
4408       guint32 stts_samples;
4409       guint32 stts_duration;
4410       guint64 stts_time;
4411
4412       if (stream->stts_sample_index >= stream->stts_samples
4413           || !stream->stts_sample_index) {
4414
4415         stream->stts_samples =
4416             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
4417         stream->stts_duration =
4418             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
4419
4420         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %"
4421             G_GUINT64_FORMAT, i, stream->stts_samples, stream->stts_duration);
4422
4423         /* take first duration for fps */
4424         if (G_UNLIKELY (stream->min_duration == 0))
4425           stream->min_duration = stream->stts_duration;
4426
4427         stream->stts_sample_index = 0;
4428       }
4429
4430       stts_samples = stream->stts_samples;
4431       stts_duration = stream->stts_duration;
4432       stts_time = stream->stts_time;
4433
4434       for (j = stream->stts_sample_index; j < stts_samples; j++) {
4435         GST_DEBUG_OBJECT (qtdemux,
4436             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
4437             cur - samples, j, GST_TIME_ARGS (gst_util_uint64_scale (stts_time,
4438                     GST_SECOND, stream->timescale)));
4439
4440         cur->timestamp = stts_time;
4441         cur->duration = stts_duration;
4442
4443         stts_time += stts_duration;
4444         cur++;
4445
4446         if (G_UNLIKELY (cur > last)) {
4447           /* save values */
4448           stream->stts_time = stts_time;
4449           stream->stts_sample_index = j + 1;
4450           goto done3;
4451         }
4452       }
4453       stream->stts_sample_index = 0;
4454       stream->stts_time = stts_time;
4455       stream->stts_index++;
4456     }
4457     /* fill up empty timestamps with the last timestamp, this can happen when
4458      * the last samples do not decode and so we don't have timestamps for them.
4459      * We however look at the last timestamp to estimate the track length so we
4460      * need something in here. */
4461     for (; cur < last; cur++) {
4462       GST_DEBUG_OBJECT (qtdemux,
4463           "fill sample %d: timestamp %" GST_TIME_FORMAT, cur - samples,
4464           GST_TIME_ARGS (gst_util_uint64_scale (stream->stts_time, GST_SECOND,
4465                   stream->timescale)));
4466       cur->timestamp = stream->stts_time;
4467       cur->duration = -1;
4468     }
4469   }
4470 done3:
4471   {
4472     /* sample sync, can be NULL */
4473     if (stream->stss_present == TRUE) {
4474       guint32 n_sample_syncs;
4475
4476       n_sample_syncs = stream->n_sample_syncs;
4477
4478       if (!n_sample_syncs) {
4479         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
4480         stream->all_keyframe = TRUE;
4481       } else {
4482         for (i = stream->stss_index; i < n_sample_syncs; i++) {
4483           /* note that the first sample is index 1, not 0 */
4484           guint32 index;
4485
4486           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
4487
4488           if (G_LIKELY (index > 0 && index <= n_samples)) {
4489             index -= 1;
4490             samples[index].keyframe = TRUE;
4491             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
4492             /* and exit if we have enough samples */
4493             if (G_UNLIKELY (index >= n)) {
4494               i++;
4495               break;
4496             }
4497           }
4498         }
4499         /* save state */
4500         stream->stss_index = i;
4501       }
4502
4503       /* stps marks partial sync frames like open GOP I-Frames */
4504       if (stream->stps_present == TRUE) {
4505         guint32 n_sample_partial_syncs;
4506
4507         n_sample_partial_syncs = stream->n_sample_partial_syncs;
4508
4509         /* if there are no entries, the stss table contains the real
4510          * sync samples */
4511         if (n_sample_partial_syncs) {
4512           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
4513             /* note that the first sample is index 1, not 0 */
4514             guint32 index;
4515
4516             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
4517
4518             if (G_LIKELY (index > 0 && index <= n_samples)) {
4519               index -= 1;
4520               samples[index].keyframe = TRUE;
4521               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
4522               /* and exit if we have enough samples */
4523               if (G_UNLIKELY (index >= n)) {
4524                 i++;
4525                 break;
4526               }
4527             }
4528           }
4529           /* save state */
4530           stream->stps_index = i;
4531         }
4532       }
4533     } else {
4534       /* no stss, all samples are keyframes */
4535       stream->all_keyframe = TRUE;
4536       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
4537     }
4538   }
4539
4540 ctts:
4541   /* composition time to sample */
4542   if (stream->ctts_present == TRUE) {
4543     guint32 n_composition_times;
4544     guint32 ctts_count;
4545     gint32 ctts_soffset;
4546
4547     /* Fill in the pts_offsets */
4548     cur = first;
4549     n_composition_times = stream->n_composition_times;
4550
4551     for (i = stream->ctts_index; i < n_composition_times; i++) {
4552       if (stream->ctts_sample_index >= stream->ctts_count
4553           || !stream->ctts_sample_index) {
4554         stream->ctts_count =
4555             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
4556         stream->ctts_soffset =
4557             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
4558         stream->ctts_sample_index = 0;
4559       }
4560
4561       ctts_count = stream->ctts_count;
4562       ctts_soffset = stream->ctts_soffset;
4563
4564       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
4565         cur->pts_offset = ctts_soffset;
4566         cur++;
4567
4568         if (G_UNLIKELY (cur > last))
4569           /* save state */
4570           stream->ctts_sample_index = j + 1;
4571         goto done;
4572       }
4573       stream->ctts_sample_index = 0;
4574       stream->ctts_index++;
4575     }
4576   }
4577 done:
4578   stream->stbl_index = n;
4579   /* if index has been completely parsed, free data that is no-longer needed */
4580   if (n == stream->n_samples)
4581     gst_qtdemux_stbl_free (stream);
4582   GST_OBJECT_UNLOCK (qtdemux);
4583
4584   return TRUE;
4585
4586   /* SUCCESS */
4587 already_parsed:
4588   {
4589     GST_LOG_OBJECT (qtdemux,
4590         "Tried to parse up to sample %u but this sample has already been parsed",
4591         n);
4592     GST_OBJECT_UNLOCK (qtdemux);
4593     return TRUE;
4594   }
4595   /* ERRORS */
4596 out_of_samples:
4597   {
4598     GST_LOG_OBJECT (qtdemux,
4599         "Tried to parse up to sample %u but there are only %u samples", n + 1,
4600         stream->n_samples);
4601     GST_ELEMENT_ERROR (qtdemux, STREAM, DECODE,
4602         (_("This file is corrupt and cannot be played.")), (NULL));
4603     return FALSE;
4604   }
4605 corrupt_file:
4606   {
4607     GST_ELEMENT_ERROR (qtdemux, STREAM, DECODE,
4608         (_("This file is corrupt and cannot be played.")), (NULL));
4609     GST_OBJECT_UNLOCK (qtdemux);
4610     return FALSE;
4611   }
4612 }
4613
4614 /* collect all segment info for @stream.
4615  */
4616 static gboolean
4617 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
4618     GNode * trak)
4619 {
4620   GNode *edts;
4621
4622   /* parse and prepare segment info from the edit list */
4623   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
4624   stream->n_segments = 0;
4625   stream->segments = NULL;
4626   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
4627     GNode *elst;
4628     gint n_segments;
4629     gint i, count;
4630     guint64 time, stime;
4631     guint8 *buffer;
4632
4633     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
4634     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
4635       goto done;
4636
4637     buffer = elst->data;
4638
4639     n_segments = QT_UINT32 (buffer + 12);
4640
4641     /* we might allocate a bit too much, at least allocate 1 segment */
4642     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
4643
4644     /* segments always start from 0 */
4645     time = 0;
4646     stime = 0;
4647     count = 0;
4648     for (i = 0; i < n_segments; i++) {
4649       guint64 duration;
4650       guint64 media_time;
4651       QtDemuxSegment *segment;
4652       guint32 rate_int;
4653
4654       media_time = QT_UINT32 (buffer + 20 + i * 12);
4655
4656       /* -1 media time is an empty segment, just ignore it */
4657       if (media_time == G_MAXUINT32)
4658         continue;
4659
4660       duration = QT_UINT32 (buffer + 16 + i * 12);
4661
4662       segment = &stream->segments[count++];
4663
4664       /* time and duration expressed in global timescale */
4665       segment->time = stime;
4666       /* add non scaled values so we don't cause roundoff errors */
4667       time += duration;
4668       stime = gst_util_uint64_scale (time, GST_SECOND, qtdemux->timescale);
4669       segment->stop_time = stime;
4670       segment->duration = stime - segment->time;
4671       /* media_time expressed in stream timescale */
4672       segment->media_start =
4673           gst_util_uint64_scale (media_time, GST_SECOND, stream->timescale);
4674       segment->media_stop = segment->media_start + segment->duration;
4675       rate_int = GST_READ_UINT32_BE (buffer + 24 + i * 12);
4676
4677       if (rate_int <= 1) {
4678         /* 0 is not allowed, some programs write 1 instead of the floating point
4679          * value */
4680         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
4681             rate_int);
4682         segment->rate = 1;
4683       } else {
4684         segment->rate = rate_int / 65536.0;
4685       }
4686
4687       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
4688           ", duration %" GST_TIME_FORMAT ", media_time %" GST_TIME_FORMAT
4689           ", rate %g, (%d)", i, GST_TIME_ARGS (segment->time),
4690           GST_TIME_ARGS (segment->duration),
4691           GST_TIME_ARGS (segment->media_start), segment->rate, rate_int);
4692     }
4693     GST_DEBUG_OBJECT (qtdemux, "found %d non-empty segments", count);
4694     stream->n_segments = count;
4695   }
4696 done:
4697
4698   /* push based does not handle segments, so act accordingly here,
4699    * and warn if applicable */
4700   if (!qtdemux->pullbased) {
4701     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
4702     /* remove and use default one below, we stream like it anyway */
4703     g_free (stream->segments);
4704     stream->segments = NULL;
4705     stream->n_segments = 0;
4706   }
4707
4708   /* no segments, create one to play the complete trak */
4709   if (stream->n_segments == 0) {
4710     GstClockTime stream_duration =
4711         gst_util_uint64_scale (stream->duration, GST_SECOND, stream->timescale);
4712
4713     if (stream->segments == NULL)
4714       stream->segments = g_new (QtDemuxSegment, 1);
4715
4716     stream->segments[0].time = 0;
4717     stream->segments[0].stop_time = stream_duration;
4718     stream->segments[0].duration = stream_duration;
4719     stream->segments[0].media_start = 0;
4720     stream->segments[0].media_stop = stream_duration;
4721     stream->segments[0].rate = 1.0;
4722
4723     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
4724         GST_TIME_ARGS (stream_duration));
4725     stream->n_segments = 1;
4726   }
4727   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
4728
4729   return TRUE;
4730 }
4731
4732 /*
4733  * Parses the stsd atom of a svq3 trak looking for
4734  * the SMI and gama atoms.
4735  */
4736 static void
4737 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux, GNode * stsd,
4738     guint8 ** gamma, GstBuffer ** seqh)
4739 {
4740   guint8 *_gamma = NULL;
4741   GstBuffer *_seqh = NULL;
4742   guint8 *stsd_data = stsd->data;
4743   guint32 length = QT_UINT32 (stsd_data);
4744   guint16 version;
4745
4746   if (length < 32) {
4747     GST_WARNING_OBJECT (qtdemux, "stsd too short");
4748     goto end;
4749   }
4750
4751   stsd_data += 32;
4752   length -= 32;
4753   version = QT_UINT16 (stsd_data);
4754   if (version == 3) {
4755     if (length >= 70) {
4756       length -= 70;
4757       stsd_data += 70;
4758       while (length > 8) {
4759         guint32 fourcc, size;
4760         guint8 *data;
4761         size = QT_UINT32 (stsd_data);
4762         fourcc = QT_FOURCC (stsd_data + 4);
4763         data = stsd_data + 8;
4764
4765         switch (fourcc) {
4766           case FOURCC_gama:{
4767             if (size == 12) {
4768               _gamma = data;
4769             } else {
4770               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
4771                   " for gama atom, expected 12", size);
4772             }
4773             break;
4774           }
4775           case FOURCC_SMI_:{
4776             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
4777               guint32 seqh_size;
4778               if (_seqh != NULL) {
4779                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
4780                     " found, ignoring");
4781               } else {
4782                 seqh_size = QT_UINT32 (data + 4);
4783                 if (seqh_size > 0) {
4784                   _seqh = gst_buffer_new_and_alloc (seqh_size);
4785                   memcpy (GST_BUFFER_DATA (_seqh), data + 8, seqh_size);
4786                 }
4787               }
4788             }
4789             break;
4790           }
4791           default:{
4792             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
4793                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
4794           }
4795         }
4796
4797         if (size <= length) {
4798           length -= size;
4799           stsd_data += size;
4800         }
4801       }
4802     } else {
4803       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
4804     }
4805   } else {
4806     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
4807         G_GUINT16_FORMAT, version);
4808     goto end;
4809   }
4810
4811 end:
4812   if (gamma) {
4813     *gamma = _gamma;
4814   }
4815   if (seqh) {
4816     *seqh = _seqh;
4817   } else if (_seqh) {
4818     gst_buffer_unref (_seqh);
4819   }
4820 }
4821
4822 /* parse the traks.
4823  * With each track we associate a new QtDemuxStream that contains all the info
4824  * about the trak.
4825  * traks that do not decode to something (like strm traks) will not have a pad.
4826  */
4827 static gboolean
4828 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
4829 {
4830   GstByteReader tkhd;
4831   int offset;
4832   GNode *mdia;
4833   GNode *mdhd;
4834   GNode *hdlr;
4835   GNode *minf;
4836   GNode *stbl;
4837   GNode *stsd;
4838   GNode *mp4a;
4839   GNode *mp4v;
4840   GNode *wave;
4841   GNode *esds;
4842   GNode *pasp;
4843   QtDemuxStream *stream;
4844   GstTagList *list = NULL;
4845   gchar *codec = NULL;
4846   const guint8 *stsd_data;
4847   guint32 version;
4848   guint32 tkhd_flags = 0;
4849   guint8 tkhd_version = 0;
4850   guint32 fourcc;
4851   guint len;
4852
4853   stream = g_new0 (QtDemuxStream, 1);
4854   /* new streams always need a discont */
4855   stream->discont = TRUE;
4856   /* we enable clipping for raw audio/video streams */
4857   stream->need_clip = FALSE;
4858   stream->need_process = FALSE;
4859   stream->segment_index = -1;
4860   stream->time_position = 0;
4861   stream->sample_index = -1;
4862   stream->last_ret = GST_FLOW_OK;
4863
4864   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
4865       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
4866       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
4867     goto corrupt_file;
4868
4869   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags: 0x%02x/%06x",
4870       tkhd_version, tkhd_flags);
4871
4872   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
4873     goto corrupt_file;
4874
4875   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
4876     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
4877     if (qtdemux->major_brand != FOURCC_mjp2 ||
4878         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
4879       goto corrupt_file;
4880   }
4881
4882   len = QT_UINT32 ((guint8 *) mdhd->data);
4883   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
4884   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
4885   if (version == 0x01000000) {
4886     if (len < 38)
4887       goto corrupt_file;
4888     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
4889     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
4890     stream->lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
4891   } else {
4892     if (len < 30)
4893       goto corrupt_file;
4894     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
4895     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
4896     stream->lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
4897   }
4898
4899   stream->lang_id[0] = 0x60 + ((stream->lang_code >> 10) & 0x1F);
4900   stream->lang_id[1] = 0x60 + ((stream->lang_code >> 5) & 0x1F);
4901   stream->lang_id[2] = 0x60 + (stream->lang_code & 0x1F);
4902   stream->lang_id[3] = 0;
4903
4904   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
4905       stream->timescale);
4906   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
4907       stream->duration);
4908   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%x/%s",
4909       stream->lang_code, stream->lang_id);
4910
4911   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
4912     goto corrupt_file;
4913
4914   if (qtdemux->duration != G_MAXINT32 && stream->duration != G_MAXINT32) {
4915     guint64 tdur1, tdur2;
4916
4917     /* don't overflow */
4918     tdur1 = stream->timescale * (guint64) qtdemux->duration;
4919     tdur2 = qtdemux->timescale * (guint64) stream->duration;
4920
4921     /* HACK:
4922      * some of those trailers, nowadays, have prologue images that are
4923      * themselves vide tracks as well. I haven't really found a way to
4924      * identify those yet, except for just looking at their duration. */
4925     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
4926       GST_WARNING_OBJECT (qtdemux,
4927           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
4928           " vs. %" G_GUINT32_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
4929           "found, assuming preview image or something; skipping track",
4930           stream->duration, stream->timescale, qtdemux->duration,
4931           qtdemux->timescale);
4932       g_free (stream);
4933       return TRUE;
4934     }
4935   }
4936
4937   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
4938     goto corrupt_file;
4939
4940   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
4941       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
4942
4943   len = QT_UINT32 ((guint8 *) hdlr->data);
4944   if (len >= 20)
4945     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
4946   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
4947       GST_FOURCC_ARGS (stream->subtype));
4948
4949   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
4950     goto corrupt_file;
4951
4952   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
4953     goto corrupt_file;
4954
4955   /* parse stsd */
4956   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
4957     goto corrupt_file;
4958   stsd_data = (const guint8 *) stsd->data;
4959
4960   /* stsd should at least have one entry */
4961   len = QT_UINT32 (stsd_data);
4962   if (len < 24)
4963     goto corrupt_file;
4964
4965   /* and that entry should fit within stsd */
4966   len = QT_UINT32 (stsd_data + 16);
4967   if (len > QT_UINT32 (stsd_data) + 16)
4968     goto corrupt_file;
4969   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", len);
4970
4971   stream->fourcc = fourcc = QT_FOURCC (stsd_data + 16 + 4);
4972   GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
4973       GST_FOURCC_ARGS (stream->fourcc));
4974
4975   if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi) ||
4976       ((fourcc & 0xFFFFFF00) == GST_MAKE_FOURCC ('e', 'n', 'c', 0)))
4977     goto error_encrypted;
4978
4979   if (stream->subtype == FOURCC_vide) {
4980     guint32 w = 0, h = 0;
4981
4982     stream->sampled = TRUE;
4983
4984     /* version 1 uses some 64-bit ints */
4985     if (!gst_byte_reader_skip (&tkhd, (tkhd_version == 1) ? 84 : 72)
4986         || !gst_byte_reader_get_uint32_be (&tkhd, &w)
4987         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
4988       goto corrupt_file;
4989
4990     stream->display_width = w >> 16;
4991     stream->display_height = h >> 16;
4992
4993     offset = 16;
4994     if (len < 86)
4995       goto corrupt_file;
4996
4997     stream->width = QT_UINT16 (stsd_data + offset + 32);
4998     stream->height = QT_UINT16 (stsd_data + offset + 34);
4999     stream->fps_n = 0;          /* this is filled in later */
5000     stream->fps_d = 0;          /* this is filled in later */
5001     stream->bits_per_sample = QT_UINT16 (stsd_data + offset + 82);
5002     stream->color_table_id = QT_UINT16 (stsd_data + offset + 84);
5003
5004     GST_LOG_OBJECT (qtdemux, "frame count:   %u",
5005         QT_UINT16 (stsd_data + offset + 48));
5006
5007     stream->caps =
5008         qtdemux_video_caps (qtdemux, stream, fourcc, stsd_data, &codec);
5009     if (codec) {
5010       list = gst_tag_list_new ();
5011       gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
5012           GST_TAG_VIDEO_CODEC, codec, NULL);
5013       g_free (codec);
5014       codec = NULL;
5015     }
5016
5017     esds = NULL;
5018     pasp = NULL;
5019     mp4v = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4v);
5020     /* H264 is MPEG-4 after all,
5021      * and qt seems to put MPEG-4 stuff in there as well */
5022     if (!mp4v)
5023       mp4v = qtdemux_tree_get_child_by_type (stsd, FOURCC_avc1);
5024     if (mp4v) {
5025       esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
5026       pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
5027     }
5028
5029     if (pasp) {
5030       const guint8 *pasp_data = (const guint8 *) pasp->data;
5031
5032       stream->par_w = QT_UINT32 (pasp_data + 8);
5033       stream->par_h = QT_UINT32 (pasp_data + 12);
5034     } else {
5035       stream->par_w = 0;
5036       stream->par_h = 0;
5037     }
5038
5039     if (esds) {
5040       gst_qtdemux_handle_esds (qtdemux, stream, esds, list);
5041     } else {
5042       switch (fourcc) {
5043         case FOURCC_avc1:
5044         {
5045           gint len = QT_UINT32 (stsd_data) - 0x66;
5046           const guint8 *avc_data = stsd_data + 0x66;
5047
5048           /* find avcC */
5049           while (len >= 0x8 &&
5050               QT_FOURCC (avc_data + 0x4) != FOURCC_avcC &&
5051               QT_UINT32 (avc_data) < len) {
5052             len -= QT_UINT32 (avc_data);
5053             avc_data += QT_UINT32 (avc_data);
5054           }
5055
5056           /* parse, if found */
5057           if (len > 0x8 && QT_FOURCC (avc_data + 0x4) == FOURCC_avcC) {
5058             GstBuffer *buf;
5059             gint size;
5060
5061             if (QT_UINT32 (avc_data) < len)
5062               size = QT_UINT32 (avc_data) - 0x8;
5063             else
5064               size = len - 0x8;
5065
5066             GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
5067
5068             buf = gst_buffer_new_and_alloc (size);
5069             memcpy (GST_BUFFER_DATA (buf), avc_data + 0x8, size);
5070             gst_caps_set_simple (stream->caps,
5071                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
5072             gst_buffer_unref (buf);
5073           }
5074           break;
5075         }
5076         case FOURCC_mjp2:
5077         {
5078           /* see annex I of the jpeg2000 spec */
5079           GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
5080           const guint8 *data;
5081           guint32 fourcc = 0;
5082           gint ncomp = 0;
5083           guint32 ncomp_map = 0;
5084           gint32 *comp_map = NULL;
5085           guint32 nchan_def = 0;
5086           gint32 *chan_def = NULL;
5087
5088           GST_DEBUG_OBJECT (qtdemux, "found mjp2");
5089           /* some required atoms */
5090           mjp2 = qtdemux_tree_get_child_by_type (stsd, FOURCC_mjp2);
5091           if (!mjp2)
5092             break;
5093           jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
5094           if (!jp2h)
5095             break;
5096
5097           /* number of components; redundant with info in codestream, but useful
5098              to a muxer */
5099           ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
5100           if (!ihdr || QT_UINT32 (ihdr->data) != 22)
5101             break;
5102           ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
5103
5104           colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
5105           if (!colr)
5106             break;
5107           GST_DEBUG_OBJECT (qtdemux, "found colr");
5108           /* extract colour space info */
5109           if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
5110             switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
5111               case 16:
5112                 fourcc = GST_MAKE_FOURCC ('s', 'R', 'G', 'B');
5113                 break;
5114               case 17:
5115                 fourcc = GST_MAKE_FOURCC ('G', 'R', 'A', 'Y');
5116                 break;
5117               case 18:
5118                 fourcc = GST_MAKE_FOURCC ('s', 'Y', 'U', 'V');
5119                 break;
5120               default:
5121                 break;
5122             }
5123           }
5124           if (!fourcc)
5125             /* colr is required, and only values 16, 17, and 18 are specified,
5126                so error if we have no fourcc */
5127             break;
5128
5129           /* extract component mapping */
5130           cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
5131           if (cmap) {
5132             guint32 cmap_len = 0;
5133             int i;
5134             cmap_len = QT_UINT32 (cmap->data);
5135             if (cmap_len >= 8) {
5136               /* normal box, subtract off header */
5137               cmap_len -= 8;
5138               /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
5139               if (cmap_len % 4 == 0) {
5140                 ncomp_map = (cmap_len / 4);
5141                 comp_map = g_new0 (gint32, ncomp_map);
5142                 for (i = 0; i < ncomp_map; i++) {
5143                   guint16 cmp;
5144                   guint8 mtyp, pcol;
5145                   cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
5146                   mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
5147                   pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
5148                   comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
5149                 }
5150               }
5151             }
5152           }
5153           /* extract channel definitions */
5154           cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
5155           if (cdef) {
5156             guint32 cdef_len = 0;
5157             int i;
5158             cdef_len = QT_UINT32 (cdef->data);
5159             if (cdef_len >= 10) {
5160               /* normal box, subtract off header and len */
5161               cdef_len -= 10;
5162               /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
5163               if (cdef_len % 6 == 0) {
5164                 nchan_def = (cdef_len / 6);
5165                 chan_def = g_new0 (gint32, nchan_def);
5166                 for (i = 0; i < nchan_def; i++)
5167                   chan_def[i] = -1;
5168                 for (i = 0; i < nchan_def; i++) {
5169                   guint16 cn, typ, asoc;
5170                   cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
5171                   typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
5172                   asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
5173                   if (cn < nchan_def) {
5174                     switch (typ) {
5175                       case 0:
5176                         chan_def[cn] = asoc;
5177                         break;
5178                       case 1:
5179                         chan_def[cn] = 0;       /* alpha */
5180                         break;
5181                       default:
5182                         chan_def[cn] = -typ;
5183                     }
5184                   }
5185                 }
5186               }
5187             }
5188           }
5189
5190           gst_caps_set_simple (stream->caps,
5191               "num-components", G_TYPE_INT, ncomp, NULL);
5192           gst_caps_set_simple (stream->caps,
5193               "fourcc", GST_TYPE_FOURCC, fourcc, NULL);
5194
5195           if (comp_map) {
5196             GValue arr = { 0, };
5197             GValue elt = { 0, };
5198             int i;
5199             g_value_init (&arr, GST_TYPE_ARRAY);
5200             g_value_init (&elt, G_TYPE_INT);
5201             for (i = 0; i < ncomp_map; i++) {
5202               g_value_set_int (&elt, comp_map[i]);
5203               gst_value_array_append_value (&arr, &elt);
5204             }
5205             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
5206                 "component-map", &arr);
5207             g_value_unset (&elt);
5208             g_value_unset (&arr);
5209             g_free (comp_map);
5210           }
5211
5212           if (chan_def) {
5213             GValue arr = { 0, };
5214             GValue elt = { 0, };
5215             int i;
5216             g_value_init (&arr, GST_TYPE_ARRAY);
5217             g_value_init (&elt, G_TYPE_INT);
5218             for (i = 0; i < nchan_def; i++) {
5219               g_value_set_int (&elt, chan_def[i]);
5220               gst_value_array_append_value (&arr, &elt);
5221             }
5222             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
5223                 "channel-definitions", &arr);
5224             g_value_unset (&elt);
5225             g_value_unset (&arr);
5226             g_free (chan_def);
5227           }
5228
5229           /* some optional atoms */
5230           field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
5231           prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
5232
5233           /* indicate possible fields in caps */
5234           if (field) {
5235             data = (guint8 *) field->data + 8;
5236             if (*data != 1)
5237               gst_caps_set_simple (stream->caps, "fields", G_TYPE_INT,
5238                   (gint) * data, NULL);
5239           }
5240           /* add codec_data if provided */
5241           if (prefix) {
5242             GstBuffer *buf;
5243             gint len;
5244
5245             GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
5246             data = prefix->data;
5247             len = QT_UINT32 (data);
5248             if (len > 0x8) {
5249               len -= 0x8;
5250               buf = gst_buffer_new_and_alloc (len);
5251               memcpy (GST_BUFFER_DATA (buf), data + 8, len);
5252               gst_caps_set_simple (stream->caps,
5253                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
5254               gst_buffer_unref (buf);
5255             }
5256           }
5257           break;
5258         }
5259         case FOURCC_SVQ3:
5260         case FOURCC_VP31:
5261         {
5262           GstBuffer *buf;
5263           GstBuffer *seqh = NULL;
5264           guint8 *gamma_data = NULL;
5265           gint len = QT_UINT32 (stsd_data);
5266
5267           qtdemux_parse_svq3_stsd_data (qtdemux, stsd, &gamma_data, &seqh);
5268           if (gamma_data) {
5269             gst_caps_set_simple (stream->caps, "applied-gamma", G_TYPE_DOUBLE,
5270                 QT_FP32 (gamma_data), NULL);
5271           }
5272           if (seqh) {
5273             /* sorry for the bad name, but we don't know what this is, other
5274              * than its own fourcc */
5275             gst_caps_set_simple (stream->caps, "seqh", GST_TYPE_BUFFER, seqh,
5276                 NULL);
5277           }
5278
5279           GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
5280           buf = gst_buffer_new_and_alloc (len);
5281           memcpy (GST_BUFFER_DATA (buf), stsd_data, len);
5282           gst_caps_set_simple (stream->caps,
5283               "codec_data", GST_TYPE_BUFFER, buf, NULL);
5284           gst_buffer_unref (buf);
5285           break;
5286         }
5287         case FOURCC_rle_:
5288         {
5289           gst_caps_set_simple (stream->caps,
5290               "depth", G_TYPE_INT, QT_UINT16 (stsd_data + offset + 82), NULL);
5291           break;
5292         }
5293         case FOURCC_XiTh:
5294         {
5295           GNode *xith, *xdxt;
5296
5297           GST_DEBUG_OBJECT (qtdemux, "found XiTh");
5298           xith = qtdemux_tree_get_child_by_type (stsd, FOURCC_XiTh);
5299           if (!xith)
5300             break;
5301
5302           xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
5303           if (!xdxt)
5304             break;
5305
5306           GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
5307           /* collect the headers and store them in a stream list so that we can
5308            * send them out first */
5309           qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
5310           break;
5311         }
5312         default:
5313           break;
5314       }
5315     }
5316
5317     GST_INFO_OBJECT (qtdemux,
5318         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
5319         GST_FOURCC_ARGS (fourcc), stream->caps);
5320
5321   } else if (stream->subtype == FOURCC_soun) {
5322     int version, samplesize;
5323     guint16 compression_id;
5324
5325     offset = 32;
5326     if (len < 36)
5327       goto corrupt_file;
5328
5329     version = QT_UINT32 (stsd_data + offset);
5330     stream->n_channels = QT_UINT16 (stsd_data + offset + 8);
5331     samplesize = QT_UINT16 (stsd_data + offset + 10);
5332     compression_id = QT_UINT16 (stsd_data + offset + 12);
5333     stream->rate = QT_FP32 (stsd_data + offset + 16);
5334
5335     GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
5336     GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
5337         QT_UINT32 (stsd_data + offset + 4));
5338     GST_LOG_OBJECT (qtdemux, "n_channels:       %d", stream->n_channels);
5339     GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
5340     GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
5341     GST_LOG_OBJECT (qtdemux, "packet size:      %d",
5342         QT_UINT16 (stsd_data + offset + 14));
5343     GST_LOG_OBJECT (qtdemux, "sample rate:      %g", stream->rate);
5344
5345     if (compression_id == 0xfffe)
5346       stream->sampled = TRUE;
5347
5348     /* first assume uncompressed audio */
5349     stream->bytes_per_sample = samplesize / 8;
5350     stream->samples_per_frame = stream->n_channels;
5351     stream->bytes_per_frame = stream->n_channels * stream->bytes_per_sample;
5352     stream->samples_per_packet = stream->samples_per_frame;
5353     stream->bytes_per_packet = stream->bytes_per_sample;
5354
5355     offset = 52;
5356     switch (fourcc) {
5357         /* Yes, these have to be hard-coded */
5358       case FOURCC_MAC6:
5359       {
5360         stream->samples_per_packet = 6;
5361         stream->bytes_per_packet = 1;
5362         stream->bytes_per_frame = 1 * stream->n_channels;
5363         stream->bytes_per_sample = 1;
5364         stream->samples_per_frame = 6 * stream->n_channels;
5365         break;
5366       }
5367       case FOURCC_MAC3:
5368       {
5369         stream->samples_per_packet = 3;
5370         stream->bytes_per_packet = 1;
5371         stream->bytes_per_frame = 1 * stream->n_channels;
5372         stream->bytes_per_sample = 1;
5373         stream->samples_per_frame = 3 * stream->n_channels;
5374         break;
5375       }
5376       case FOURCC_ima4:
5377       {
5378         stream->samples_per_packet = 64;
5379         stream->bytes_per_packet = 34;
5380         stream->bytes_per_frame = 34 * stream->n_channels;
5381         stream->bytes_per_sample = 2;
5382         stream->samples_per_frame = 64 * stream->n_channels;
5383         break;
5384       }
5385       case FOURCC_ulaw:
5386       case FOURCC_alaw:
5387       {
5388         stream->samples_per_packet = 1;
5389         stream->bytes_per_packet = 1;
5390         stream->bytes_per_frame = 1 * stream->n_channels;
5391         stream->bytes_per_sample = 1;
5392         stream->samples_per_frame = 1 * stream->n_channels;
5393         break;
5394       }
5395       case FOURCC_agsm:
5396       {
5397         stream->samples_per_packet = 160;
5398         stream->bytes_per_packet = 33;
5399         stream->bytes_per_frame = 33 * stream->n_channels;
5400         stream->bytes_per_sample = 2;
5401         stream->samples_per_frame = 160 * stream->n_channels;
5402         break;
5403       }
5404       default:
5405         break;
5406     }
5407
5408     if (version == 0x00010000) {
5409       switch (fourcc) {
5410         case FOURCC_twos:
5411         case FOURCC_sowt:
5412         case FOURCC_raw_:
5413           break;
5414         default:
5415         {
5416           /* only parse extra decoding config for non-pcm audio */
5417           stream->samples_per_packet = QT_UINT32 (stsd_data + offset);
5418           stream->bytes_per_packet = QT_UINT32 (stsd_data + offset + 4);
5419           stream->bytes_per_frame = QT_UINT32 (stsd_data + offset + 8);
5420           stream->bytes_per_sample = QT_UINT32 (stsd_data + offset + 12);
5421
5422           GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
5423               stream->samples_per_packet);
5424           GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
5425               stream->bytes_per_packet);
5426           GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
5427               stream->bytes_per_frame);
5428           GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
5429               stream->bytes_per_sample);
5430
5431           if (!stream->sampled && stream->bytes_per_packet) {
5432             stream->samples_per_frame = (stream->bytes_per_frame /
5433                 stream->bytes_per_packet) * stream->samples_per_packet;
5434             GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
5435                 stream->samples_per_frame);
5436           }
5437           break;
5438         }
5439       }
5440     } else if (version == 0x00020000) {
5441       union
5442       {
5443         gdouble fp;
5444         guint64 val;
5445       } qtfp;
5446
5447       stream->samples_per_packet = QT_UINT32 (stsd_data + offset);
5448       qtfp.val = QT_UINT64 (stsd_data + offset + 4);
5449       stream->rate = qtfp.fp;
5450       stream->n_channels = QT_UINT32 (stsd_data + offset + 12);
5451
5452       GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
5453           stream->samples_per_packet);
5454       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", stream->rate);
5455       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", stream->n_channels);
5456
5457     } else {
5458       GST_WARNING_OBJECT (qtdemux, "unknown version %08x", version);
5459     }
5460
5461     stream->caps = qtdemux_audio_caps (qtdemux, stream, fourcc, NULL, 0,
5462         &codec);
5463
5464     switch (fourcc) {
5465       case FOURCC_in24:
5466       {
5467         GNode *enda;
5468         GNode *in24;
5469
5470         in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
5471
5472         enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
5473         if (!enda) {
5474           wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
5475           if (wave)
5476             enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
5477         }
5478         if (enda) {
5479           gst_caps_set_simple (stream->caps,
5480               "endianness", G_TYPE_INT, G_LITTLE_ENDIAN, NULL);
5481         }
5482         break;
5483       }
5484       default:
5485         break;
5486     }
5487
5488     if (codec) {
5489       list = gst_tag_list_new ();
5490       gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
5491           GST_TAG_AUDIO_CODEC, codec, NULL);
5492       g_free (codec);
5493       codec = NULL;
5494     }
5495
5496     mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4a);
5497     wave = NULL;
5498     esds = NULL;
5499     if (mp4a) {
5500       wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
5501       if (wave)
5502         esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
5503       if (!esds)
5504         esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
5505     }
5506
5507
5508     /* If the fourcc's bottom 16 bits gives 'sm', then the top
5509        16 bits is a byte-swapped wave-style codec identifier,
5510        and we can find a WAVE header internally to a 'wave' atom here.
5511        This can more clearly be thought of as 'ms' as the top 16 bits, and a
5512        codec id as the bottom 16 bits - but byte-swapped to store in QT (which
5513        is big-endian).
5514      */
5515     if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
5516       if (len < offset + 20) {
5517         GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
5518       } else {
5519         guint32 datalen = QT_UINT32 (stsd_data + offset + 16);
5520         const guint8 *data = stsd_data + offset + 16;
5521         GNode *wavenode;
5522         GNode *waveheadernode;
5523
5524         wavenode = g_node_new ((guint8 *) data);
5525         if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
5526           const guint8 *waveheader;
5527           guint32 headerlen;
5528
5529           waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
5530           waveheader = (const guint8 *) waveheadernode->data;
5531           headerlen = QT_UINT32 (waveheader);
5532
5533           if (headerlen > 8) {
5534             gst_riff_strf_auds *header = NULL;
5535             GstBuffer *headerbuf;
5536             GstBuffer *extra;
5537
5538             waveheader += 8;
5539             headerlen -= 8;
5540
5541             headerbuf = gst_buffer_new ();
5542             GST_BUFFER_DATA (headerbuf) = (guint8 *) waveheader;
5543             GST_BUFFER_SIZE (headerbuf) = headerlen;
5544
5545             if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
5546                     headerbuf, &header, &extra)) {
5547               gst_caps_unref (stream->caps);
5548               stream->caps = gst_riff_create_audio_caps (header->format, NULL,
5549                   header, extra, NULL, NULL);
5550
5551               if (extra)
5552                 gst_buffer_unref (extra);
5553             }
5554           }
5555         }
5556         g_node_destroy (wavenode);
5557       }
5558     } else if (esds) {
5559       gst_qtdemux_handle_esds (qtdemux, stream, esds, list);
5560     } else {
5561       switch (fourcc) {
5562 #if 0
5563           /* FIXME: what is in the chunk? */
5564         case FOURCC_QDMC:
5565         {
5566           gint len = QT_UINT32 (stsd_data);
5567
5568           /* seems to be always = 116 = 0x74 */
5569           break;
5570         }
5571 #endif
5572         case FOURCC_QDM2:
5573         {
5574           gint len = QT_UINT32 (stsd_data);
5575
5576           if (len > 0x4C) {
5577             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x4C);
5578
5579             memcpy (GST_BUFFER_DATA (buf), stsd_data + 0x4C, len - 0x4C);
5580             gst_caps_set_simple (stream->caps,
5581                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
5582             gst_buffer_unref (buf);
5583           }
5584           gst_caps_set_simple (stream->caps,
5585               "samplesize", G_TYPE_INT, samplesize, NULL);
5586           break;
5587         }
5588         case FOURCC_alac:
5589         {
5590           gint len = QT_UINT32 (stsd_data);
5591
5592           if (len >= 132) {
5593             GstBuffer *buf = gst_buffer_new_and_alloc (36);
5594             memcpy (GST_BUFFER_DATA (buf), stsd_data + 88, 36);
5595             gst_caps_set_simple (stream->caps,
5596                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
5597             gst_buffer_unref (buf);
5598           }
5599           gst_caps_set_simple (stream->caps,
5600               "samplesize", G_TYPE_INT, samplesize, NULL);
5601           break;
5602         }
5603         case FOURCC_samr:
5604         {
5605           gint len = QT_UINT32 (stsd_data);
5606
5607           if (len > 0x34) {
5608             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x34);
5609
5610             memcpy (GST_BUFFER_DATA (buf), stsd_data + 0x34, len - 0x34);
5611
5612             gst_caps_set_simple (stream->caps,
5613                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
5614             gst_buffer_unref (buf);
5615           }
5616           break;
5617         }
5618         default:
5619           break;
5620       }
5621     }
5622     GST_INFO_OBJECT (qtdemux,
5623         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
5624         GST_FOURCC_ARGS (fourcc), stream->caps);
5625
5626   } else if (stream->subtype == FOURCC_strm) {
5627     if (fourcc != FOURCC_rtsp) {
5628       GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
5629           GST_FOURCC_ARGS (fourcc));
5630       goto unknown_stream;
5631     }
5632     stream->sampled = TRUE;
5633   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text) {
5634
5635     stream->sampled = TRUE;
5636
5637     offset = 16;
5638
5639     stream->caps =
5640         qtdemux_sub_caps (qtdemux, stream, fourcc, stsd_data, &codec);
5641     if (codec) {
5642       list = gst_tag_list_new ();
5643       gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
5644           GST_TAG_SUBTITLE_CODEC, codec, NULL);
5645       g_free (codec);
5646       codec = NULL;
5647     }
5648
5649     /* hunt for sort-of codec data */
5650     switch (fourcc) {
5651       case FOURCC_mp4s:
5652       {
5653         guint len;
5654         const guint8 *data;
5655
5656         /* look for palette */
5657         /* target mp4s atom */
5658         len = QT_UINT32 (stsd_data + offset);
5659         data = stsd_data + offset;
5660         /* verify sufficient length,
5661          * and esds present with decConfigDescr of expected size and position */
5662         if ((len >= 106 + 8)
5663             && (QT_FOURCC (data + 8 + 8 + 4) == FOURCC_esds)
5664             && (QT_UINT16 (data + 8 + 40) == 0x0540)) {
5665           GstStructure *s;
5666           guint32 clut[16];
5667           gint i;
5668
5669           /* move to decConfigDescr data */
5670           data = data + 8 + 42;
5671           for (i = 0; i < 16; i++) {
5672             clut[i] = QT_UINT32 (data);
5673             data += 4;
5674           }
5675
5676           s = gst_structure_new ("application/x-gst-dvd", "event",
5677               G_TYPE_STRING, "dvd-spu-clut-change",
5678               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
5679               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
5680               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
5681               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
5682               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
5683               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
5684               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
5685               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
5686               NULL);
5687
5688           /* store event and trigger custom processing */
5689           stream->pending_event =
5690               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
5691           stream->need_process = TRUE;
5692         }
5693         break;
5694       }
5695       default:
5696         break;
5697     }
5698   } else {
5699     goto unknown_stream;
5700   }
5701
5702   /* promote to sampled format */
5703   if (stream->fourcc == FOURCC_samr) {
5704     /* force mono 8000 Hz for AMR */
5705     stream->sampled = TRUE;
5706     stream->n_channels = 1;
5707     stream->rate = 8000;
5708   } else if (stream->fourcc == FOURCC_sawb) {
5709     /* force mono 16000 Hz for AMR-WB */
5710     stream->sampled = TRUE;
5711     stream->n_channels = 1;
5712     stream->rate = 16000;
5713   } else if (stream->fourcc == FOURCC_mp4a) {
5714     stream->sampled = TRUE;
5715   }
5716
5717   /* collect sample information */
5718   if (!qtdemux_stbl_init (qtdemux, stream, stbl)
5719       || !qtdemux_parse_samples (qtdemux, stream, 0))
5720     goto samples_failed;
5721
5722   /* configure segments */
5723   if (!qtdemux_parse_segments (qtdemux, stream, trak))
5724     goto segments_failed;
5725
5726   /* add some language tag, if useful */
5727   if (stream->lang_code && strcmp (stream->lang_id, "unk") &&
5728       strcmp (stream->lang_id, "und")) {
5729     const gchar *lang_code;
5730
5731     if (!list)
5732       list = gst_tag_list_new ();
5733
5734     /* convert ISO 639-2 code to ISO 639-1 */
5735     lang_code = gst_tag_get_language_code (stream->lang_id);
5736     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
5737         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
5738   }
5739
5740   /* now we are ready to add the stream */
5741   gst_qtdemux_add_stream (qtdemux, stream, list);
5742
5743   return TRUE;
5744
5745 /* ERRORS */
5746 corrupt_file:
5747   {
5748     GST_ELEMENT_ERROR (qtdemux, STREAM, DECODE,
5749         (_("This file is corrupt and cannot be played.")), (NULL));
5750     g_free (stream);
5751     return FALSE;
5752   }
5753 error_encrypted:
5754   {
5755     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
5756     g_free (stream);
5757     return FALSE;
5758   }
5759 samples_failed:
5760 segments_failed:
5761   {
5762     /* we posted an error already */
5763     /* free stbl sub-atoms */
5764     gst_qtdemux_stbl_free (stream);
5765     g_free (stream);
5766     return FALSE;
5767   }
5768 unknown_stream:
5769   {
5770     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
5771         GST_FOURCC_ARGS (stream->subtype));
5772     g_free (stream);
5773     return TRUE;
5774   }
5775 }
5776
5777 /* check if major or compatible brand is 3GP */
5778 static inline gboolean
5779 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
5780 {
5781   if (major) {
5782     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
5783         GST_MAKE_FOURCC ('3', 'g', 0, 0));
5784   } else if (qtdemux->comp_brands != NULL) {
5785     guint8 *data = GST_BUFFER_DATA (qtdemux->comp_brands);
5786     guint size = GST_BUFFER_SIZE (qtdemux->comp_brands);
5787     gboolean res = FALSE;
5788
5789     while (size >= 4) {
5790       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
5791           GST_MAKE_FOURCC ('3', 'g', 0, 0));
5792       data += 4;
5793       size -= 4;
5794     }
5795     return res;
5796   } else {
5797     return FALSE;
5798   }
5799 }
5800
5801 /* check if tag is a spec'ed 3GP tag keyword storing a string */
5802 static inline gboolean
5803 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
5804 {
5805   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
5806       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
5807       || fourcc == FOURCC_albm;
5808 }
5809
5810 static void
5811 qtdemux_tag_add_location (GstQTDemux * qtdemux, const char *tag,
5812     const char *dummy, GNode * node)
5813 {
5814   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
5815   int offset;
5816   char *name;
5817   gchar *data;
5818   gdouble longitude, latitude, altitude;
5819   gint len;
5820
5821   len = QT_UINT32 (node->data);
5822   if (len <= 14)
5823     goto short_read;
5824
5825   data = node->data;
5826   offset = 14;
5827
5828   /* TODO: language code skipped */
5829
5830   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
5831
5832   if (!name) {
5833     /* do not alarm in trivial case, but bail out otherwise */
5834     if (*(data + offset) != 0) {
5835       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
5836           "giving up", tag);
5837     }
5838   } else {
5839     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
5840         GST_TAG_GEO_LOCATION_NAME, name, NULL);
5841     offset += strlen (name);
5842     g_free (name);
5843   }
5844
5845   if (len < offset + 2 + 4 + 4 + 4)
5846     goto short_read;
5847
5848   /* +1 +1 = skip null-terminator and location role byte */
5849   offset += 1 + 1;
5850   longitude = QT_FP32 (data + offset);
5851
5852   offset += 4;
5853   latitude = QT_FP32 (data + offset);
5854
5855   offset += 4;
5856   altitude = QT_FP32 (data + offset);
5857
5858   /* one invalid means all are invalid */
5859   if (longitude >= -180.0 && longitude <= 180.0 &&
5860       latitude >= -90.0 && latitude <= 90.0) {
5861     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
5862         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
5863         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
5864         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
5865   }
5866
5867   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
5868
5869   return;
5870
5871   /* ERRORS */
5872 short_read:
5873   {
5874     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
5875     return;
5876   }
5877 }
5878
5879
5880 static void
5881 qtdemux_tag_add_year (GstQTDemux * qtdemux, const char *tag, const char *dummy,
5882     GNode * node)
5883 {
5884   guint16 y;
5885   GDate *date;
5886   gint len;
5887
5888   len = QT_UINT32 (node->data);
5889   if (len < 14)
5890     return;
5891
5892   y = QT_UINT16 ((guint8 *) node->data + 12);
5893   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
5894
5895   date = g_date_new_dmy (1, 1, y);
5896   gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag, date, NULL);
5897   g_date_free (date);
5898 }
5899
5900 static void
5901 qtdemux_tag_add_classification (GstQTDemux * qtdemux, const char *tag,
5902     const char *dummy, GNode * node)
5903 {
5904   int offset;
5905   char *tag_str = NULL;
5906   guint8 *entity;
5907   guint16 table;
5908   gint len;
5909
5910   len = QT_UINT32 (node->data);
5911   if (len <= 20)
5912     goto short_read;
5913
5914   offset = 12;
5915   entity = (guint8 *) node->data + offset;
5916
5917   offset += 4;
5918   table = QT_UINT16 ((guint8 *) node->data + offset);
5919
5920   /* Language code skipped */
5921
5922   offset += 4;
5923
5924   /* Tag format: "XXXX://Y[YYYY]/classification info string"
5925    * XXXX: classification entity, fixed length 4 chars.
5926    * Y[YYYY]: classification table, max 5 chars.
5927    */
5928   tag_str = g_strdup_printf ("----://%u/%s",
5929       table, (char *) node->data + offset);
5930
5931   /* memcpy To be sure we're preserving byte order */
5932   memcpy (tag_str, entity, 4);
5933   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
5934
5935   gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_APPEND, tag,
5936       tag_str, NULL);
5937
5938   g_free (tag_str);
5939
5940   return;
5941
5942   /* ERRORS */
5943 short_read:
5944   {
5945     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
5946     return;
5947   }
5948 }
5949
5950 static gboolean
5951 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, const char *tag,
5952     const char *dummy, GNode * node)
5953 {
5954   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
5955   GNode *data;
5956   char *s;
5957   int len;
5958   guint32 type;
5959   int offset;
5960   gboolean ret = TRUE;
5961
5962   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
5963   if (data) {
5964     len = QT_UINT32 (data->data);
5965     type = QT_UINT32 ((guint8 *) data->data + 8);
5966     if (type == 0x00000001 && len > 16) {
5967       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
5968           env_vars);
5969       if (s) {
5970         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
5971         gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag, s,
5972             NULL);
5973         g_free (s);
5974       } else {
5975         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
5976       }
5977     }
5978   } else {
5979     len = QT_UINT32 (node->data);
5980     type = QT_UINT32 ((guint8 *) node->data + 4);
5981     if ((type >> 24) == 0xa9) {
5982       /* Type starts with the (C) symbol, so the next 32 bits are
5983        * the language code, which we ignore */
5984       offset = 12;
5985       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
5986     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
5987             QT_FOURCC ((guint8 *) node->data + 4))) {
5988       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
5989
5990       /* we go for 3GP style encoding if major brands claims so,
5991        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
5992       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
5993           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
5994               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
5995         offset = 14;
5996         /* 16-bit Language code is ignored here as well */
5997         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
5998       } else {
5999         goto normal;
6000       }
6001     } else {
6002     normal:
6003       offset = 8;
6004       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
6005       ret = FALSE;              /* may have to fallback */
6006     }
6007     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
6008         len - offset, env_vars);
6009     if (s) {
6010       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
6011       gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag, s, NULL);
6012       g_free (s);
6013       ret = TRUE;
6014     } else {
6015       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
6016     }
6017   }
6018   return ret;
6019 }
6020
6021 static void
6022 qtdemux_tag_add_str (GstQTDemux * qtdemux, const char *tag,
6023     const char *dummy, GNode * node)
6024 {
6025   qtdemux_tag_add_str_full (qtdemux, tag, dummy, node);
6026 }
6027
6028 static void
6029 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, const char *tag,
6030     const char *dummy, GNode * node)
6031 {
6032   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
6033   guint8 *data;
6034   char *s, *t, *k = NULL;
6035   int len;
6036   int offset;
6037   int count;
6038
6039   /* first try normal string tag if major brand not 3GP */
6040   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
6041     if (!qtdemux_tag_add_str_full (qtdemux, tag, dummy, node)) {
6042       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
6043        * let's try it 3gpp way after minor safety check */
6044       data = node->data;
6045       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
6046         return;
6047     } else
6048       return;
6049   }
6050
6051   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
6052
6053   data = node->data;
6054
6055   len = QT_UINT32 (data);
6056   if (len < 15)
6057     goto short_read;
6058
6059   count = QT_UINT8 (data + 14);
6060   offset = 15;
6061   for (; count; count--) {
6062     gint slen;
6063
6064     if (offset + 1 > len)
6065       goto short_read;
6066     slen = QT_UINT8 (data + offset);
6067     offset += 1;
6068     if (offset + slen > len)
6069       goto short_read;
6070     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
6071         slen, env_vars);
6072     if (s) {
6073       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
6074       if (k) {
6075         t = g_strjoin (",", k, s, NULL);
6076         g_free (s);
6077         g_free (k);
6078         k = t;
6079       } else {
6080         k = s;
6081       }
6082     } else {
6083       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
6084     }
6085     offset += slen;
6086   }
6087
6088 done:
6089   if (k) {
6090     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
6091     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag, k, NULL);
6092   }
6093   g_free (k);
6094
6095   return;
6096
6097   /* ERRORS */
6098 short_read:
6099   {
6100     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
6101     goto done;
6102   }
6103 }
6104
6105 static void
6106 qtdemux_tag_add_num (GstQTDemux * qtdemux, const char *tag1,
6107     const char *tag2, GNode * node)
6108 {
6109   GNode *data;
6110   int len;
6111   int type;
6112   int n1, n2;
6113
6114   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
6115   if (data) {
6116     len = QT_UINT32 (data->data);
6117     type = QT_UINT32 ((guint8 *) data->data + 8);
6118     if (type == 0x00000000 && len >= 22) {
6119       n1 = QT_UINT16 ((guint8 *) data->data + 18);
6120       n2 = QT_UINT16 ((guint8 *) data->data + 20);
6121       if (n1 > 0) {
6122         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
6123         gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
6124             tag1, n1, NULL);
6125       }
6126       if (n2 > 0) {
6127         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
6128         gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
6129             tag2, n2, NULL);
6130       }
6131     }
6132   }
6133 }
6134
6135 static void
6136 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, const char *tag1, const char *dummy,
6137     GNode * node)
6138 {
6139   GNode *data;
6140   int len;
6141   int type;
6142   int n1;
6143
6144   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
6145   if (data) {
6146     len = QT_UINT32 (data->data);
6147     type = QT_UINT32 ((guint8 *) data->data + 8);
6148     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
6149     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
6150     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
6151       n1 = QT_UINT16 ((guint8 *) data->data + 16);
6152       if (n1) {
6153         /* do not add bpm=0 */
6154         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
6155         gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
6156             tag1, (gdouble) n1, NULL);
6157       }
6158     }
6159   }
6160 }
6161
6162 static void
6163 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, const char *tag1,
6164     const char *dummy, GNode * node)
6165 {
6166   GNode *data;
6167   int len;
6168   int type;
6169   guint32 num;
6170
6171   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
6172   if (data) {
6173     len = QT_UINT32 (data->data);
6174     type = QT_UINT32 ((guint8 *) data->data + 8);
6175     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
6176     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
6177     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
6178       num = QT_UINT32 ((guint8 *) data->data + 16);
6179       if (num) {
6180         /* do not add num=0 */
6181         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
6182         gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
6183             tag1, num, NULL);
6184       }
6185     }
6186   }
6187 }
6188
6189 static void
6190 qtdemux_tag_add_covr (GstQTDemux * qtdemux, const char *tag1, const char *dummy,
6191     GNode * node)
6192 {
6193   GNode *data;
6194   int len;
6195   int type;
6196   GstBuffer *buf;
6197
6198   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
6199   if (data) {
6200     len = QT_UINT32 (data->data);
6201     type = QT_UINT32 ((guint8 *) data->data + 8);
6202     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
6203     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
6204       if ((buf = gst_tag_image_data_to_image_buffer ((guint8 *) data->data + 16,
6205                   len - 16, GST_TAG_IMAGE_TYPE_NONE))) {
6206         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
6207         gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
6208             tag1, buf, NULL);
6209         gst_buffer_unref (buf);
6210       }
6211     }
6212   }
6213 }
6214
6215 static void
6216 qtdemux_tag_add_date (GstQTDemux * qtdemux, const char *tag, const char *dummy,
6217     GNode * node)
6218 {
6219   GNode *data;
6220   char *s;
6221   int len;
6222   int type;
6223
6224   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
6225   if (data) {
6226     len = QT_UINT32 (data->data);
6227     type = QT_UINT32 ((guint8 *) data->data + 8);
6228     if (type == 0x00000001 && len > 16) {
6229       guint y, m = 1, d = 1;
6230       gint ret;
6231
6232       s = g_strndup ((char *) data->data + 16, len - 16);
6233       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
6234       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
6235       if (ret >= 1 && y > 1500 && y < 3000) {
6236         GDate *date;
6237
6238         date = g_date_new_dmy (d, m, y);
6239         gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag,
6240             date, NULL);
6241         g_date_free (date);
6242       } else {
6243         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
6244       }
6245       g_free (s);
6246     }
6247   }
6248 }
6249
6250 static void
6251 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, const char *tag, const char *dummy,
6252     GNode * node)
6253 {
6254   GNode *data;
6255
6256   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
6257
6258   /* re-route to normal string tag if major brand says so
6259    * or no data atom and compatible brand suggests so */
6260   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
6261       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
6262     qtdemux_tag_add_str (qtdemux, tag, dummy, node);
6263     return;
6264   }
6265
6266   if (data) {
6267     guint len, type, n;
6268
6269     len = QT_UINT32 (data->data);
6270     type = QT_UINT32 ((guint8 *) data->data + 8);
6271     if (type == 0x00000000 && len >= 18) {
6272       n = QT_UINT16 ((guint8 *) data->data + 16);
6273       if (n > 0) {
6274         const gchar *genre;
6275
6276         genre = gst_tag_id3_genre_get (n - 1);
6277         if (genre != NULL) {
6278           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
6279           gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
6280               tag, genre, NULL);
6281         }
6282       }
6283     }
6284   }
6285 }
6286
6287 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux,
6288     const char *tag, const char *tag_bis, GNode * node);
6289
6290 /* unmapped tags
6291 FOURCC_pcst -> if media is a podcast -> bool
6292 FOURCC_cpil -> if media is part of a compilation -> bool
6293 FOURCC_pgap -> if media is part of a gapless context -> bool
6294 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
6295 */
6296
6297 static const struct
6298 {
6299   guint32 fourcc;
6300   const gchar *gst_tag;
6301   const gchar *gst_tag_bis;
6302   const GstQTDemuxAddTagFunc func;
6303 } add_funcs[] = {
6304   {
6305   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
6306   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
6307   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
6308   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
6309   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
6310   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
6311   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
6312   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
6313   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
6314   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
6315   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
6316   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
6317   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
6318   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
6319   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
6320   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
6321   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
6322   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
6323   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
6324   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
6325   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
6326   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
6327   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
6328         qtdemux_tag_add_num}, {
6329   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
6330         qtdemux_tag_add_num}, {
6331   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
6332   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
6333   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
6334   FOURCC_covr, GST_TAG_PREVIEW_IMAGE, NULL, qtdemux_tag_add_covr}, {
6335   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
6336   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
6337   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
6338   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
6339   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
6340   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
6341   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
6342   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
6343   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
6344   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
6345   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
6346   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
6347   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
6348   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
6349         qtdemux_tag_add_classification}
6350 };
6351
6352 static void
6353 qtdemux_tag_add_blob (GNode * node, GstQTDemux * demux)
6354 {
6355   gint len;
6356   guint8 *data;
6357   GstBuffer *buf;
6358   gchar *media_type, *style;
6359   GstCaps *caps;
6360   guint i;
6361   guint8 ndata[4];
6362
6363   data = node->data;
6364   len = QT_UINT32 (data);
6365   buf = gst_buffer_new_and_alloc (len);
6366   memcpy (GST_BUFFER_DATA (buf), data, len);
6367
6368   /* heuristic to determine style of tag */
6369   if (QT_FOURCC (data + 4) == FOURCC_____ ||
6370       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
6371     style = "itunes";
6372   else if (demux->major_brand == FOURCC_qt__)
6373     style = "quicktime";
6374   /* fall back to assuming iso/3gp tag style */
6375   else
6376     style = "iso";
6377
6378   /* santize the name for the caps. */
6379   for (i = 0; i < 4; i++) {
6380     guint8 d = data[4 + i];
6381     if (g_ascii_isalnum (d))
6382       ndata[i] = g_ascii_tolower (d);
6383     else
6384       ndata[i] = '_';
6385   }
6386
6387   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
6388       ndata[0], ndata[1], ndata[2], ndata[3]);
6389   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
6390
6391   caps = gst_caps_new_simple (media_type, "style", G_TYPE_STRING, style, NULL);
6392   gst_buffer_set_caps (buf, caps);
6393   gst_caps_unref (caps);
6394   g_free (media_type);
6395
6396   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, caps %" GST_PTR_FORMAT,
6397       GST_BUFFER_SIZE (buf), caps);
6398
6399   gst_tag_list_add (demux->tag_list, GST_TAG_MERGE_APPEND,
6400       GST_QT_DEMUX_PRIVATE_TAG, buf, NULL);
6401   gst_buffer_unref (buf);
6402 }
6403
6404 static void
6405 qtdemux_parse_udta (GstQTDemux * qtdemux, GNode * udta)
6406 {
6407   GNode *meta;
6408   GNode *ilst;
6409   GNode *node;
6410   gint i;
6411
6412   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
6413   if (meta != NULL) {
6414     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
6415     if (ilst == NULL) {
6416       GST_LOG_OBJECT (qtdemux, "no ilst");
6417       return;
6418     }
6419   } else {
6420     ilst = udta;
6421     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
6422   }
6423
6424   GST_DEBUG_OBJECT (qtdemux, "new tag list");
6425   qtdemux->tag_list = gst_tag_list_new ();
6426
6427   for (i = 0; i < G_N_ELEMENTS (add_funcs); ++i) {
6428     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
6429     if (node) {
6430       gint len;
6431
6432       len = QT_UINT32 (node->data);
6433       if (len < 12) {
6434         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
6435             GST_FOURCC_ARGS (add_funcs[i].fourcc));
6436       } else {
6437         add_funcs[i].func (qtdemux, add_funcs[i].gst_tag,
6438             add_funcs[i].gst_tag_bis, node);
6439       }
6440       g_node_destroy (node);
6441     }
6442   }
6443
6444   /* parsed nodes have been removed, pass along remainder as blob */
6445   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
6446       (GNodeForeachFunc) qtdemux_tag_add_blob, qtdemux);
6447
6448 }
6449
6450 typedef struct
6451 {
6452   GstStructure *structure;      /* helper for sort function */
6453   gchar *location;
6454   guint min_req_bitrate;
6455   guint min_req_qt_version;
6456 } GstQtReference;
6457
6458 static gint
6459 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
6460 {
6461   GstQtReference *ref_a = (GstQtReference *) a;
6462   GstQtReference *ref_b = (GstQtReference *) b;
6463
6464   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
6465     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
6466
6467   /* known bitrates go before unknown; higher bitrates go first */
6468   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
6469 }
6470
6471 /* sort the redirects and post a message for the application.
6472  */
6473 static void
6474 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
6475 {
6476   GstQtReference *best;
6477   GstStructure *s;
6478   GstMessage *msg;
6479   GValue list_val = { 0, };
6480   GList *l;
6481
6482   g_assert (references != NULL);
6483
6484   references = g_list_sort (references, qtdemux_redirects_sort_func);
6485
6486   best = (GstQtReference *) references->data;
6487
6488   g_value_init (&list_val, GST_TYPE_LIST);
6489
6490   for (l = references; l != NULL; l = l->next) {
6491     GstQtReference *ref = (GstQtReference *) l->data;
6492     GValue struct_val = { 0, };
6493
6494     ref->structure = gst_structure_new ("redirect",
6495         "new-location", G_TYPE_STRING, ref->location, NULL);
6496
6497     if (ref->min_req_bitrate > 0) {
6498       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
6499           ref->min_req_bitrate, NULL);
6500     }
6501
6502     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
6503     g_value_set_boxed (&struct_val, ref->structure);
6504     gst_value_list_append_value (&list_val, &struct_val);
6505     g_value_unset (&struct_val);
6506     /* don't free anything here yet, since we need best->structure below */
6507   }
6508
6509   g_assert (best != NULL);
6510   s = gst_structure_copy (best->structure);
6511
6512   if (g_list_length (references) > 1) {
6513     gst_structure_set_value (s, "locations", &list_val);
6514   }
6515
6516   g_value_unset (&list_val);
6517
6518   for (l = references; l != NULL; l = l->next) {
6519     GstQtReference *ref = (GstQtReference *) l->data;
6520
6521     gst_structure_free (ref->structure);
6522     g_free (ref->location);
6523     g_free (ref);
6524   }
6525   g_list_free (references);
6526
6527   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
6528   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
6529   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
6530 }
6531
6532 /* look for redirect nodes, collect all redirect information and
6533  * process it.
6534  */
6535 static gboolean
6536 qtdemux_parse_redirects (GstQTDemux * qtdemux)
6537 {
6538   GNode *rmra, *rmda, *rdrf;
6539
6540   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
6541   if (rmra) {
6542     GList *redirects = NULL;
6543
6544     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
6545     while (rmda) {
6546       GstQtReference ref = { NULL, NULL, 0, 0 };
6547       GNode *rmdr, *rmvc;
6548
6549       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
6550         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
6551         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
6552             ref.min_req_bitrate);
6553       }
6554
6555       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
6556         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
6557         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
6558
6559 #ifndef GST_DISABLE_GST_DEBUG
6560         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
6561 #endif
6562         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
6563
6564         GST_LOG_OBJECT (qtdemux,
6565             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
6566             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
6567             bitmask, check_type);
6568         if (package == FOURCC_qtim && check_type == 0) {
6569           ref.min_req_qt_version = version;
6570         }
6571       }
6572
6573       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
6574       if (rdrf) {
6575         guint32 ref_type;
6576         guint8 *ref_data;
6577
6578         ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
6579         ref_data = (guint8 *) rdrf->data + 20;
6580         if (ref_type == FOURCC_alis) {
6581           guint record_len, record_version, fn_len;
6582
6583           /* MacOSX alias record, google for alias-layout.txt */
6584           record_len = QT_UINT16 (ref_data + 4);
6585           record_version = QT_UINT16 (ref_data + 4 + 2);
6586           fn_len = QT_UINT8 (ref_data + 50);
6587           if (record_len > 50 && record_version == 2 && fn_len > 0) {
6588             ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
6589           }
6590         } else if (ref_type == FOURCC_url_) {
6591           ref.location = g_strdup ((gchar *) ref_data);
6592         } else {
6593           GST_DEBUG_OBJECT (qtdemux,
6594               "unknown rdrf reference type %" GST_FOURCC_FORMAT,
6595               GST_FOURCC_ARGS (ref_type));
6596         }
6597         if (ref.location != NULL) {
6598           GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
6599           redirects = g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
6600         } else {
6601           GST_WARNING_OBJECT (qtdemux,
6602               "Failed to extract redirect location from rdrf atom");
6603         }
6604       }
6605
6606       /* look for others */
6607       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
6608     }
6609
6610     if (redirects != NULL) {
6611       qtdemux_process_redirects (qtdemux, redirects);
6612     }
6613   }
6614   return TRUE;
6615 }
6616
6617 static GstTagList *
6618 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
6619 {
6620   const gchar *fmt;
6621
6622   if (tags == NULL)
6623     tags = gst_tag_list_new ();
6624
6625   if (qtdemux->major_brand == FOURCC_mjp2)
6626     fmt = "Motion JPEG 2000";
6627   else if ((qtdemux->major_brand & 0xffff) == GST_MAKE_FOURCC ('3', 'g', 0, 0))
6628     fmt = "3GP";
6629   else if (qtdemux->major_brand == FOURCC_qt__)
6630     fmt = "Quicktime";
6631   else
6632     fmt = "ISO MP4/M4A";
6633
6634   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
6635       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
6636
6637   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
6638       fmt, NULL);
6639
6640   return tags;
6641 }
6642
6643 /* we have read th complete moov node now.
6644  * This function parses all of the relevant info, creates the traks and
6645  * prepares all data structures for playback
6646  */
6647 static gboolean
6648 qtdemux_parse_tree (GstQTDemux * qtdemux)
6649 {
6650   GNode *mvhd;
6651   GNode *trak;
6652   GNode *udta;
6653   gint64 duration;
6654
6655   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
6656   if (mvhd == NULL) {
6657     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
6658     return qtdemux_parse_redirects (qtdemux);
6659   }
6660
6661   qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
6662   qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
6663
6664   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
6665   GST_INFO_OBJECT (qtdemux, "duration: %u", qtdemux->duration);
6666
6667   /* set duration in the segment info */
6668   gst_qtdemux_get_duration (qtdemux, &duration);
6669   gst_segment_set_duration (&qtdemux->segment, GST_FORMAT_TIME, duration);
6670
6671   /* parse all traks */
6672   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
6673   while (trak) {
6674     qtdemux_parse_trak (qtdemux, trak);
6675     /* iterate all siblings */
6676     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
6677   }
6678   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
6679
6680   /* find and push tags, we do this after adding the pads so we can push the
6681    * tags downstream as well. */
6682   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
6683   if (udta) {
6684     qtdemux_parse_udta (qtdemux, udta);
6685   } else {
6686     GST_LOG_OBJECT (qtdemux, "No udta node found.");
6687   }
6688
6689   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
6690   GST_INFO_OBJECT (qtdemux, "posting global tags: %" GST_PTR_FORMAT,
6691       qtdemux->tag_list);
6692   /* post now, send event on pads later */
6693   gst_element_post_message (GST_ELEMENT (qtdemux),
6694       gst_message_new_tag (GST_OBJECT (qtdemux),
6695           gst_tag_list_copy (qtdemux->tag_list)));
6696
6697   return TRUE;
6698 }
6699
6700 /* taken from ffmpeg */
6701 static unsigned int
6702 get_size (guint8 * ptr, guint8 ** end)
6703 {
6704   int count = 4;
6705   int len = 0;
6706
6707   while (count--) {
6708     int c = *ptr;
6709
6710     ptr++;
6711     len = (len << 7) | (c & 0x7f);
6712     if (!(c & 0x80))
6713       break;
6714   }
6715   if (end)
6716     *end = ptr;
6717   return len;
6718 }
6719
6720 /* this can change the codec originally present in @list */
6721 static void
6722 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
6723     GNode * esds, GstTagList * list)
6724 {
6725   int len = QT_UINT32 (esds->data);
6726   guint8 *ptr = esds->data;
6727   guint8 *end = ptr + len;
6728   int tag;
6729   guint8 *data_ptr = NULL;
6730   int data_len = 0;
6731   guint8 object_type_id = 0;
6732   char *codec_name = NULL;
6733   GstCaps *caps = NULL;
6734
6735   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
6736   ptr += 8;
6737   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
6738   ptr += 4;
6739   while (ptr < end) {
6740     tag = QT_UINT8 (ptr);
6741     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
6742     ptr++;
6743     len = get_size (ptr, &ptr);
6744     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
6745
6746     switch (tag) {
6747       case 0x03:
6748         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
6749         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
6750         ptr += 3;
6751         break;
6752       case 0x04:{
6753         guint max_bitrate, avg_bitrate;
6754
6755         object_type_id = QT_UINT8 (ptr);
6756         max_bitrate = QT_UINT32 (ptr + 5);
6757         avg_bitrate = QT_UINT32 (ptr + 9);
6758         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
6759         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
6760         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
6761         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
6762         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
6763         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
6764           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
6765               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
6766         }
6767         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
6768           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
6769               avg_bitrate, NULL);
6770         }
6771         ptr += 13;
6772         break;
6773       }
6774       case 0x05:
6775         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
6776         data_ptr = ptr;
6777         data_len = len;
6778         ptr += len;
6779         break;
6780       case 0x06:
6781         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
6782         ptr += 1;
6783         break;
6784       default:
6785         GST_ERROR_OBJECT (qtdemux, "parse error");
6786         break;
6787     }
6788   }
6789
6790   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
6791    * in use, and should also be used to override some other parameters for some
6792    * codecs. */
6793   switch (object_type_id) {
6794     case 0x20:                 /* MPEG-4 */
6795       break;                    /* Nothing special needed here */
6796     case 0x21:                 /* H.264 */
6797       codec_name = "H.264 / AVC";
6798       caps = gst_caps_new_simple ("video/x-h264", NULL);
6799       break;
6800     case 0x40:                 /* AAC (any) */
6801     case 0x66:                 /* AAC Main */
6802     case 0x67:                 /* AAC LC */
6803     case 0x68:                 /* AAC SSR */
6804       /* Override channels and rate based on the codec_data, as it's often
6805        * wrong. */
6806       if (data_ptr && data_len >= 2) {
6807         guint channels, rateindex;
6808         int rates[] = { 96000, 88200, 64000, 48000, 44100, 32000,
6809           24000, 22050, 16000, 12000, 11025, 8000
6810         };
6811
6812         channels = (data_ptr[1] & 0x7f) >> 3;
6813         if (channels <= 7) {
6814           stream->n_channels = channels;
6815         }
6816
6817         rateindex = ((data_ptr[0] & 0x7) << 1) | ((data_ptr[1] & 0x80) >> 7);
6818         if (rateindex < sizeof (rates) / sizeof (*rates)) {
6819           stream->rate = rates[rateindex];
6820         }
6821       }
6822       break;
6823     case 0x60:                 /* MPEG-2, various profiles */
6824     case 0x61:
6825     case 0x62:
6826     case 0x63:
6827     case 0x64:
6828     case 0x65:
6829       codec_name = "MPEG-2 video";
6830
6831       gst_caps_unref (stream->caps);
6832       stream->caps = gst_caps_new_simple ("video/mpeg",
6833           "mpegversion", G_TYPE_INT, 2,
6834           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
6835       break;
6836     case 0x69:                 /* MP3 has two different values, accept either */
6837     case 0x6B:
6838       /* change to mpeg1 layer 3 audio */
6839       gst_caps_set_simple (stream->caps, "layer", G_TYPE_INT, 3,
6840           "mpegversion", G_TYPE_INT, 1, NULL);
6841       codec_name = "MPEG-1 layer 3";
6842       break;
6843     case 0x6A:                 /* MPEG-1 */
6844       codec_name = "MPEG-1 video";
6845
6846       gst_caps_unref (stream->caps);
6847       stream->caps = gst_caps_new_simple ("video/mpeg",
6848           "mpegversion", G_TYPE_INT, 1,
6849           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
6850       break;
6851     case 0x6C:                 /* MJPEG */
6852       caps = gst_caps_new_simple ("image/jpeg", NULL);
6853       codec_name = "Motion-JPEG";
6854       break;
6855     case 0x6D:                 /* PNG */
6856       caps = gst_caps_new_simple ("image/png", NULL);
6857       codec_name = "PNG still images";
6858       break;
6859     case 0x6E:                 /* JPEG2000 */
6860       codec_name = "JPEG-2000";
6861       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
6862       break;
6863     case 0xA4:                 /* Dirac */
6864       codec_name = "Dirac";
6865       caps = gst_caps_new_simple ("video/x-dirac", NULL);
6866       break;
6867     case 0xA5:                 /* AC3 */
6868       codec_name = "AC-3 audio";
6869       caps = gst_caps_new_simple ("audio/x-ac3", NULL);
6870       break;
6871     case 0xE1:                 /* QCELP */
6872       /* QCELP, the codec_data is a riff tag (little endian) with
6873        * 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). */
6874       caps = gst_caps_new_simple ("audio/qcelp", NULL);
6875       codec_name = "QCELP";
6876       break;
6877     default:
6878       break;
6879   }
6880
6881   /* If we have a replacement caps, then change our caps for this stream */
6882   if (caps) {
6883     gst_caps_unref (stream->caps);
6884     stream->caps = caps;
6885   }
6886
6887   if (codec_name && list)
6888     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
6889         GST_TAG_AUDIO_CODEC, codec_name, NULL);
6890
6891   /* Add the codec_data attribute to caps, if we have it */
6892   if (data_ptr) {
6893     GstBuffer *buffer;
6894
6895     buffer = gst_buffer_new_and_alloc (data_len);
6896     memcpy (GST_BUFFER_DATA (buffer), data_ptr, data_len);
6897
6898     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
6899     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
6900
6901     gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
6902         buffer, NULL);
6903     gst_buffer_unref (buffer);
6904   }
6905
6906 }
6907
6908 #define _codec(name) \
6909   do { \
6910     if (codec_name) { \
6911       *codec_name = g_strdup (name); \
6912     } \
6913   } while (0)
6914
6915 static GstCaps *
6916 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
6917     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
6918 {
6919   GstCaps *caps;
6920   const GstStructure *s;
6921   const gchar *name;
6922
6923   switch (fourcc) {
6924     case GST_MAKE_FOURCC ('p', 'n', 'g', ' '):
6925       _codec ("PNG still images");
6926       caps = gst_caps_new_simple ("image/png", NULL);
6927       break;
6928     case GST_MAKE_FOURCC ('j', 'p', 'e', 'g'):
6929       _codec ("JPEG still images");
6930       caps = gst_caps_new_simple ("image/jpeg", NULL);
6931       break;
6932     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
6933     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
6934     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
6935       _codec ("Motion-JPEG");
6936       caps = gst_caps_new_simple ("image/jpeg", NULL);
6937       break;
6938     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
6939       _codec ("Motion-JPEG format B");
6940       caps = gst_caps_new_simple ("video/x-mjpeg-b", NULL);
6941       break;
6942     case GST_MAKE_FOURCC ('m', 'j', 'p', '2'):
6943       _codec ("JPEG-2000");
6944       /* override to what it should be according to spec, avoid palette_data */
6945       stream->bits_per_sample = 24;
6946       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
6947       break;
6948     case GST_MAKE_FOURCC ('S', 'V', 'Q', '3'):
6949       _codec ("Sorensen video v.3");
6950       caps = gst_caps_new_simple ("video/x-svq",
6951           "svqversion", G_TYPE_INT, 3, NULL);
6952       break;
6953     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
6954     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
6955       _codec ("Sorensen video v.1");
6956       caps = gst_caps_new_simple ("video/x-svq",
6957           "svqversion", G_TYPE_INT, 1, NULL);
6958       break;
6959     case GST_MAKE_FOURCC ('r', 'a', 'w', ' '):
6960     {
6961       guint16 bps;
6962
6963       _codec ("Raw RGB video");
6964       bps = QT_UINT16 (stsd_data + 98);
6965       /* set common stuff */
6966       caps = gst_caps_new_simple ("video/x-raw-rgb",
6967           "endianness", G_TYPE_INT, G_BYTE_ORDER, "depth", G_TYPE_INT, bps,
6968           NULL);
6969
6970       switch (bps) {
6971         case 15:
6972           gst_caps_set_simple (caps,
6973               "bpp", G_TYPE_INT, 16,
6974               "endianness", G_TYPE_INT, G_BIG_ENDIAN,
6975               "red_mask", G_TYPE_INT, 0x7c00,
6976               "green_mask", G_TYPE_INT, 0x03e0,
6977               "blue_mask", G_TYPE_INT, 0x001f, NULL);
6978           break;
6979         case 16:
6980           gst_caps_set_simple (caps,
6981               "bpp", G_TYPE_INT, 16,
6982               "endianness", G_TYPE_INT, G_BIG_ENDIAN,
6983               "red_mask", G_TYPE_INT, 0xf800,
6984               "green_mask", G_TYPE_INT, 0x07e0,
6985               "blue_mask", G_TYPE_INT, 0x001f, NULL);
6986           break;
6987         case 24:
6988           gst_caps_set_simple (caps,
6989               "bpp", G_TYPE_INT, 24,
6990               "endianness", G_TYPE_INT, G_BIG_ENDIAN,
6991               "red_mask", G_TYPE_INT, 0xff0000,
6992               "green_mask", G_TYPE_INT, 0x00ff00,
6993               "blue_mask", G_TYPE_INT, 0x0000ff, NULL);
6994           break;
6995         case 32:
6996           gst_caps_set_simple (caps,
6997               "bpp", G_TYPE_INT, 32,
6998               "endianness", G_TYPE_INT, G_BIG_ENDIAN,
6999               "alpha_mask", G_TYPE_INT, 0xff000000,
7000               "red_mask", G_TYPE_INT, 0x00ff0000,
7001               "green_mask", G_TYPE_INT, 0x0000ff00,
7002               "blue_mask", G_TYPE_INT, 0x000000ff, NULL);
7003           break;
7004         default:
7005           /* unknown */
7006           break;
7007       }
7008       break;
7009     }
7010     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
7011       _codec ("Raw planar YUV 4:2:0");
7012       caps = gst_caps_new_simple ("video/x-raw-yuv",
7013           "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
7014           NULL);
7015       break;
7016     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
7017     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
7018       _codec ("Raw packed YUV 4:2:2");
7019       caps = gst_caps_new_simple ("video/x-raw-yuv",
7020           "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'),
7021           NULL);
7022       break;
7023     case GST_MAKE_FOURCC ('2', 'v', 'u', 'y'):
7024       _codec ("Raw packed YUV 4:2:0");
7025       caps = gst_caps_new_simple ("video/x-raw-yuv",
7026           "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'),
7027           NULL);
7028       break;
7029     case GST_MAKE_FOURCC ('v', '2', '1', '0'):
7030       _codec ("Raw packed YUV 10-bit 4:2:2");
7031       caps = gst_caps_new_simple ("video/x-raw-yuv",
7032           "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('v', '2', '1', '0'),
7033           NULL);
7034       break;
7035     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
7036     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
7037       _codec ("MPEG-1 video");
7038       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
7039           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
7040       break;
7041     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
7042     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
7043     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
7044     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
7045     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080i60 */
7046     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
7047     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
7048     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
7049     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
7050     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
7051     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
7052     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 */
7053     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
7054     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
7055       _codec ("MPEG-2 video");
7056       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
7057           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
7058       break;
7059     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
7060       _codec ("GIF still images");
7061       caps = gst_caps_new_simple ("image/gif", NULL);
7062       break;
7063     case GST_MAKE_FOURCC ('h', '2', '6', '3'):
7064     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
7065     case GST_MAKE_FOURCC ('s', '2', '6', '3'):
7066     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
7067       _codec ("H.263");
7068       /* ffmpeg uses the height/width props, don't know why */
7069       caps = gst_caps_new_simple ("video/x-h263", NULL);
7070       break;
7071     case GST_MAKE_FOURCC ('m', 'p', '4', 'v'):
7072       _codec ("MPEG-4 video");
7073       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
7074           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
7075       break;
7076     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
7077     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
7078       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
7079       caps = gst_caps_new_simple ("video/x-msmpeg",
7080           "msmpegversion", G_TYPE_INT, 43, NULL);
7081       break;
7082     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
7083     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
7084       _codec ("3ivX video");
7085       caps = gst_caps_new_simple ("video/x-3ivx", NULL);
7086       break;
7087     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
7088       _codec ("DivX 3");
7089       caps = gst_caps_new_simple ("video/x-divx",
7090           "divxversion", G_TYPE_INT, 3, NULL);
7091       break;
7092     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
7093     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
7094       _codec ("DivX 4");
7095       caps = gst_caps_new_simple ("video/x-divx",
7096           "divxversion", G_TYPE_INT, 4, NULL);
7097       break;
7098     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
7099       _codec ("DivX 5");
7100       caps = gst_caps_new_simple ("video/x-divx",
7101           "divxversion", G_TYPE_INT, 5, NULL);
7102       break;
7103     case GST_MAKE_FOURCC ('X', 'V', 'I', 'D'):
7104     case GST_MAKE_FOURCC ('x', 'v', 'i', 'd'):
7105       _codec ("XVID MPEG-4");
7106       caps = gst_caps_new_simple ("video/x-xvid", NULL);
7107       break;
7108
7109     case GST_MAKE_FOURCC ('F', 'M', 'P', '4'):
7110     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
7111       caps = gst_caps_new_simple ("video/mpeg",
7112           "mpegversion", G_TYPE_INT, 4, NULL);
7113       if (codec_name)
7114         *codec_name = g_strdup ("FFmpeg MPEG-4");
7115       break;
7116
7117     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
7118       _codec ("Cinepak");
7119       caps = gst_caps_new_simple ("video/x-cinepak", NULL);
7120       break;
7121     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
7122       _codec ("Apple QuickDraw");
7123       caps = gst_caps_new_simple ("video/x-qdrw", NULL);
7124       break;
7125     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
7126       _codec ("Apple video");
7127       caps = gst_caps_new_simple ("video/x-apple-video", NULL);
7128       break;
7129     case GST_MAKE_FOURCC ('a', 'v', 'c', '1'):
7130       _codec ("H.264 / AVC");
7131       caps = gst_caps_new_simple ("video/x-h264", NULL);
7132       break;
7133     case GST_MAKE_FOURCC ('r', 'l', 'e', ' '):
7134       _codec ("Run-length encoding");
7135       caps = gst_caps_new_simple ("video/x-rle",
7136           "layout", G_TYPE_STRING, "quicktime", NULL);
7137       break;
7138     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
7139       _codec ("Indeo Video 3");
7140       caps = gst_caps_new_simple ("video/x-indeo",
7141           "indeoversion", G_TYPE_INT, 3, NULL);
7142       break;
7143     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
7144     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
7145       _codec ("Intel Video 4");
7146       caps = gst_caps_new_simple ("video/x-indeo",
7147           "indeoversion", G_TYPE_INT, 4, NULL);
7148       break;
7149     case GST_MAKE_FOURCC ('d', 'v', 'c', 'p'):
7150     case GST_MAKE_FOURCC ('d', 'v', 'c', ' '):
7151     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
7152     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
7153     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
7154     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
7155     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
7156     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
7157       _codec ("DV Video");
7158       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
7159           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
7160       break;
7161     case GST_MAKE_FOURCC ('d', 'v', '5', 'n'): /* DVCPRO50 NTSC */
7162     case GST_MAKE_FOURCC ('d', 'v', '5', 'p'): /* DVCPRO50 PAL */
7163       _codec ("DVCPro50 Video");
7164       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
7165           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
7166       break;
7167     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
7168     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
7169       _codec ("DVCProHD Video");
7170       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
7171           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
7172       break;
7173     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
7174       _codec ("Apple Graphics (SMC)");
7175       caps = gst_caps_new_simple ("video/x-smc", NULL);
7176       break;
7177     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
7178       _codec ("VP3");
7179       caps = gst_caps_new_simple ("video/x-vp3", NULL);
7180       break;
7181     case GST_MAKE_FOURCC ('X', 'i', 'T', 'h'):
7182       _codec ("Theora");
7183       caps = gst_caps_new_simple ("video/x-theora", NULL);
7184       /* theora uses one byte of padding in the data stream because it does not
7185        * allow 0 sized packets while theora does */
7186       stream->padding = 1;
7187       break;
7188     case GST_MAKE_FOURCC ('d', 'r', 'a', 'c'):
7189       _codec ("Dirac");
7190       caps = gst_caps_new_simple ("video/x-dirac", NULL);
7191       break;
7192     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
7193       _codec ("TIFF still images");
7194       caps = gst_caps_new_simple ("image/tiff", NULL);
7195       break;
7196     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
7197       _codec ("Apple Intermediate Codec");
7198       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
7199       break;
7200     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
7201       _codec ("AVID DNxHD");
7202       caps = gst_caps_from_string ("video/x-dnxhd");
7203       break;
7204     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
7205     default:
7206     {
7207       char *s;
7208
7209       s = g_strdup_printf ("video/x-gst-fourcc-%" GST_FOURCC_FORMAT,
7210           GST_FOURCC_ARGS (fourcc));
7211       caps = gst_caps_new_simple (s, NULL);
7212       break;
7213     }
7214   }
7215
7216   /* enable clipping for raw video streams */
7217   s = gst_caps_get_structure (caps, 0);
7218   name = gst_structure_get_name (s);
7219   if (g_str_has_prefix (name, "video/x-raw-")) {
7220     stream->need_clip = TRUE;
7221   }
7222   return caps;
7223 }
7224
7225 static GstCaps *
7226 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
7227     guint32 fourcc, const guint8 * data, int len, gchar ** codec_name)
7228 {
7229   GstCaps *caps;
7230   const GstStructure *s;
7231   const gchar *name;
7232   gint endian = 0;
7233
7234   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc %08x", fourcc);
7235
7236   switch (fourcc) {
7237     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
7238     case GST_MAKE_FOURCC ('r', 'a', 'w', ' '):
7239       _codec ("Raw 8-bit PCM audio");
7240       caps = gst_caps_new_simple ("audio/x-raw-int", "width", G_TYPE_INT, 8,
7241           "depth", G_TYPE_INT, 8, "signed", G_TYPE_BOOLEAN, FALSE, NULL);
7242       break;
7243     case GST_MAKE_FOURCC ('t', 'w', 'o', 's'):
7244       endian = G_BIG_ENDIAN;
7245       /* fall-through */
7246     case GST_MAKE_FOURCC ('s', 'o', 'w', 't'):
7247     {
7248       gchar *str;
7249       gint depth;
7250
7251       if (!endian)
7252         endian = G_LITTLE_ENDIAN;
7253
7254       depth = stream->bytes_per_packet * 8;
7255       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
7256       _codec (str);
7257       g_free (str);
7258       caps = gst_caps_new_simple ("audio/x-raw-int",
7259           "width", G_TYPE_INT, depth, "depth", G_TYPE_INT, depth,
7260           "endianness", G_TYPE_INT, endian,
7261           "signed", G_TYPE_BOOLEAN, TRUE, NULL);
7262       break;
7263     }
7264     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
7265       _codec ("Raw 64-bit floating-point audio");
7266       caps = gst_caps_new_simple ("audio/x-raw-float", "width", G_TYPE_INT, 64,
7267           "endianness", G_TYPE_INT, G_BIG_ENDIAN, NULL);
7268       break;
7269     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
7270       _codec ("Raw 32-bit floating-point audio");
7271       caps = gst_caps_new_simple ("audio/x-raw-float", "width", G_TYPE_INT, 32,
7272           "endianness", G_TYPE_INT, G_BIG_ENDIAN, NULL);
7273       break;
7274     case FOURCC_in24:
7275       _codec ("Raw 24-bit PCM audio");
7276       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
7277        * endian later */
7278       caps = gst_caps_new_simple ("audio/x-raw-int", "width", G_TYPE_INT, 24,
7279           "depth", G_TYPE_INT, 24,
7280           "endianness", G_TYPE_INT, G_BIG_ENDIAN,
7281           "signed", G_TYPE_BOOLEAN, TRUE, NULL);
7282       break;
7283     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
7284       _codec ("Raw 32-bit PCM audio");
7285       caps = gst_caps_new_simple ("audio/x-raw-int", "width", G_TYPE_INT, 32,
7286           "depth", G_TYPE_INT, 32,
7287           "endianness", G_TYPE_INT, G_BIG_ENDIAN,
7288           "signed", G_TYPE_BOOLEAN, TRUE, NULL);
7289       break;
7290     case GST_MAKE_FOURCC ('u', 'l', 'a', 'w'):
7291       _codec ("Mu-law audio");
7292       caps = gst_caps_new_simple ("audio/x-mulaw", NULL);
7293       break;
7294     case GST_MAKE_FOURCC ('a', 'l', 'a', 'w'):
7295       _codec ("A-law audio");
7296       caps = gst_caps_new_simple ("audio/x-alaw", NULL);
7297       break;
7298     case 0x0200736d:
7299     case 0x6d730002:
7300       _codec ("Microsoft ADPCM");
7301       /* Microsoft ADPCM-ACM code 2 */
7302       caps = gst_caps_new_simple ("audio/x-adpcm",
7303           "layout", G_TYPE_STRING, "microsoft", NULL);
7304       break;
7305     case 0x1100736d:
7306     case 0x6d730011:
7307       _codec ("DVI/IMA ADPCM");
7308       caps = gst_caps_new_simple ("audio/x-adpcm",
7309           "layout", G_TYPE_STRING, "dvi", NULL);
7310       break;
7311     case 0x1700736d:
7312     case 0x6d730017:
7313       _codec ("DVI/Intel IMA ADPCM");
7314       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
7315       caps = gst_caps_new_simple ("audio/x-adpcm",
7316           "layout", G_TYPE_STRING, "quicktime", NULL);
7317       break;
7318     case 0x5500736d:
7319     case 0x6d730055:
7320       /* MPEG layer 3, CBR only (pre QT4.1) */
7321     case GST_MAKE_FOURCC ('.', 'm', 'p', '3'):
7322       _codec ("MPEG-1 layer 3");
7323       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
7324       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
7325           "mpegversion", G_TYPE_INT, 1, NULL);
7326       break;
7327     case 0x20736d:
7328     case GST_MAKE_FOURCC ('a', 'c', '-', '3'):
7329       _codec ("AC-3 audio");
7330       caps = gst_caps_new_simple ("audio/x-ac3", NULL);
7331       stream->sampled = TRUE;
7332       break;
7333     case GST_MAKE_FOURCC ('M', 'A', 'C', '3'):
7334       _codec ("MACE-3");
7335       caps = gst_caps_new_simple ("audio/x-mace",
7336           "maceversion", G_TYPE_INT, 3, NULL);
7337       break;
7338     case GST_MAKE_FOURCC ('M', 'A', 'C', '6'):
7339       _codec ("MACE-6");
7340       caps = gst_caps_new_simple ("audio/x-mace",
7341           "maceversion", G_TYPE_INT, 6, NULL);
7342       break;
7343     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
7344       /* ogg/vorbis */
7345       caps = gst_caps_new_simple ("application/ogg", NULL);
7346       break;
7347     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
7348       _codec ("DV audio");
7349       caps = gst_caps_new_simple ("audio/x-dv", NULL);
7350       break;
7351     case GST_MAKE_FOURCC ('m', 'p', '4', 'a'):
7352       _codec ("MPEG-4 AAC audio");
7353       caps = gst_caps_new_simple ("audio/mpeg",
7354           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE, NULL);
7355       break;
7356     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
7357       _codec ("QDesign Music");
7358       caps = gst_caps_new_simple ("audio/x-qdm", NULL);
7359       break;
7360     case GST_MAKE_FOURCC ('Q', 'D', 'M', '2'):
7361       _codec ("QDesign Music v.2");
7362       /* FIXME: QDesign music version 2 (no constant) */
7363       if (data) {
7364         caps = gst_caps_new_simple ("audio/x-qdm2",
7365             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
7366             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
7367             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
7368       } else {
7369         caps = gst_caps_new_simple ("audio/x-qdm2", NULL);
7370       }
7371       break;
7372     case GST_MAKE_FOURCC ('a', 'g', 's', 'm'):
7373       _codec ("GSM audio");
7374       caps = gst_caps_new_simple ("audio/x-gsm", NULL);
7375       break;
7376     case GST_MAKE_FOURCC ('s', 'a', 'm', 'r'):
7377       _codec ("AMR audio");
7378       caps = gst_caps_new_simple ("audio/AMR", NULL);
7379       break;
7380     case GST_MAKE_FOURCC ('s', 'a', 'w', 'b'):
7381       _codec ("AMR-WB audio");
7382       caps = gst_caps_new_simple ("audio/AMR-WB", NULL);
7383       break;
7384     case GST_MAKE_FOURCC ('i', 'm', 'a', '4'):
7385       _codec ("Quicktime IMA ADPCM");
7386       caps = gst_caps_new_simple ("audio/x-adpcm",
7387           "layout", G_TYPE_STRING, "quicktime", NULL);
7388       break;
7389     case GST_MAKE_FOURCC ('a', 'l', 'a', 'c'):
7390       _codec ("Apple lossless audio");
7391       caps = gst_caps_new_simple ("audio/x-alac", NULL);
7392       break;
7393     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
7394       _codec ("QualComm PureVoice");
7395       caps = gst_caps_from_string ("audio/qcelp");
7396       break;
7397     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
7398       /* ? */
7399     default:
7400     {
7401       char *s;
7402
7403       s = g_strdup_printf ("audio/x-gst-fourcc-%" GST_FOURCC_FORMAT,
7404           GST_FOURCC_ARGS (fourcc));
7405       caps = gst_caps_new_simple (s, NULL);
7406       break;
7407     }
7408   }
7409
7410   /* enable clipping for raw audio streams */
7411   s = gst_caps_get_structure (caps, 0);
7412   name = gst_structure_get_name (s);
7413   if (g_str_has_prefix (name, "audio/x-raw-")) {
7414     stream->need_clip = TRUE;
7415   }
7416   return caps;
7417 }
7418
7419 static GstCaps *
7420 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
7421     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
7422 {
7423   GstCaps *caps;
7424
7425   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc %08x", fourcc);
7426
7427   switch (fourcc) {
7428     case GST_MAKE_FOURCC ('m', 'p', '4', 's'):
7429       _codec ("DVD subtitle");
7430       caps = gst_caps_new_simple ("video/x-dvd-subpicture", NULL);
7431       break;
7432     case GST_MAKE_FOURCC ('t', 'e', 'x', 't'):
7433       _codec ("Quicktime timed text");
7434       goto text;
7435     case GST_MAKE_FOURCC ('t', 'x', '3', 'g'):
7436       _codec ("3GPP timed text");
7437     text:
7438       caps = gst_caps_new_simple ("text/plain", NULL);
7439       /* actual text piece needs to be extracted */
7440       stream->need_process = TRUE;
7441       break;
7442     default:
7443     {
7444       char *s;
7445
7446       s = g_strdup_printf ("text/x-gst-fourcc-%" GST_FOURCC_FORMAT,
7447           GST_FOURCC_ARGS (fourcc));
7448       caps = gst_caps_new_simple (s, NULL);
7449       break;
7450     }
7451   }
7452   return caps;
7453 }