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