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