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