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