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