5f6b077744c4ba0c5dc9e0f90d9eaef68875b07d
[platform/upstream/gstreamer.git] / gst / quicktime / 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           /* the mdat was before the header */
4143           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
4144               demux->n_streams, demux->mdatbuffer);
4145           /* restore our adapter/offset view of things with upstream;
4146            * put preceding buffered data ahead of current moov data.
4147            * This should also handle evil mdat, moov, mdat cases and alike */
4148           gst_adapter_clear (demux->adapter);
4149           demux->mdatbuffer = NULL;
4150           demux->offset = demux->mdatoffset;
4151           demux->neededbytes = next_entry_size (demux);
4152           demux->state = QTDEMUX_STATE_MOVIE;
4153           demux->mdatleft = gst_adapter_available (demux->adapter);
4154
4155           /* Only post, event on pads is done after newsegment */
4156           qtdemux_post_global_tags (demux);
4157
4158         } else {
4159           GST_DEBUG_OBJECT (demux, "Carrying on normally");
4160           gst_adapter_flush (demux->adapter, demux->neededbytes);
4161
4162           if (demux->got_moov && demux->first_mdat != -1) {
4163             gboolean res;
4164
4165             /* we need to seek back */
4166             res = qtdemux_seek_offset (demux, demux->first_mdat);
4167             if (res) {
4168               demux->offset = demux->first_mdat;
4169             } else {
4170               GST_DEBUG_OBJECT (demux, "Seek back failed");
4171             }
4172           } else {
4173             demux->offset += demux->neededbytes;
4174           }
4175           demux->neededbytes = 16;
4176           demux->state = QTDEMUX_STATE_INITIAL;
4177         }
4178
4179         break;
4180       }
4181       case QTDEMUX_STATE_BUFFER_MDAT:{
4182         GstBuffer *buf;
4183
4184         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
4185             demux->offset);
4186         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
4187         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
4188             GST_FOURCC_ARGS (QT_FOURCC (GST_BUFFER_DATA (buf) + 4)));
4189         if (demux->mdatbuffer)
4190           demux->mdatbuffer = gst_buffer_join (demux->mdatbuffer, buf);
4191         else
4192           demux->mdatbuffer = buf;
4193         demux->offset += demux->neededbytes;
4194         demux->neededbytes = 16;
4195         demux->state = QTDEMUX_STATE_INITIAL;
4196         gst_qtdemux_post_progress (demux, 1, 1);
4197
4198         break;
4199       }
4200       case QTDEMUX_STATE_MOVIE:{
4201         GstBuffer *outbuf;
4202         QtDemuxStream *stream = NULL;
4203         QtDemuxSample *sample;
4204         int i = -1;
4205         guint64 timestamp, duration, position;
4206         gboolean keyframe;
4207
4208         GST_DEBUG_OBJECT (demux,
4209             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
4210
4211         if (demux->fragmented) {
4212           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
4213               demux->mdatleft);
4214           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
4215             /* if needed data starts within this atom,
4216              * then it should not exceed this atom */
4217             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
4218               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
4219                   (_("This file is invalid and cannot be played.")),
4220                   ("sample data crosses atom boundary"));
4221               ret = GST_FLOW_ERROR;
4222               break;
4223             }
4224             demux->mdatleft -= demux->neededbytes;
4225           } else {
4226             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
4227             /* so we are dropping more than left in this atom */
4228             demux->todrop -= demux->mdatleft;
4229             demux->neededbytes -= demux->mdatleft;
4230             demux->mdatleft = 0;
4231             /* need to resume atom parsing so we do not miss any other pieces */
4232             demux->state = QTDEMUX_STATE_INITIAL;
4233             demux->neededbytes = 16;
4234             break;
4235           }
4236         }
4237
4238         if (demux->todrop) {
4239           GST_LOG_OBJECT (demux, "Dropping %d bytes", demux->todrop);
4240           gst_adapter_flush (demux->adapter, demux->todrop);
4241           demux->neededbytes -= demux->todrop;
4242           demux->offset += demux->todrop;
4243         }
4244
4245         /* first buffer? */
4246         /* initial newsegment sent here after having added pads,
4247          * possible others in sink_event */
4248         if (G_UNLIKELY (demux->pending_newsegment)) {
4249           gst_qtdemux_push_event (demux, demux->pending_newsegment);
4250           demux->pending_newsegment = NULL;
4251           /* clear to send tags on all streams */
4252           for (i = 0; i < demux->n_streams; i++) {
4253             gst_qtdemux_push_tags (demux, demux->streams[i]);
4254           }
4255         }
4256
4257         /* Figure out which stream this is packet belongs to */
4258         for (i = 0; i < demux->n_streams; i++) {
4259           stream = demux->streams[i];
4260           if (stream->sample_index >= stream->n_samples)
4261             continue;
4262           GST_LOG_OBJECT (demux,
4263               "Checking stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
4264               " / size:%d)", i, stream->sample_index,
4265               stream->samples[stream->sample_index].offset,
4266               stream->samples[stream->sample_index].size);
4267
4268           if (stream->samples[stream->sample_index].offset == demux->offset)
4269             break;
4270         }
4271
4272         if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
4273           goto unknown_stream;
4274
4275         /* Put data in a buffer, set timestamps, caps, ... */
4276         outbuf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
4277         GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
4278             GST_FOURCC_ARGS (stream->fourcc));
4279
4280         g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
4281
4282         sample = &stream->samples[stream->sample_index];
4283
4284         position = QTSAMPLE_DTS (stream, sample);
4285         timestamp = QTSAMPLE_PTS (stream, sample);
4286         duration = QTSAMPLE_DUR_DTS (stream, sample, position);
4287         keyframe = QTSAMPLE_KEYFRAME (stream, sample);
4288
4289         ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
4290             timestamp, duration, keyframe, position, demux->offset);
4291
4292         /* combine flows */
4293         ret = gst_qtdemux_combine_flows (demux, stream, ret);
4294
4295         stream->sample_index++;
4296
4297         /* update current offset and figure out size of next buffer */
4298         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
4299             demux->offset, demux->neededbytes);
4300         demux->offset += demux->neededbytes;
4301         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
4302             demux->offset);
4303
4304         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
4305           if (demux->fragmented) {
4306             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
4307             /* there may be more to follow, only finish this atom */
4308             demux->todrop = demux->mdatleft;
4309             demux->neededbytes = demux->todrop;
4310             break;
4311           }
4312           goto eos;
4313         }
4314         break;
4315       }
4316       default:
4317         goto invalid_state;
4318     }
4319   }
4320
4321   /* when buffering movie data, at least show user something is happening */
4322   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
4323       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
4324     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
4325         demux->neededbytes);
4326   }
4327 done:
4328   gst_object_unref (demux);
4329
4330   return ret;
4331
4332   /* ERRORS */
4333 unknown_stream:
4334   {
4335     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
4336     ret = GST_FLOW_ERROR;
4337     goto done;
4338   }
4339 eos:
4340   {
4341     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
4342     ret = GST_FLOW_UNEXPECTED;
4343     goto done;
4344   }
4345 invalid_state:
4346   {
4347     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
4348         (NULL), ("qtdemuxer invalid state %d", demux->state));
4349     ret = GST_FLOW_ERROR;
4350     goto done;
4351   }
4352 no_moov:
4353   {
4354     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
4355         (NULL), ("no 'moov' atom within the first 10 MB"));
4356     ret = GST_FLOW_ERROR;
4357     goto done;
4358   }
4359 }
4360
4361 static gboolean
4362 qtdemux_sink_activate (GstPad * sinkpad)
4363 {
4364   if (gst_pad_check_pull_range (sinkpad))
4365     return gst_pad_activate_pull (sinkpad, TRUE);
4366   else
4367     return gst_pad_activate_push (sinkpad, TRUE);
4368 }
4369
4370 static gboolean
4371 qtdemux_sink_activate_pull (GstPad * sinkpad, gboolean active)
4372 {
4373   GstQTDemux *demux = GST_QTDEMUX (GST_PAD_PARENT (sinkpad));
4374
4375   if (active) {
4376     demux->pullbased = TRUE;
4377     demux->segment_running = TRUE;
4378     return gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
4379         sinkpad);
4380   } else {
4381     demux->segment_running = FALSE;
4382     return gst_pad_stop_task (sinkpad);
4383   }
4384 }
4385
4386 static gboolean
4387 qtdemux_sink_activate_push (GstPad * sinkpad, gboolean active)
4388 {
4389   GstQTDemux *demux = GST_QTDEMUX (GST_PAD_PARENT (sinkpad));
4390
4391   demux->pullbased = FALSE;
4392
4393   return TRUE;
4394 }
4395
4396 #ifdef HAVE_ZLIB
4397 static void *
4398 qtdemux_zalloc (void *opaque, unsigned int items, unsigned int size)
4399 {
4400   return g_malloc (items * size);
4401 }
4402
4403 static void
4404 qtdemux_zfree (void *opaque, void *addr)
4405 {
4406   g_free (addr);
4407 }
4408
4409 static void *
4410 qtdemux_inflate (void *z_buffer, guint z_length, guint length)
4411 {
4412   guint8 *buffer;
4413   z_stream *z;
4414   int ret;
4415
4416   z = g_new0 (z_stream, 1);
4417   z->zalloc = qtdemux_zalloc;
4418   z->zfree = qtdemux_zfree;
4419   z->opaque = NULL;
4420
4421   z->next_in = z_buffer;
4422   z->avail_in = z_length;
4423
4424   buffer = (guint8 *) g_malloc (length);
4425   ret = inflateInit (z);
4426   while (z->avail_in > 0) {
4427     if (z->avail_out == 0) {
4428       length += 1024;
4429       buffer = (guint8 *) g_realloc (buffer, length);
4430       z->next_out = buffer + z->total_out;
4431       z->avail_out = 1024;
4432     }
4433     ret = inflate (z, Z_SYNC_FLUSH);
4434     if (ret != Z_OK)
4435       break;
4436   }
4437   if (ret != Z_STREAM_END) {
4438     g_warning ("inflate() returned %d", ret);
4439   }
4440
4441   g_free (z);
4442   return buffer;
4443 }
4444 #endif /* HAVE_ZLIB */
4445
4446 static gboolean
4447 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
4448 {
4449   GNode *cmov;
4450
4451   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
4452
4453   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
4454   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
4455
4456   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
4457   if (cmov) {
4458     guint32 method;
4459     GNode *dcom;
4460     GNode *cmvd;
4461
4462     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
4463     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
4464     if (dcom == NULL || cmvd == NULL)
4465       goto invalid_compression;
4466
4467     method = QT_FOURCC ((guint8 *) dcom->data + 8);
4468     switch (method) {
4469 #ifdef HAVE_ZLIB
4470       case GST_MAKE_FOURCC ('z', 'l', 'i', 'b'):{
4471         guint uncompressed_length;
4472         guint compressed_length;
4473         guint8 *buf;
4474
4475         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
4476         compressed_length = QT_UINT32 ((guint8 *) cmvd->data + 4) - 12;
4477         GST_LOG ("length = %u", uncompressed_length);
4478
4479         buf =
4480             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
4481             compressed_length, uncompressed_length);
4482
4483         qtdemux->moov_node_compressed = qtdemux->moov_node;
4484         qtdemux->moov_node = g_node_new (buf);
4485
4486         qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
4487             uncompressed_length);
4488         break;
4489       }
4490 #endif /* HAVE_ZLIB */
4491       default:
4492         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
4493             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
4494         break;
4495     }
4496   }
4497   return TRUE;
4498
4499   /* ERRORS */
4500 invalid_compression:
4501   {
4502     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
4503     return FALSE;
4504   }
4505 }
4506
4507 static gboolean
4508 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
4509     const guint8 * end)
4510 {
4511   while (G_UNLIKELY (buf < end)) {
4512     GNode *child;
4513     guint32 len;
4514
4515     if (G_UNLIKELY (buf + 4 > end)) {
4516       GST_LOG_OBJECT (qtdemux, "buffer overrun");
4517       break;
4518     }
4519     len = QT_UINT32 (buf);
4520     if (G_UNLIKELY (len == 0)) {
4521       GST_LOG_OBJECT (qtdemux, "empty container");
4522       break;
4523     }
4524     if (G_UNLIKELY (len < 8)) {
4525       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
4526       break;
4527     }
4528     if (G_UNLIKELY (len > (end - buf))) {
4529       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
4530           (gint) (end - buf));
4531       break;
4532     }
4533
4534     child = g_node_new ((guint8 *) buf);
4535     g_node_append (node, child);
4536     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
4537     qtdemux_parse_node (qtdemux, child, buf, len);
4538
4539     buf += len;
4540   }
4541   return TRUE;
4542 }
4543
4544 static gboolean
4545 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
4546     GNode * xdxt)
4547 {
4548   int len = QT_UINT32 (xdxt->data);
4549   guint8 *buf = xdxt->data;
4550   guint8 *end = buf + len;
4551   GstBuffer *buffer;
4552
4553   /* skip size and type */
4554   buf += 8;
4555   end -= 8;
4556
4557   while (buf < end) {
4558     gint size;
4559     guint32 type;
4560
4561     size = QT_UINT32 (buf);
4562     type = QT_FOURCC (buf + 4);
4563
4564     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
4565
4566     if (buf + size > end || size <= 0)
4567       break;
4568
4569     buf += 8;
4570     size -= 8;
4571
4572     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
4573         GST_FOURCC_ARGS (type));
4574
4575     switch (type) {
4576       case FOURCC_tCtH:
4577         buffer = gst_buffer_new_and_alloc (size);
4578         memcpy (GST_BUFFER_DATA (buffer), buf, size);
4579         stream->buffers = g_slist_append (stream->buffers, buffer);
4580         GST_LOG_OBJECT (qtdemux, "parsing theora header");
4581         break;
4582       case FOURCC_tCt_:
4583         buffer = gst_buffer_new_and_alloc (size);
4584         memcpy (GST_BUFFER_DATA (buffer), buf, size);
4585         stream->buffers = g_slist_append (stream->buffers, buffer);
4586         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
4587         break;
4588       case FOURCC_tCtC:
4589         buffer = gst_buffer_new_and_alloc (size);
4590         memcpy (GST_BUFFER_DATA (buffer), buf, size);
4591         stream->buffers = g_slist_append (stream->buffers, buffer);
4592         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
4593         break;
4594       default:
4595         GST_WARNING_OBJECT (qtdemux,
4596             "unknown theora cookie %" GST_FOURCC_FORMAT,
4597             GST_FOURCC_ARGS (type));
4598         break;
4599     }
4600     buf += size;
4601   }
4602   return TRUE;
4603 }
4604
4605 static gboolean
4606 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
4607     guint length)
4608 {
4609   guint32 fourcc = 0;
4610   guint32 node_length = 0;
4611   const QtNodeType *type;
4612   const guint8 *end;
4613
4614   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
4615
4616   if (G_UNLIKELY (length < 8))
4617     goto not_enough_data;
4618
4619   node_length = QT_UINT32 (buffer);
4620   fourcc = QT_FOURCC (buffer + 4);
4621
4622   /* ignore empty nodes */
4623   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
4624     return TRUE;
4625
4626   type = qtdemux_type_get (fourcc);
4627
4628   end = buffer + length;
4629
4630   GST_LOG_OBJECT (qtdemux,
4631       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
4632       GST_FOURCC_ARGS (fourcc), node_length, type->name);
4633
4634   if (node_length > length)
4635     goto broken_atom_size;
4636
4637   if (type->flags & QT_FLAG_CONTAINER) {
4638     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
4639   } else {
4640     switch (fourcc) {
4641       case FOURCC_stsd:
4642       {
4643         if (node_length < 20) {
4644           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
4645           break;
4646         }
4647         GST_DEBUG_OBJECT (qtdemux,
4648             "parsing stsd (sample table, sample description) atom");
4649         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
4650         break;
4651       }
4652       case FOURCC_mp4a:
4653       case FOURCC_alac:
4654       {
4655         guint32 version;
4656         guint32 offset;
4657         guint min_size;
4658
4659         /* also read alac (or whatever) in stead of mp4a in the following,
4660          * since a similar layout is used in other cases as well */
4661         if (fourcc == FOURCC_mp4a)
4662           min_size = 20;
4663         else
4664           min_size = 40;
4665
4666         /* There are two things we might encounter here: a true mp4a atom, and
4667            an mp4a entry in an stsd atom. The latter is what we're interested
4668            in, and it looks like an atom, but isn't really one. The true mp4a
4669            atom is short, so we detect it based on length here. */
4670         if (length < min_size) {
4671           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
4672               GST_FOURCC_ARGS (fourcc));
4673           break;
4674         }
4675
4676         /* 'version' here is the sound sample description version. Types 0 and
4677            1 are documented in the QTFF reference, but type 2 is not: it's
4678            described in Apple header files instead (struct SoundDescriptionV2
4679            in Movies.h) */
4680         version = QT_UINT16 (buffer + 16);
4681
4682         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
4683             GST_FOURCC_ARGS (fourcc), version);
4684
4685         /* parse any esds descriptors */
4686         switch (version) {
4687           case 0:
4688             offset = 0x24;
4689             break;
4690           case 1:
4691             offset = 0x34;
4692             break;
4693           case 2:
4694             offset = 0x48;
4695             break;
4696           default:
4697             GST_WARNING_OBJECT (qtdemux,
4698                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
4699                 GST_FOURCC_ARGS (fourcc), version);
4700             offset = 0;
4701             break;
4702         }
4703         if (offset)
4704           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
4705         break;
4706       }
4707       case FOURCC_mp4v:
4708       case FOURCC_MP4V:
4709       case FOURCC_fmp4:
4710       case FOURCC_FMP4:
4711       {
4712         const guint8 *buf;
4713         guint32 version;
4714         int tlen;
4715
4716         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
4717             GST_FOURCC_ARGS (fourcc));
4718         version = QT_UINT32 (buffer + 16);
4719         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
4720         if (1 || version == 0x00000000) {
4721           buf = buffer + 0x32;
4722
4723           /* FIXME Quicktime uses PASCAL string while
4724            * the iso format uses C strings. Check the file
4725            * type before attempting to parse the string here. */
4726           tlen = QT_UINT8 (buf);
4727           GST_DEBUG_OBJECT (qtdemux, "tlen = %d", tlen);
4728           buf++;
4729           GST_DEBUG_OBJECT (qtdemux, "string = %.*s", tlen, (char *) buf);
4730           /* the string has a reserved space of 32 bytes so skip
4731            * the remaining 31 */
4732           buf += 31;
4733           buf += 4;             /* and 4 bytes reserved */
4734
4735           GST_MEMDUMP_OBJECT (qtdemux, "mp4v", buf, end - buf);
4736
4737           qtdemux_parse_container (qtdemux, node, buf, end);
4738         }
4739         break;
4740       }
4741       case FOURCC_avc1:
4742       {
4743         GST_MEMDUMP_OBJECT (qtdemux, "avc1", buffer, end - buffer);
4744         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
4745         break;
4746       }
4747       case FOURCC_mjp2:
4748       {
4749         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
4750         break;
4751       }
4752       case FOURCC_meta:
4753       {
4754         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
4755         qtdemux_parse_container (qtdemux, node, buffer + 12, end);
4756         break;
4757       }
4758       case FOURCC_XiTh:
4759       {
4760         guint32 version;
4761         guint32 offset;
4762
4763         version = QT_UINT32 (buffer + 12);
4764         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
4765
4766         switch (version) {
4767           case 0x00000001:
4768             offset = 0x62;
4769             break;
4770           default:
4771             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
4772             offset = 0;
4773             break;
4774         }
4775         if (offset)
4776           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
4777         break;
4778       }
4779       case FOURCC_in24:
4780       {
4781         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
4782         break;
4783       }
4784       default:
4785         if (!strcmp (type->name, "unknown"))
4786           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
4787         break;
4788     }
4789   }
4790   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
4791       GST_FOURCC_ARGS (fourcc));
4792   return TRUE;
4793
4794 /* ERRORS */
4795 not_enough_data:
4796   {
4797     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4798         (_("This file is corrupt and cannot be played.")),
4799         ("Not enough data for an atom header, got only %u bytes", length));
4800     return FALSE;
4801   }
4802 broken_atom_size:
4803   {
4804     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4805         (_("This file is corrupt and cannot be played.")),
4806         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
4807             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
4808             length));
4809     return FALSE;
4810   }
4811 }
4812
4813 static GNode *
4814 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
4815 {
4816   GNode *child;
4817   guint8 *buffer;
4818   guint32 child_fourcc;
4819
4820   for (child = g_node_first_child (node); child;
4821       child = g_node_next_sibling (child)) {
4822     buffer = (guint8 *) child->data;
4823
4824     child_fourcc = QT_FOURCC (buffer + 4);
4825
4826     if (G_UNLIKELY (child_fourcc == fourcc)) {
4827       return child;
4828     }
4829   }
4830   return NULL;
4831 }
4832
4833 static GNode *
4834 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
4835     GstByteReader * parser)
4836 {
4837   GNode *child;
4838   guint8 *buffer;
4839   guint32 child_fourcc, child_len;
4840
4841   for (child = g_node_first_child (node); child;
4842       child = g_node_next_sibling (child)) {
4843     buffer = (guint8 *) child->data;
4844
4845     child_len = QT_UINT32 (buffer);
4846     child_fourcc = QT_FOURCC (buffer + 4);
4847
4848     if (G_UNLIKELY (child_fourcc == fourcc)) {
4849       if (G_UNLIKELY (child_len < (4 + 4)))
4850         return NULL;
4851       /* FIXME: must verify if atom length < parent atom length */
4852       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
4853       return child;
4854     }
4855   }
4856   return NULL;
4857 }
4858
4859 static GNode *
4860 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
4861     GstByteReader * parser)
4862 {
4863   GNode *child;
4864   guint8 *buffer;
4865   guint32 child_fourcc, child_len;
4866
4867   for (child = g_node_next_sibling (node); child;
4868       child = g_node_next_sibling (child)) {
4869     buffer = (guint8 *) child->data;
4870
4871     child_fourcc = QT_FOURCC (buffer + 4);
4872
4873     if (child_fourcc == fourcc) {
4874       if (parser) {
4875         child_len = QT_UINT32 (buffer);
4876         if (G_UNLIKELY (child_len < (4 + 4)))
4877           return NULL;
4878         /* FIXME: must verify if atom length < parent atom length */
4879         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
4880       }
4881       return child;
4882     }
4883   }
4884   return NULL;
4885 }
4886
4887 static GNode *
4888 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
4889 {
4890   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
4891 }
4892
4893 static gboolean
4894 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
4895     QtDemuxStream * stream, GstTagList * list)
4896 {
4897   /* consistent default for push based mode */
4898   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
4899   gst_segment_set_newsegment (&stream->segment, FALSE, 1.0, GST_FORMAT_TIME,
4900       0, GST_CLOCK_TIME_NONE, 0);
4901
4902   if (stream->subtype == FOURCC_vide) {
4903     gchar *name = g_strdup_printf ("video_%02d", qtdemux->n_video_streams);
4904
4905     stream->pad =
4906         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
4907     g_free (name);
4908
4909     /* fps is calculated base on the duration of the first frames since
4910      * qt does not have a fixed framerate. */
4911     if ((stream->n_samples == 1) && (stream->min_duration == 0)) {
4912       /* still frame */
4913       stream->fps_n = 0;
4914       stream->fps_d = 1;
4915     } else {
4916       stream->fps_n = stream->timescale;
4917       if (stream->min_duration == 0)
4918         stream->fps_d = 1;
4919       else
4920         stream->fps_d = stream->min_duration;
4921     }
4922
4923     if (stream->caps) {
4924       gboolean gray;
4925       gint depth, palette_count;
4926       const guint32 *palette_data = NULL;
4927
4928       gst_caps_set_simple (stream->caps,
4929           "width", G_TYPE_INT, stream->width,
4930           "height", G_TYPE_INT, stream->height,
4931           "framerate", GST_TYPE_FRACTION, stream->fps_n, stream->fps_d, NULL);
4932
4933       /* calculate pixel-aspect-ratio using display width and height */
4934       GST_DEBUG_OBJECT (qtdemux,
4935           "video size %dx%d, target display size %dx%d", stream->width,
4936           stream->height, stream->display_width, stream->display_height);
4937
4938       if (stream->display_width > 0 && stream->display_height > 0 &&
4939           stream->width > 0 && stream->height > 0) {
4940         gint n, d;
4941
4942         /* calculate the pixel aspect ratio using the display and pixel w/h */
4943         n = stream->display_width * stream->height;
4944         d = stream->display_height * stream->width;
4945         if (n == d)
4946           n = d = 1;
4947         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
4948         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
4949             GST_TYPE_FRACTION, n, d, NULL);
4950       }
4951
4952       /* qt file might have pasp atom */
4953       if (stream->par_w > 0 && stream->par_h > 0) {
4954         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", stream->par_w, stream->par_h);
4955         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
4956             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
4957       }
4958
4959       depth = stream->bits_per_sample;
4960
4961       /* more than 32 bits means grayscale */
4962       gray = (depth > 32);
4963       /* low 32 bits specify the depth  */
4964       depth &= 0x1F;
4965
4966       /* different number of palette entries is determined by depth. */
4967       palette_count = 0;
4968       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
4969         palette_count = (1 << depth);
4970
4971       switch (palette_count) {
4972         case 0:
4973           break;
4974         case 2:
4975           palette_data = ff_qt_default_palette_2;
4976           break;
4977         case 4:
4978           palette_data = ff_qt_default_palette_4;
4979           break;
4980         case 16:
4981           if (gray)
4982             palette_data = ff_qt_grayscale_palette_16;
4983           else
4984             palette_data = ff_qt_default_palette_16;
4985           break;
4986         case 256:
4987           if (gray)
4988             palette_data = ff_qt_grayscale_palette_256;
4989           else
4990             palette_data = ff_qt_default_palette_256;
4991           break;
4992         default:
4993           GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4994               (_("The video in this file might not play correctly.")),
4995               ("unsupported palette depth %d", depth));
4996           break;
4997       }
4998       if (palette_data) {
4999         GstBuffer *palette;
5000
5001         /* make sure it's not writable. We leave MALLOCDATA to NULL so that we
5002          * don't free any of the buffer data. */
5003         palette = gst_buffer_new ();
5004         GST_BUFFER_FLAG_SET (palette, GST_BUFFER_FLAG_READONLY);
5005         GST_BUFFER_DATA (palette) = (guint8 *) palette_data;
5006         GST_BUFFER_SIZE (palette) = sizeof (guint32) * palette_count;
5007
5008         gst_caps_set_simple (stream->caps, "palette_data",
5009             GST_TYPE_BUFFER, palette, NULL);
5010         gst_buffer_unref (palette);
5011       } else if (palette_count != 0) {
5012         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
5013             (NULL), ("Unsupported palette depth %d. Ignoring stream.", depth));
5014
5015         gst_object_unref (stream->pad);
5016         stream->pad = NULL;
5017       }
5018     }
5019     qtdemux->n_video_streams++;
5020   } else if (stream->subtype == FOURCC_soun) {
5021     gchar *name = g_strdup_printf ("audio_%02d", qtdemux->n_audio_streams);
5022
5023     stream->pad =
5024         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
5025     g_free (name);
5026     if (stream->caps) {
5027       gst_caps_set_simple (stream->caps,
5028           "rate", G_TYPE_INT, (int) stream->rate,
5029           "channels", G_TYPE_INT, stream->n_channels, NULL);
5030     }
5031     qtdemux->n_audio_streams++;
5032   } else if (stream->subtype == FOURCC_strm) {
5033     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
5034   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text) {
5035     gchar *name = g_strdup_printf ("subtitle_%02d", qtdemux->n_sub_streams);
5036
5037     stream->pad =
5038         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
5039     g_free (name);
5040     qtdemux->n_sub_streams++;
5041   } else {
5042     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5043     goto done;
5044   }
5045
5046   if (stream->pad) {
5047     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
5048
5049     gst_pad_use_fixed_caps (stream->pad);
5050     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
5051     gst_pad_set_query_type_function (stream->pad,
5052         gst_qtdemux_get_src_query_types);
5053     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
5054
5055     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT, stream->caps);
5056     gst_pad_set_caps (stream->pad, stream->caps);
5057
5058     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
5059         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
5060     gst_pad_set_active (stream->pad, TRUE);
5061     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
5062     if (stream->pending_tags)
5063       gst_tag_list_free (stream->pending_tags);
5064     stream->pending_tags = list;
5065     if (list) {
5066       /* post now, send event on pad later */
5067       GST_DEBUG_OBJECT (qtdemux, "Posting tags %" GST_PTR_FORMAT, list);
5068       gst_element_post_message (GST_ELEMENT (qtdemux),
5069           gst_message_new_tag_full (GST_OBJECT (qtdemux), stream->pad,
5070               gst_tag_list_copy (list)));
5071     }
5072     /* global tags go on each pad anyway */
5073     stream->send_global_tags = TRUE;
5074   }
5075 done:
5076   return TRUE;
5077 }
5078
5079 /* find next atom with @fourcc starting at @offset */
5080 static GstFlowReturn
5081 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
5082     guint64 * length, guint32 fourcc)
5083 {
5084   GstFlowReturn ret;
5085   guint32 lfourcc;
5086   GstBuffer *buf;
5087
5088   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
5089       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
5090
5091   while (TRUE) {
5092     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
5093     if (G_UNLIKELY (ret != GST_FLOW_OK))
5094       goto locate_failed;
5095     if (G_LIKELY (GST_BUFFER_SIZE (buf) != 16)) {
5096       /* likely EOF */
5097       ret = GST_FLOW_UNEXPECTED;
5098       gst_buffer_unref (buf);
5099       goto locate_failed;
5100     }
5101     extract_initial_length_and_fourcc (GST_BUFFER_DATA (buf), 16, length,
5102         &lfourcc);
5103     gst_buffer_unref (buf);
5104
5105     if (G_UNLIKELY (*length == 0)) {
5106       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
5107       ret = GST_FLOW_ERROR;
5108       goto locate_failed;
5109     }
5110
5111     if (lfourcc == fourcc) {
5112       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
5113           *offset);
5114       break;
5115     } else {
5116       GST_LOG_OBJECT (qtdemux,
5117           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
5118           GST_FOURCC_ARGS (fourcc), *offset);
5119       *offset += *length;
5120     }
5121   }
5122
5123   return GST_FLOW_OK;
5124
5125 locate_failed:
5126   {
5127     /* might simply have had last one */
5128     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
5129     return ret;
5130   }
5131 }
5132
5133 /* should only do something in pull mode */
5134 /* call with OBJECT lock */
5135 static GstFlowReturn
5136 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
5137 {
5138   guint64 length, offset;
5139   GstBuffer *buf = NULL;
5140   GstFlowReturn ret = GST_FLOW_OK;
5141   GstFlowReturn res = TRUE;
5142
5143   offset = qtdemux->moof_offset;
5144   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
5145
5146   if (!offset) {
5147     GST_DEBUG_OBJECT (qtdemux, "no next moof");
5148     return GST_FLOW_UNEXPECTED;
5149   }
5150
5151   /* best not do pull etc with lock held */
5152   GST_OBJECT_UNLOCK (qtdemux);
5153
5154   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
5155   if (ret != GST_FLOW_OK)
5156     goto flow_failed;
5157
5158   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
5159   if (G_UNLIKELY (ret != GST_FLOW_OK))
5160     goto flow_failed;
5161   if (!qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf),
5162           GST_BUFFER_SIZE (buf), offset, NULL)) {
5163     gst_buffer_unref (buf);
5164     buf = NULL;
5165     goto parse_failed;
5166   }
5167
5168   gst_buffer_unref (buf);
5169   buf = NULL;
5170
5171   offset += length;
5172   /* look for next moof */
5173   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
5174   if (G_UNLIKELY (ret != GST_FLOW_OK))
5175     goto flow_failed;
5176
5177 exit:
5178   GST_OBJECT_LOCK (qtdemux);
5179
5180   qtdemux->moof_offset = offset;
5181
5182   return res;
5183
5184 parse_failed:
5185   {
5186     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
5187     offset = 0;
5188     res = GST_FLOW_ERROR;
5189     goto exit;
5190   }
5191 flow_failed:
5192   {
5193     /* maybe upstream temporarily flushing */
5194     if (ret != GST_FLOW_WRONG_STATE) {
5195       GST_DEBUG_OBJECT (qtdemux, "no next moof");
5196       offset = 0;
5197     } else {
5198       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
5199       /* resume at current position next time */
5200     }
5201     res = ret;
5202     goto exit;
5203   }
5204 }
5205
5206 /* initialise bytereaders for stbl sub-atoms */
5207 static gboolean
5208 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
5209 {
5210   stream->stbl_index = -1;      /* no samples have yet been parsed */
5211
5212   /* time-to-sample atom */
5213   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
5214     goto corrupt_file;
5215
5216   /* copy atom data into a new buffer for later use */
5217   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
5218
5219   /* skip version + flags */
5220   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
5221       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
5222     goto corrupt_file;
5223   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
5224
5225   /* make sure there's enough data */
5226   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 2 * 4))
5227     goto corrupt_file;
5228
5229   /* sync sample atom */
5230   stream->stps_present = FALSE;
5231   if ((stream->stss_present =
5232           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
5233               &stream->stss) ? TRUE : FALSE) == TRUE) {
5234     /* copy atom data into a new buffer for later use */
5235     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
5236
5237     /* skip version + flags */
5238     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
5239         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
5240       goto corrupt_file;
5241
5242     if (stream->n_sample_syncs) {
5243       /* make sure there's enough data */
5244       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
5245         goto corrupt_file;
5246     }
5247
5248     /* partial sync sample atom */
5249     if ((stream->stps_present =
5250             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
5251                 &stream->stps) ? TRUE : FALSE) == TRUE) {
5252       /* copy atom data into a new buffer for later use */
5253       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
5254
5255       /* skip version + flags */
5256       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
5257           !gst_byte_reader_get_uint32_be (&stream->stps,
5258               &stream->n_sample_partial_syncs))
5259         goto corrupt_file;
5260
5261       /* if there are no entries, the stss table contains the real
5262        * sync samples */
5263       if (stream->n_sample_partial_syncs) {
5264         /* make sure there's enough data */
5265         if (!qt_atom_parser_has_chunks (&stream->stps,
5266                 stream->n_sample_partial_syncs, 4))
5267           goto corrupt_file;
5268       }
5269     }
5270   }
5271
5272   /* sample size */
5273   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
5274     goto no_samples;
5275
5276   /* copy atom data into a new buffer for later use */
5277   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
5278
5279   /* skip version + flags */
5280   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
5281       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
5282     goto corrupt_file;
5283
5284   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
5285     goto corrupt_file;
5286
5287   if (!stream->n_samples)
5288     goto no_samples;
5289
5290   /* sample-to-chunk atom */
5291   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
5292     goto corrupt_file;
5293
5294   /* copy atom data into a new buffer for later use */
5295   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
5296
5297   /* skip version + flags */
5298   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
5299       !gst_byte_reader_get_uint32_be (&stream->stsc,
5300           &stream->n_samples_per_chunk))
5301     goto corrupt_file;
5302
5303   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
5304       stream->n_samples_per_chunk);
5305
5306   /* make sure there's enough data */
5307   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
5308           12))
5309     goto corrupt_file;
5310
5311
5312   /* chunk offset */
5313   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
5314     stream->co_size = sizeof (guint32);
5315   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
5316           &stream->stco))
5317     stream->co_size = sizeof (guint64);
5318   else
5319     goto corrupt_file;
5320
5321   /* copy atom data into a new buffer for later use */
5322   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
5323
5324   /* skip version + flags */
5325   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
5326     goto corrupt_file;
5327
5328   /* chunks_are_chunks == 0 means treat chunks as samples */
5329   stream->chunks_are_chunks = !stream->sample_size || stream->sampled;
5330   if (stream->chunks_are_chunks) {
5331     /* skip number of entries */
5332     if (!gst_byte_reader_skip (&stream->stco, 4))
5333       goto corrupt_file;
5334
5335     /* make sure there are enough data in the stsz atom */
5336     if (!stream->sample_size) {
5337       /* different sizes for each sample */
5338       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
5339         goto corrupt_file;
5340     }
5341   } else {
5342     /* treat chunks as samples */
5343     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
5344       goto corrupt_file;
5345   }
5346
5347   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
5348       stream->n_samples, (guint) sizeof (QtDemuxSample),
5349       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
5350
5351   if (stream->n_samples >=
5352       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
5353     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
5354         "be larger than %uMB (broken file?)", stream->n_samples,
5355         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
5356     return FALSE;
5357   }
5358
5359   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
5360   if (!stream->samples) {
5361     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
5362         stream->n_samples);
5363     return FALSE;
5364   }
5365
5366
5367   /* composition time-to-sample */
5368   if ((stream->ctts_present =
5369           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
5370               &stream->ctts) ? TRUE : FALSE) == TRUE) {
5371     /* copy atom data into a new buffer for later use */
5372     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
5373
5374     /* skip version + flags */
5375     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
5376         || !gst_byte_reader_get_uint32_be (&stream->ctts,
5377             &stream->n_composition_times))
5378       goto corrupt_file;
5379
5380     /* make sure there's enough data */
5381     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
5382             4 + 4))
5383       goto corrupt_file;
5384   }
5385
5386   return TRUE;
5387
5388 corrupt_file:
5389   {
5390     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
5391         (_("This file is corrupt and cannot be played.")), (NULL));
5392     return FALSE;
5393   }
5394 no_samples:
5395   {
5396     gst_qtdemux_stbl_free (stream);
5397     if (!qtdemux->fragmented) {
5398       /* not quite good */
5399       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
5400       return FALSE;
5401     } else {
5402       /* may pick up samples elsewhere */
5403       return TRUE;
5404     }
5405   }
5406 }
5407
5408 /* collect samples from the next sample to be parsed up to sample @n for @stream
5409  * by reading the info from @stbl
5410  *
5411  * This code can be executed from both the streaming thread and the seeking
5412  * thread so it takes the object lock to protect itself
5413  */
5414 static gboolean
5415 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
5416 {
5417   gint i, j, k;
5418   QtDemuxSample *samples, *first, *cur, *last;
5419   guint32 n_samples_per_chunk;
5420   guint32 n_samples;
5421
5422   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
5423       GST_FOURCC_FORMAT ", pad %s", GST_FOURCC_ARGS (stream->fourcc),
5424       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
5425
5426   n_samples = stream->n_samples;
5427
5428   if (n >= n_samples)
5429     goto out_of_samples;
5430
5431   GST_OBJECT_LOCK (qtdemux);
5432   if (n <= stream->stbl_index)
5433     goto already_parsed;
5434
5435   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
5436
5437   if (!stream->stsz.data) {
5438     /* so we already parsed and passed all the moov samples;
5439      * onto fragmented ones */
5440     g_assert (qtdemux->fragmented);
5441     goto done;
5442   }
5443
5444   /* pointer to the sample table */
5445   samples = stream->samples;
5446
5447   /* starts from -1, moves to the next sample index to parse */
5448   stream->stbl_index++;
5449
5450   /* keep track of the first and last sample to fill */
5451   first = &samples[stream->stbl_index];
5452   last = &samples[n];
5453
5454   if (stream->chunks_are_chunks) {
5455     /* set the sample sizes */
5456     if (stream->sample_size == 0) {
5457       /* different sizes for each sample */
5458       for (cur = first; cur <= last; cur++) {
5459         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
5460         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
5461             (guint) (cur - samples), cur->size);
5462       }
5463     } else {
5464       /* samples have the same size */
5465       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
5466       for (cur = first; cur <= last; cur++)
5467         cur->size = stream->sample_size;
5468     }
5469   }
5470
5471   n_samples_per_chunk = stream->n_samples_per_chunk;
5472   cur = first;
5473
5474   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
5475     guint32 last_chunk;
5476
5477     if (stream->stsc_chunk_index >= stream->last_chunk
5478         || stream->stsc_chunk_index < stream->first_chunk) {
5479       stream->first_chunk =
5480           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
5481       stream->samples_per_chunk =
5482           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
5483       gst_byte_reader_skip_unchecked (&stream->stsc, 4);
5484
5485       /* chunk numbers are counted from 1 it seems */
5486       if (G_UNLIKELY (stream->first_chunk == 0))
5487         goto corrupt_file;
5488
5489       --stream->first_chunk;
5490
5491       /* the last chunk of each entry is calculated by taking the first chunk
5492        * of the next entry; except if there is no next, where we fake it with
5493        * INT_MAX */
5494       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
5495         stream->last_chunk = G_MAXUINT32;
5496       } else {
5497         stream->last_chunk =
5498             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
5499         if (G_UNLIKELY (stream->last_chunk == 0))
5500           goto corrupt_file;
5501
5502         --stream->last_chunk;
5503       }
5504
5505       GST_LOG_OBJECT (qtdemux,
5506           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d", i,
5507           stream->first_chunk, stream->last_chunk, stream->samples_per_chunk);
5508
5509       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
5510         goto corrupt_file;
5511
5512       if (stream->last_chunk != G_MAXUINT32) {
5513         if (!qt_atom_parser_peek_sub (&stream->stco,
5514                 stream->first_chunk * stream->co_size,
5515                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
5516                 &stream->co_chunk))
5517           goto corrupt_file;
5518
5519       } else {
5520         stream->co_chunk = stream->stco;
5521         if (!gst_byte_reader_skip (&stream->co_chunk,
5522                 stream->first_chunk * stream->co_size))
5523           goto corrupt_file;
5524       }
5525
5526       stream->stsc_chunk_index = stream->first_chunk;
5527     }
5528
5529     last_chunk = stream->last_chunk;
5530
5531     if (stream->chunks_are_chunks) {
5532       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
5533         guint32 samples_per_chunk;
5534         guint64 chunk_offset;
5535
5536         if (!stream->stsc_sample_index
5537             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
5538                 &stream->chunk_offset))
5539           goto corrupt_file;
5540
5541         samples_per_chunk = stream->samples_per_chunk;
5542         chunk_offset = stream->chunk_offset;
5543
5544         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
5545           GST_LOG_OBJECT (qtdemux, "Creating entry %d with offset %"
5546               G_GUINT64_FORMAT, (guint) (cur - samples), stream->chunk_offset);
5547
5548           cur->offset = chunk_offset;
5549           chunk_offset += cur->size;
5550           cur++;
5551
5552           if (G_UNLIKELY (cur > last)) {
5553             /* save state */
5554             stream->stsc_sample_index = k + 1;
5555             stream->chunk_offset = chunk_offset;
5556             stream->stsc_chunk_index = j;
5557             goto done2;
5558           }
5559         }
5560         stream->stsc_sample_index = 0;
5561       }
5562       stream->stsc_chunk_index = j;
5563     } else {
5564       cur = &samples[stream->stsc_chunk_index];
5565
5566       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
5567         if (j > n) {
5568           /* save state */
5569           stream->stsc_chunk_index = j;
5570           goto done;
5571         }
5572
5573         cur->offset =
5574             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
5575             stream->co_size);
5576
5577         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
5578             "%" G_GUINT64_FORMAT, j, cur->offset);
5579
5580         if (stream->samples_per_frame * stream->bytes_per_frame) {
5581           cur->size =
5582               (stream->samples_per_chunk * stream->n_channels) /
5583               stream->samples_per_frame * stream->bytes_per_frame;
5584         } else {
5585           cur->size = stream->samples_per_chunk;
5586         }
5587
5588         GST_DEBUG_OBJECT (qtdemux,
5589             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
5590             j, GST_TIME_ARGS (gst_util_uint64_scale (stream->stco_sample_index,
5591                     GST_SECOND, stream->timescale)), cur->size);
5592
5593         cur->timestamp = stream->stco_sample_index;
5594         cur->duration = stream->samples_per_chunk;
5595         cur->keyframe = TRUE;
5596         cur++;
5597
5598         stream->stco_sample_index += stream->samples_per_chunk;
5599       }
5600       stream->stsc_chunk_index = j;
5601     }
5602     stream->stsc_index++;
5603   }
5604
5605   if (!stream->chunks_are_chunks)
5606     goto ctts;
5607 done2:
5608   {
5609     guint32 n_sample_times;
5610
5611     n_sample_times = stream->n_sample_times;
5612     cur = first;
5613
5614     for (i = stream->stts_index; i < n_sample_times; i++) {
5615       guint32 stts_samples;
5616       guint32 stts_duration;
5617       guint32 stts_time;
5618
5619       if (stream->stts_sample_index >= stream->stts_samples
5620           || !stream->stts_sample_index) {
5621
5622         stream->stts_samples =
5623             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
5624         stream->stts_duration =
5625             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
5626
5627         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
5628             i, stream->stts_samples, stream->stts_duration);
5629
5630         stream->stts_sample_index = 0;
5631       }
5632
5633       stts_samples = stream->stts_samples;
5634       stts_duration = stream->stts_duration;
5635       stts_time = stream->stts_time;
5636
5637       for (j = stream->stts_sample_index; j < stts_samples; j++) {
5638         GST_DEBUG_OBJECT (qtdemux,
5639             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
5640             (guint) (cur - samples), j,
5641             GST_TIME_ARGS (gst_util_uint64_scale (stts_time, GST_SECOND,
5642                     stream->timescale)));
5643
5644         cur->timestamp = stts_time;
5645         cur->duration = stts_duration;
5646
5647         stts_time += stts_duration;
5648         cur++;
5649
5650         if (G_UNLIKELY (cur > last)) {
5651           /* save values */
5652           stream->stts_time = stts_time;
5653           stream->stts_sample_index = j + 1;
5654           goto done3;
5655         }
5656       }
5657       stream->stts_sample_index = 0;
5658       stream->stts_time = stts_time;
5659       stream->stts_index++;
5660     }
5661     /* fill up empty timestamps with the last timestamp, this can happen when
5662      * the last samples do not decode and so we don't have timestamps for them.
5663      * We however look at the last timestamp to estimate the track length so we
5664      * need something in here. */
5665     for (; cur < last; cur++) {
5666       GST_DEBUG_OBJECT (qtdemux,
5667           "fill sample %d: timestamp %" GST_TIME_FORMAT,
5668           (guint) (cur - samples),
5669           GST_TIME_ARGS (gst_util_uint64_scale (stream->stts_time, GST_SECOND,
5670                   stream->timescale)));
5671       cur->timestamp = stream->stts_time;
5672       cur->duration = -1;
5673     }
5674   }
5675 done3:
5676   {
5677     /* sample sync, can be NULL */
5678     if (stream->stss_present == TRUE) {
5679       guint32 n_sample_syncs;
5680
5681       n_sample_syncs = stream->n_sample_syncs;
5682
5683       if (!n_sample_syncs) {
5684         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
5685         stream->all_keyframe = TRUE;
5686       } else {
5687         for (i = stream->stss_index; i < n_sample_syncs; i++) {
5688           /* note that the first sample is index 1, not 0 */
5689           guint32 index;
5690
5691           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
5692
5693           if (G_LIKELY (index > 0 && index <= n_samples)) {
5694             index -= 1;
5695             samples[index].keyframe = TRUE;
5696             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
5697             /* and exit if we have enough samples */
5698             if (G_UNLIKELY (index >= n)) {
5699               i++;
5700               break;
5701             }
5702           }
5703         }
5704         /* save state */
5705         stream->stss_index = i;
5706       }
5707
5708       /* stps marks partial sync frames like open GOP I-Frames */
5709       if (stream->stps_present == TRUE) {
5710         guint32 n_sample_partial_syncs;
5711
5712         n_sample_partial_syncs = stream->n_sample_partial_syncs;
5713
5714         /* if there are no entries, the stss table contains the real
5715          * sync samples */
5716         if (n_sample_partial_syncs) {
5717           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
5718             /* note that the first sample is index 1, not 0 */
5719             guint32 index;
5720
5721             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
5722
5723             if (G_LIKELY (index > 0 && index <= n_samples)) {
5724               index -= 1;
5725               samples[index].keyframe = TRUE;
5726               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
5727               /* and exit if we have enough samples */
5728               if (G_UNLIKELY (index >= n)) {
5729                 i++;
5730                 break;
5731               }
5732             }
5733           }
5734           /* save state */
5735           stream->stps_index = i;
5736         }
5737       }
5738     } else {
5739       /* no stss, all samples are keyframes */
5740       stream->all_keyframe = TRUE;
5741       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
5742     }
5743   }
5744
5745 ctts:
5746   /* composition time to sample */
5747   if (stream->ctts_present == TRUE) {
5748     guint32 n_composition_times;
5749     guint32 ctts_count;
5750     gint32 ctts_soffset;
5751
5752     /* Fill in the pts_offsets */
5753     cur = first;
5754     n_composition_times = stream->n_composition_times;
5755
5756     for (i = stream->ctts_index; i < n_composition_times; i++) {
5757       if (stream->ctts_sample_index >= stream->ctts_count
5758           || !stream->ctts_sample_index) {
5759         stream->ctts_count =
5760             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
5761         stream->ctts_soffset =
5762             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
5763         stream->ctts_sample_index = 0;
5764       }
5765
5766       ctts_count = stream->ctts_count;
5767       ctts_soffset = stream->ctts_soffset;
5768
5769       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
5770         cur->pts_offset = ctts_soffset;
5771         cur++;
5772
5773         if (G_UNLIKELY (cur > last)) {
5774           /* save state */
5775           stream->ctts_sample_index = j + 1;
5776           goto done;
5777         }
5778       }
5779       stream->ctts_sample_index = 0;
5780       stream->ctts_index++;
5781     }
5782   }
5783 done:
5784   stream->stbl_index = n;
5785   /* if index has been completely parsed, free data that is no-longer needed */
5786   if (n + 1 == stream->n_samples) {
5787     gst_qtdemux_stbl_free (stream);
5788     GST_DEBUG_OBJECT (qtdemux,
5789         "parsed all available samples; checking for more");
5790     while (n + 1 == stream->n_samples)
5791       if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
5792         break;
5793   }
5794   GST_OBJECT_UNLOCK (qtdemux);
5795
5796   return TRUE;
5797
5798   /* SUCCESS */
5799 already_parsed:
5800   {
5801     GST_LOG_OBJECT (qtdemux,
5802         "Tried to parse up to sample %u but this sample has already been parsed",
5803         n);
5804     /* if fragmented, there may be more */
5805     if (qtdemux->fragmented && n == stream->stbl_index)
5806       goto done;
5807     GST_OBJECT_UNLOCK (qtdemux);
5808     return TRUE;
5809   }
5810   /* ERRORS */
5811 out_of_samples:
5812   {
5813     GST_LOG_OBJECT (qtdemux,
5814         "Tried to parse up to sample %u but there are only %u samples", n + 1,
5815         stream->n_samples);
5816     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
5817         (_("This file is corrupt and cannot be played.")), (NULL));
5818     return FALSE;
5819   }
5820 corrupt_file:
5821   {
5822     GST_OBJECT_UNLOCK (qtdemux);
5823     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
5824         (_("This file is corrupt and cannot be played.")), (NULL));
5825     return FALSE;
5826   }
5827 }
5828
5829 /* collect all segment info for @stream.
5830  */
5831 static gboolean
5832 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
5833     GNode * trak)
5834 {
5835   GNode *edts;
5836
5837   /* parse and prepare segment info from the edit list */
5838   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
5839   stream->n_segments = 0;
5840   stream->segments = NULL;
5841   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
5842     GNode *elst;
5843     gint n_segments;
5844     gint i, count;
5845     guint64 time, stime;
5846     guint8 *buffer;
5847
5848     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
5849     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
5850       goto done;
5851
5852     buffer = elst->data;
5853
5854     n_segments = QT_UINT32 (buffer + 12);
5855
5856     /* we might allocate a bit too much, at least allocate 1 segment */
5857     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
5858
5859     /* segments always start from 0 */
5860     time = 0;
5861     stime = 0;
5862     count = 0;
5863     for (i = 0; i < n_segments; i++) {
5864       guint64 duration;
5865       guint64 media_time;
5866       QtDemuxSegment *segment;
5867       guint32 rate_int;
5868
5869       media_time = QT_UINT32 (buffer + 20 + i * 12);
5870
5871       /* -1 media time is an empty segment, just ignore it */
5872       if (media_time == G_MAXUINT32)
5873         continue;
5874
5875       duration = QT_UINT32 (buffer + 16 + i * 12);
5876
5877       segment = &stream->segments[count++];
5878
5879       /* time and duration expressed in global timescale */
5880       segment->time = stime;
5881       /* add non scaled values so we don't cause roundoff errors */
5882       time += duration;
5883       stime = gst_util_uint64_scale (time, GST_SECOND, qtdemux->timescale);
5884       segment->stop_time = stime;
5885       segment->duration = stime - segment->time;
5886       /* media_time expressed in stream timescale */
5887       segment->media_start =
5888           gst_util_uint64_scale (media_time, GST_SECOND, stream->timescale);
5889       segment->media_stop = segment->media_start + segment->duration;
5890       rate_int = GST_READ_UINT32_BE (buffer + 24 + i * 12);
5891
5892       if (rate_int <= 1) {
5893         /* 0 is not allowed, some programs write 1 instead of the floating point
5894          * value */
5895         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
5896             rate_int);
5897         segment->rate = 1;
5898       } else {
5899         segment->rate = rate_int / 65536.0;
5900       }
5901
5902       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
5903           ", duration %" GST_TIME_FORMAT ", media_time %" GST_TIME_FORMAT
5904           ", rate %g, (%d)", i, GST_TIME_ARGS (segment->time),
5905           GST_TIME_ARGS (segment->duration),
5906           GST_TIME_ARGS (segment->media_start), segment->rate, rate_int);
5907     }
5908     GST_DEBUG_OBJECT (qtdemux, "found %d non-empty segments", count);
5909     stream->n_segments = count;
5910   }
5911 done:
5912
5913   /* push based does not handle segments, so act accordingly here,
5914    * and warn if applicable */
5915   if (!qtdemux->pullbased) {
5916     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
5917     /* remove and use default one below, we stream like it anyway */
5918     g_free (stream->segments);
5919     stream->segments = NULL;
5920     stream->n_segments = 0;
5921   }
5922
5923   /* no segments, create one to play the complete trak */
5924   if (stream->n_segments == 0) {
5925     GstClockTime stream_duration =
5926         gst_util_uint64_scale (stream->duration, GST_SECOND, stream->timescale);
5927
5928     if (stream->segments == NULL)
5929       stream->segments = g_new (QtDemuxSegment, 1);
5930
5931     /* represent unknown our way */
5932     if (stream_duration == 0)
5933       stream_duration = -1;
5934
5935     stream->segments[0].time = 0;
5936     stream->segments[0].stop_time = stream_duration;
5937     stream->segments[0].duration = stream_duration;
5938     stream->segments[0].media_start = 0;
5939     stream->segments[0].media_stop = stream_duration;
5940     stream->segments[0].rate = 1.0;
5941
5942     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
5943         GST_TIME_ARGS (stream_duration));
5944     stream->n_segments = 1;
5945   }
5946   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
5947
5948   return TRUE;
5949 }
5950
5951 /*
5952  * Parses the stsd atom of a svq3 trak looking for
5953  * the SMI and gama atoms.
5954  */
5955 static void
5956 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux, GNode * stsd,
5957     guint8 ** gamma, GstBuffer ** seqh)
5958 {
5959   guint8 *_gamma = NULL;
5960   GstBuffer *_seqh = NULL;
5961   guint8 *stsd_data = stsd->data;
5962   guint32 length = QT_UINT32 (stsd_data);
5963   guint16 version;
5964
5965   if (length < 32) {
5966     GST_WARNING_OBJECT (qtdemux, "stsd too short");
5967     goto end;
5968   }
5969
5970   stsd_data += 32;
5971   length -= 32;
5972   version = QT_UINT16 (stsd_data);
5973   if (version == 3) {
5974     if (length >= 70) {
5975       length -= 70;
5976       stsd_data += 70;
5977       while (length > 8) {
5978         guint32 fourcc, size;
5979         guint8 *data;
5980         size = QT_UINT32 (stsd_data);
5981         fourcc = QT_FOURCC (stsd_data + 4);
5982         data = stsd_data + 8;
5983
5984         switch (fourcc) {
5985           case FOURCC_gama:{
5986             if (size == 12) {
5987               _gamma = data;
5988             } else {
5989               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
5990                   " for gama atom, expected 12", size);
5991             }
5992             break;
5993           }
5994           case FOURCC_SMI_:{
5995             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
5996               guint32 seqh_size;
5997               if (_seqh != NULL) {
5998                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
5999                     " found, ignoring");
6000               } else {
6001                 seqh_size = QT_UINT32 (data + 4);
6002                 if (seqh_size > 0) {
6003                   _seqh = gst_buffer_new_and_alloc (seqh_size);
6004                   memcpy (GST_BUFFER_DATA (_seqh), data + 8, seqh_size);
6005                 }
6006               }
6007             }
6008             break;
6009           }
6010           default:{
6011             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
6012                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
6013           }
6014         }
6015
6016         if (size <= length) {
6017           length -= size;
6018           stsd_data += size;
6019         }
6020       }
6021     } else {
6022       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
6023     }
6024   } else {
6025     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
6026         G_GUINT16_FORMAT, version);
6027     goto end;
6028   }
6029
6030 end:
6031   if (gamma) {
6032     *gamma = _gamma;
6033   }
6034   if (seqh) {
6035     *seqh = _seqh;
6036   } else if (_seqh) {
6037     gst_buffer_unref (_seqh);
6038   }
6039 }
6040
6041 static gchar *
6042 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
6043 {
6044   GNode *dinf;
6045   GstByteReader dref;
6046   gchar *uri = NULL;
6047
6048   /*
6049    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
6050    * atom that might contain a 'data' atom with the rtsp uri.
6051    * This case was reported in bug #597497, some info about
6052    * the hndl atom can be found in TN1195
6053    */
6054   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
6055   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
6056
6057   if (dinf) {
6058     guint32 dref_num_entries = 0;
6059     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
6060         gst_byte_reader_skip (&dref, 4) &&
6061         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
6062       gint i;
6063
6064       /* search dref entries for hndl atom */
6065       for (i = 0; i < dref_num_entries; i++) {
6066         guint32 size = 0, type;
6067         guint8 string_len = 0;
6068         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
6069             qt_atom_parser_get_fourcc (&dref, &type)) {
6070           if (type == FOURCC_hndl) {
6071             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
6072
6073             /* skip data reference handle bytes and the
6074              * following pascal string and some extra 4
6075              * bytes I have no idea what are */
6076             if (!gst_byte_reader_skip (&dref, 4) ||
6077                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
6078                 !gst_byte_reader_skip (&dref, string_len + 4)) {
6079               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
6080               break;
6081             }
6082
6083             /* iterate over the atoms to find the data atom */
6084             while (gst_byte_reader_get_remaining (&dref) >= 8) {
6085               guint32 atom_size;
6086               guint32 atom_type;
6087
6088               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
6089                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
6090                 if (atom_type == FOURCC_data) {
6091                   const guint8 *uri_aux = NULL;
6092
6093                   /* found the data atom that might contain the rtsp uri */
6094                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
6095                       "hndl atom, interpreting it as an URI");
6096                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
6097                           &uri_aux)) {
6098                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
6099                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
6100                     else
6101                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
6102                           "didn't contain a rtsp address");
6103                   } else {
6104                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
6105                         "atom contents");
6106                   }
6107                   break;
6108                 }
6109                 /* skipping to the next entry */
6110                 gst_byte_reader_skip (&dref, atom_size - 8);
6111               } else {
6112                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
6113                     "atom header");
6114                 break;
6115               }
6116             }
6117             break;
6118           }
6119           /* skip to the next entry */
6120           gst_byte_reader_skip (&dref, size - 8);
6121         } else {
6122           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
6123         }
6124       }
6125       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
6126     }
6127   }
6128   return uri;
6129 }
6130
6131 static gint
6132 less_than (gconstpointer a, gconstpointer b)
6133 {
6134   const guint32 *av = a, *bv = b;
6135
6136   return *av - *bv;
6137 }
6138
6139 /* parse the traks.
6140  * With each track we associate a new QtDemuxStream that contains all the info
6141  * about the trak.
6142  * traks that do not decode to something (like strm traks) will not have a pad.
6143  */
6144 static gboolean
6145 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
6146 {
6147   GstByteReader tkhd;
6148   int offset;
6149   GNode *mdia;
6150   GNode *mdhd;
6151   GNode *hdlr;
6152   GNode *minf;
6153   GNode *stbl;
6154   GNode *stsd;
6155   GNode *mp4a;
6156   GNode *mp4v;
6157   GNode *wave;
6158   GNode *esds;
6159   GNode *pasp;
6160   QtDemuxStream *stream;
6161   GstTagList *list = NULL;
6162   gchar *codec = NULL;
6163   const guint8 *stsd_data;
6164   guint16 lang_code;            /* quicktime lang code or packed iso code */
6165   guint32 version;
6166   guint32 tkhd_flags = 0;
6167   guint8 tkhd_version = 0;
6168   guint32 fourcc;
6169   guint value_size, len;
6170
6171   stream = g_new0 (QtDemuxStream, 1);
6172   /* new streams always need a discont */
6173   stream->discont = TRUE;
6174   /* we enable clipping for raw audio/video streams */
6175   stream->need_clip = FALSE;
6176   stream->need_process = FALSE;
6177   stream->segment_index = -1;
6178   stream->time_position = 0;
6179   stream->sample_index = -1;
6180   stream->last_ret = GST_FLOW_OK;
6181
6182   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
6183       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
6184       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
6185     goto corrupt_file;
6186
6187   /* pick between 64 or 32 bits */
6188   value_size = tkhd_version == 1 ? 8 : 4;
6189   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
6190       !gst_byte_reader_get_uint32_be (&tkhd, &stream->track_id))
6191     goto corrupt_file;
6192
6193   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
6194       tkhd_version, tkhd_flags, stream->track_id);
6195
6196   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
6197     goto corrupt_file;
6198
6199   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
6200     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
6201     if (qtdemux->major_brand != FOURCC_mjp2 ||
6202         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
6203       goto corrupt_file;
6204   }
6205
6206   len = QT_UINT32 ((guint8 *) mdhd->data);
6207   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
6208   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
6209   if (version == 0x01000000) {
6210     if (len < 38)
6211       goto corrupt_file;
6212     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
6213     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
6214     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
6215   } else {
6216     if (len < 30)
6217       goto corrupt_file;
6218     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
6219     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
6220     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
6221   }
6222
6223   if (lang_code < 0x800) {
6224     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
6225   } else {
6226     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
6227     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
6228     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
6229     stream->lang_id[3] = 0;
6230   }
6231
6232   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
6233       stream->timescale);
6234   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
6235       stream->duration);
6236   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
6237       lang_code, stream->lang_id);
6238
6239   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
6240     goto corrupt_file;
6241
6242   /* fragmented files may have bogus duration in moov */
6243   if (!qtdemux->fragmented &&
6244       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
6245     guint64 tdur1, tdur2;
6246
6247     /* don't overflow */
6248     tdur1 = stream->timescale * (guint64) qtdemux->duration;
6249     tdur2 = qtdemux->timescale * (guint64) stream->duration;
6250
6251     /* HACK:
6252      * some of those trailers, nowadays, have prologue images that are
6253      * themselves vide tracks as well. I haven't really found a way to
6254      * identify those yet, except for just looking at their duration. */
6255     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
6256       GST_WARNING_OBJECT (qtdemux,
6257           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
6258           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
6259           "found, assuming preview image or something; skipping track",
6260           stream->duration, stream->timescale, qtdemux->duration,
6261           qtdemux->timescale);
6262       g_free (stream);
6263       return TRUE;
6264     }
6265   }
6266
6267   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
6268     goto corrupt_file;
6269
6270   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
6271       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
6272
6273   len = QT_UINT32 ((guint8 *) hdlr->data);
6274   if (len >= 20)
6275     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
6276   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
6277       GST_FOURCC_ARGS (stream->subtype));
6278
6279   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
6280     goto corrupt_file;
6281
6282   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
6283     goto corrupt_file;
6284
6285   /* parse stsd */
6286   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
6287     goto corrupt_file;
6288   stsd_data = (const guint8 *) stsd->data;
6289
6290   /* stsd should at least have one entry */
6291   len = QT_UINT32 (stsd_data);
6292   if (len < 24)
6293     goto corrupt_file;
6294
6295   /* and that entry should fit within stsd */
6296   len = QT_UINT32 (stsd_data + 16);
6297   if (len > QT_UINT32 (stsd_data) + 16)
6298     goto corrupt_file;
6299   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", len);
6300
6301   stream->fourcc = fourcc = QT_FOURCC (stsd_data + 16 + 4);
6302   GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
6303       GST_FOURCC_ARGS (stream->fourcc));
6304
6305   if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi) ||
6306       ((fourcc & 0xFFFFFF00) == GST_MAKE_FOURCC ('e', 'n', 'c', 0)))
6307     goto error_encrypted;
6308
6309   if (stream->subtype == FOURCC_vide) {
6310     guint32 w = 0, h = 0;
6311
6312     stream->sampled = TRUE;
6313
6314     /* version 1 uses some 64-bit ints */
6315     if (!gst_byte_reader_skip (&tkhd, 56 + value_size)
6316         || !gst_byte_reader_get_uint32_be (&tkhd, &w)
6317         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
6318       goto corrupt_file;
6319
6320     stream->display_width = w >> 16;
6321     stream->display_height = h >> 16;
6322
6323     offset = 16;
6324     if (len < 86)
6325       goto corrupt_file;
6326
6327     stream->width = QT_UINT16 (stsd_data + offset + 32);
6328     stream->height = QT_UINT16 (stsd_data + offset + 34);
6329     stream->fps_n = 0;          /* this is filled in later */
6330     stream->fps_d = 0;          /* this is filled in later */
6331     stream->bits_per_sample = QT_UINT16 (stsd_data + offset + 82);
6332     stream->color_table_id = QT_UINT16 (stsd_data + offset + 84);
6333
6334     GST_LOG_OBJECT (qtdemux, "frame count:   %u",
6335         QT_UINT16 (stsd_data + offset + 48));
6336
6337     stream->caps =
6338         qtdemux_video_caps (qtdemux, stream, fourcc, stsd_data, &codec);
6339     if (codec) {
6340       list = gst_tag_list_new ();
6341       gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
6342           GST_TAG_VIDEO_CODEC, codec, NULL);
6343       g_free (codec);
6344       codec = NULL;
6345     }
6346
6347     esds = NULL;
6348     pasp = NULL;
6349     /* pick 'the' stsd child */
6350     mp4v = qtdemux_tree_get_child_by_type (stsd, fourcc);
6351     if (mp4v) {
6352       esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
6353       pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
6354     }
6355
6356     if (pasp) {
6357       const guint8 *pasp_data = (const guint8 *) pasp->data;
6358
6359       stream->par_w = QT_UINT32 (pasp_data + 8);
6360       stream->par_h = QT_UINT32 (pasp_data + 12);
6361     } else {
6362       stream->par_w = 0;
6363       stream->par_h = 0;
6364     }
6365
6366     if (esds) {
6367       gst_qtdemux_handle_esds (qtdemux, stream, esds, list);
6368     } else {
6369       switch (fourcc) {
6370         case FOURCC_avc1:
6371         {
6372           gint len = QT_UINT32 (stsd_data) - 0x66;
6373           const guint8 *avc_data = stsd_data + 0x66;
6374
6375           /* find avcC */
6376           while (len >= 0x8) {
6377             gint size;
6378
6379             if (QT_UINT32 (avc_data) <= len)
6380               size = QT_UINT32 (avc_data) - 0x8;
6381             else
6382               size = len - 0x8;
6383
6384             if (size < 1)
6385               /* No real data, so break out */
6386               break;
6387
6388             switch (QT_FOURCC (avc_data + 0x4)) {
6389               case FOURCC_avcC:
6390               {
6391                 /* parse, if found */
6392                 GstBuffer *buf;
6393
6394                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
6395
6396                 /* First 4 bytes are the length of the atom, the next 4 bytes
6397                  * are the fourcc, the next 1 byte is the version, and the
6398                  * subsequent bytes are sequence parameter set like data. */
6399                 gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
6400                     avc_data + 8 + 1, size - 1);
6401
6402                 buf = gst_buffer_new_and_alloc (size);
6403                 memcpy (GST_BUFFER_DATA (buf), avc_data + 0x8, size);
6404                 gst_caps_set_simple (stream->caps,
6405                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
6406                 gst_buffer_unref (buf);
6407
6408                 break;
6409               }
6410               case FOURCC_btrt:
6411               {
6412                 guint avg_bitrate, max_bitrate;
6413
6414                 /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
6415                 if (size < 12)
6416                   break;
6417
6418                 max_bitrate = QT_UINT32 (avc_data + 0xc);
6419                 avg_bitrate = QT_UINT32 (avc_data + 0x10);
6420
6421                 if (!max_bitrate && !avg_bitrate)
6422                   break;
6423
6424                 /* Some muxers seem to swap the average and maximum bitrates
6425                  * (I'm looking at you, YouTube), so we swap for sanity. */
6426                 if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
6427                   guint temp = avg_bitrate;
6428
6429                   avg_bitrate = max_bitrate;
6430                   max_bitrate = temp;
6431                 }
6432
6433                 if (!list)
6434                   list = gst_tag_list_new ();
6435
6436                 if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
6437                   gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
6438                       GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
6439                 }
6440                 if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
6441                   gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
6442                       GST_TAG_BITRATE, avg_bitrate, NULL);
6443                 }
6444
6445                 break;
6446               }
6447
6448               default:
6449                 break;
6450             }
6451
6452             len -= size + 8;
6453             avc_data += size + 8;
6454           }
6455
6456           break;
6457         }
6458         case FOURCC_mp4v:
6459         case FOURCC_MP4V:
6460         case FOURCC_fmp4:
6461         case FOURCC_FMP4:
6462         {
6463           GNode *glbl;
6464
6465           GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
6466               GST_FOURCC_ARGS (fourcc));
6467
6468           /* codec data might be in glbl extension atom */
6469           glbl = mp4v ?
6470               qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
6471           if (glbl) {
6472             guint8 *data;
6473             GstBuffer *buf;
6474             gint len;
6475
6476             GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
6477             data = glbl->data;
6478             len = QT_UINT32 (data);
6479             if (len > 0x8) {
6480               len -= 0x8;
6481               buf = gst_buffer_new_and_alloc (len);
6482               memcpy (GST_BUFFER_DATA (buf), data + 8, len);
6483               gst_caps_set_simple (stream->caps,
6484                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
6485               gst_buffer_unref (buf);
6486             }
6487           }
6488           break;
6489         }
6490         case FOURCC_mjp2:
6491         {
6492           /* see annex I of the jpeg2000 spec */
6493           GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
6494           const guint8 *data;
6495           guint32 fourcc = 0;
6496           gint ncomp = 0;
6497           guint32 ncomp_map = 0;
6498           gint32 *comp_map = NULL;
6499           guint32 nchan_def = 0;
6500           gint32 *chan_def = NULL;
6501
6502           GST_DEBUG_OBJECT (qtdemux, "found mjp2");
6503           /* some required atoms */
6504           mjp2 = qtdemux_tree_get_child_by_type (stsd, FOURCC_mjp2);
6505           if (!mjp2)
6506             break;
6507           jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
6508           if (!jp2h)
6509             break;
6510
6511           /* number of components; redundant with info in codestream, but useful
6512              to a muxer */
6513           ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
6514           if (!ihdr || QT_UINT32 (ihdr->data) != 22)
6515             break;
6516           ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
6517
6518           colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
6519           if (!colr)
6520             break;
6521           GST_DEBUG_OBJECT (qtdemux, "found colr");
6522           /* extract colour space info */
6523           if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
6524             switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
6525               case 16:
6526                 fourcc = GST_MAKE_FOURCC ('s', 'R', 'G', 'B');
6527                 break;
6528               case 17:
6529                 fourcc = GST_MAKE_FOURCC ('G', 'R', 'A', 'Y');
6530                 break;
6531               case 18:
6532                 fourcc = GST_MAKE_FOURCC ('s', 'Y', 'U', 'V');
6533                 break;
6534               default:
6535                 break;
6536             }
6537           }
6538           if (!fourcc)
6539             /* colr is required, and only values 16, 17, and 18 are specified,
6540                so error if we have no fourcc */
6541             break;
6542
6543           /* extract component mapping */
6544           cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
6545           if (cmap) {
6546             guint32 cmap_len = 0;
6547             int i;
6548             cmap_len = QT_UINT32 (cmap->data);
6549             if (cmap_len >= 8) {
6550               /* normal box, subtract off header */
6551               cmap_len -= 8;
6552               /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
6553               if (cmap_len % 4 == 0) {
6554                 ncomp_map = (cmap_len / 4);
6555                 comp_map = g_new0 (gint32, ncomp_map);
6556                 for (i = 0; i < ncomp_map; i++) {
6557                   guint16 cmp;
6558                   guint8 mtyp, pcol;
6559                   cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
6560                   mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
6561                   pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
6562                   comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
6563                 }
6564               }
6565             }
6566           }
6567           /* extract channel definitions */
6568           cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
6569           if (cdef) {
6570             guint32 cdef_len = 0;
6571             int i;
6572             cdef_len = QT_UINT32 (cdef->data);
6573             if (cdef_len >= 10) {
6574               /* normal box, subtract off header and len */
6575               cdef_len -= 10;
6576               /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
6577               if (cdef_len % 6 == 0) {
6578                 nchan_def = (cdef_len / 6);
6579                 chan_def = g_new0 (gint32, nchan_def);
6580                 for (i = 0; i < nchan_def; i++)
6581                   chan_def[i] = -1;
6582                 for (i = 0; i < nchan_def; i++) {
6583                   guint16 cn, typ, asoc;
6584                   cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
6585                   typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
6586                   asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
6587                   if (cn < nchan_def) {
6588                     switch (typ) {
6589                       case 0:
6590                         chan_def[cn] = asoc;
6591                         break;
6592                       case 1:
6593                         chan_def[cn] = 0;       /* alpha */
6594                         break;
6595                       default:
6596                         chan_def[cn] = -typ;
6597                     }
6598                   }
6599                 }
6600               }
6601             }
6602           }
6603
6604           gst_caps_set_simple (stream->caps,
6605               "num-components", G_TYPE_INT, ncomp, NULL);
6606           gst_caps_set_simple (stream->caps,
6607               "fourcc", GST_TYPE_FOURCC, fourcc, NULL);
6608
6609           if (comp_map) {
6610             GValue arr = { 0, };
6611             GValue elt = { 0, };
6612             int i;
6613             g_value_init (&arr, GST_TYPE_ARRAY);
6614             g_value_init (&elt, G_TYPE_INT);
6615             for (i = 0; i < ncomp_map; i++) {
6616               g_value_set_int (&elt, comp_map[i]);
6617               gst_value_array_append_value (&arr, &elt);
6618             }
6619             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
6620                 "component-map", &arr);
6621             g_value_unset (&elt);
6622             g_value_unset (&arr);
6623             g_free (comp_map);
6624           }
6625
6626           if (chan_def) {
6627             GValue arr = { 0, };
6628             GValue elt = { 0, };
6629             int i;
6630             g_value_init (&arr, GST_TYPE_ARRAY);
6631             g_value_init (&elt, G_TYPE_INT);
6632             for (i = 0; i < nchan_def; i++) {
6633               g_value_set_int (&elt, chan_def[i]);
6634               gst_value_array_append_value (&arr, &elt);
6635             }
6636             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
6637                 "channel-definitions", &arr);
6638             g_value_unset (&elt);
6639             g_value_unset (&arr);
6640             g_free (chan_def);
6641           }
6642
6643           /* some optional atoms */
6644           field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
6645           prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
6646
6647           /* indicate possible fields in caps */
6648           if (field) {
6649             data = (guint8 *) field->data + 8;
6650             if (*data != 1)
6651               gst_caps_set_simple (stream->caps, "fields", G_TYPE_INT,
6652                   (gint) * data, NULL);
6653           }
6654           /* add codec_data if provided */
6655           if (prefix) {
6656             GstBuffer *buf;
6657             gint len;
6658
6659             GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
6660             data = prefix->data;
6661             len = QT_UINT32 (data);
6662             if (len > 0x8) {
6663               len -= 0x8;
6664               buf = gst_buffer_new_and_alloc (len);
6665               memcpy (GST_BUFFER_DATA (buf), data + 8, len);
6666               gst_caps_set_simple (stream->caps,
6667                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
6668               gst_buffer_unref (buf);
6669             }
6670           }
6671           break;
6672         }
6673         case FOURCC_SVQ3:
6674         case FOURCC_VP31:
6675         {
6676           GstBuffer *buf;
6677           GstBuffer *seqh = NULL;
6678           guint8 *gamma_data = NULL;
6679           gint len = QT_UINT32 (stsd_data);
6680
6681           qtdemux_parse_svq3_stsd_data (qtdemux, stsd, &gamma_data, &seqh);
6682           if (gamma_data) {
6683             gst_caps_set_simple (stream->caps, "applied-gamma", G_TYPE_DOUBLE,
6684                 QT_FP32 (gamma_data), NULL);
6685           }
6686           if (seqh) {
6687             /* sorry for the bad name, but we don't know what this is, other
6688              * than its own fourcc */
6689             gst_caps_set_simple (stream->caps, "seqh", GST_TYPE_BUFFER, seqh,
6690                 NULL);
6691           }
6692
6693           GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
6694           buf = gst_buffer_new_and_alloc (len);
6695           memcpy (GST_BUFFER_DATA (buf), stsd_data, len);
6696           gst_caps_set_simple (stream->caps,
6697               "codec_data", GST_TYPE_BUFFER, buf, NULL);
6698           gst_buffer_unref (buf);
6699           break;
6700         }
6701         case FOURCC_rle_:
6702         {
6703           gst_caps_set_simple (stream->caps,
6704               "depth", G_TYPE_INT, QT_UINT16 (stsd_data + offset + 82), NULL);
6705           break;
6706         }
6707         case FOURCC_XiTh:
6708         {
6709           GNode *xith, *xdxt;
6710
6711           GST_DEBUG_OBJECT (qtdemux, "found XiTh");
6712           xith = qtdemux_tree_get_child_by_type (stsd, FOURCC_XiTh);
6713           if (!xith)
6714             break;
6715
6716           xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
6717           if (!xdxt)
6718             break;
6719
6720           GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
6721           /* collect the headers and store them in a stream list so that we can
6722            * send them out first */
6723           qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
6724           break;
6725         }
6726         case FOURCC_ovc1:
6727         {
6728           GNode *ovc1;
6729           gchar *ovc1_data;
6730           guint ovc1_len;
6731           GstBuffer *buf;
6732
6733           GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
6734           ovc1 = qtdemux_tree_get_child_by_type (stsd, FOURCC_ovc1);
6735           if (!ovc1)
6736             break;
6737           ovc1_data = ovc1->data;
6738           ovc1_len = QT_UINT32 (ovc1_data);
6739           if (ovc1_len <= 198) {
6740             GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
6741             break;
6742           }
6743           buf = gst_buffer_new_and_alloc (ovc1_len - 198);
6744           memcpy (GST_BUFFER_DATA (buf), ovc1_data + 198, ovc1_len - 198);
6745           gst_caps_set_simple (stream->caps,
6746               "codec_data", GST_TYPE_BUFFER, buf, NULL);
6747           gst_buffer_unref (buf);
6748           break;
6749         }
6750         default:
6751           break;
6752       }
6753     }
6754
6755     GST_INFO_OBJECT (qtdemux,
6756         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
6757         GST_FOURCC_ARGS (fourcc), stream->caps);
6758
6759   } else if (stream->subtype == FOURCC_soun) {
6760     int version, samplesize;
6761     guint16 compression_id;
6762
6763     offset = 32;
6764     if (len < 36)
6765       goto corrupt_file;
6766
6767     version = QT_UINT32 (stsd_data + offset);
6768     stream->n_channels = QT_UINT16 (stsd_data + offset + 8);
6769     samplesize = QT_UINT16 (stsd_data + offset + 10);
6770     compression_id = QT_UINT16 (stsd_data + offset + 12);
6771     stream->rate = QT_FP32 (stsd_data + offset + 16);
6772
6773     GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
6774     GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
6775         QT_UINT32 (stsd_data + offset + 4));
6776     GST_LOG_OBJECT (qtdemux, "n_channels:       %d", stream->n_channels);
6777     GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
6778     GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
6779     GST_LOG_OBJECT (qtdemux, "packet size:      %d",
6780         QT_UINT16 (stsd_data + offset + 14));
6781     GST_LOG_OBJECT (qtdemux, "sample rate:      %g", stream->rate);
6782
6783     if (compression_id == 0xfffe)
6784       stream->sampled = TRUE;
6785
6786     /* first assume uncompressed audio */
6787     stream->bytes_per_sample = samplesize / 8;
6788     stream->samples_per_frame = stream->n_channels;
6789     stream->bytes_per_frame = stream->n_channels * stream->bytes_per_sample;
6790     stream->samples_per_packet = stream->samples_per_frame;
6791     stream->bytes_per_packet = stream->bytes_per_sample;
6792
6793     offset = 52;
6794     switch (fourcc) {
6795         /* Yes, these have to be hard-coded */
6796       case FOURCC_MAC6:
6797       {
6798         stream->samples_per_packet = 6;
6799         stream->bytes_per_packet = 1;
6800         stream->bytes_per_frame = 1 * stream->n_channels;
6801         stream->bytes_per_sample = 1;
6802         stream->samples_per_frame = 6 * stream->n_channels;
6803         break;
6804       }
6805       case FOURCC_MAC3:
6806       {
6807         stream->samples_per_packet = 3;
6808         stream->bytes_per_packet = 1;
6809         stream->bytes_per_frame = 1 * stream->n_channels;
6810         stream->bytes_per_sample = 1;
6811         stream->samples_per_frame = 3 * stream->n_channels;
6812         break;
6813       }
6814       case FOURCC_ima4:
6815       {
6816         stream->samples_per_packet = 64;
6817         stream->bytes_per_packet = 34;
6818         stream->bytes_per_frame = 34 * stream->n_channels;
6819         stream->bytes_per_sample = 2;
6820         stream->samples_per_frame = 64 * stream->n_channels;
6821         break;
6822       }
6823       case FOURCC_ulaw:
6824       case FOURCC_alaw:
6825       {
6826         stream->samples_per_packet = 1;
6827         stream->bytes_per_packet = 1;
6828         stream->bytes_per_frame = 1 * stream->n_channels;
6829         stream->bytes_per_sample = 1;
6830         stream->samples_per_frame = 1 * stream->n_channels;
6831         break;
6832       }
6833       case FOURCC_agsm:
6834       {
6835         stream->samples_per_packet = 160;
6836         stream->bytes_per_packet = 33;
6837         stream->bytes_per_frame = 33 * stream->n_channels;
6838         stream->bytes_per_sample = 2;
6839         stream->samples_per_frame = 160 * stream->n_channels;
6840         break;
6841       }
6842       default:
6843         break;
6844     }
6845
6846     if (version == 0x00010000) {
6847       switch (fourcc) {
6848         case FOURCC_twos:
6849         case FOURCC_sowt:
6850         case FOURCC_raw_:
6851           break;
6852         default:
6853         {
6854           /* only parse extra decoding config for non-pcm audio */
6855           stream->samples_per_packet = QT_UINT32 (stsd_data + offset);
6856           stream->bytes_per_packet = QT_UINT32 (stsd_data + offset + 4);
6857           stream->bytes_per_frame = QT_UINT32 (stsd_data + offset + 8);
6858           stream->bytes_per_sample = QT_UINT32 (stsd_data + offset + 12);
6859
6860           GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
6861               stream->samples_per_packet);
6862           GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
6863               stream->bytes_per_packet);
6864           GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
6865               stream->bytes_per_frame);
6866           GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
6867               stream->bytes_per_sample);
6868
6869           if (!stream->sampled && stream->bytes_per_packet) {
6870             stream->samples_per_frame = (stream->bytes_per_frame /
6871                 stream->bytes_per_packet) * stream->samples_per_packet;
6872             GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
6873                 stream->samples_per_frame);
6874           }
6875           break;
6876         }
6877       }
6878     } else if (version == 0x00020000) {
6879       union
6880       {
6881         gdouble fp;
6882         guint64 val;
6883       } qtfp;
6884
6885       stream->samples_per_packet = QT_UINT32 (stsd_data + offset);
6886       qtfp.val = QT_UINT64 (stsd_data + offset + 4);
6887       stream->rate = qtfp.fp;
6888       stream->n_channels = QT_UINT32 (stsd_data + offset + 12);
6889
6890       GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
6891           stream->samples_per_packet);
6892       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", stream->rate);
6893       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", stream->n_channels);
6894
6895     } else {
6896       GST_WARNING_OBJECT (qtdemux, "unknown version %08x", version);
6897     }
6898
6899     stream->caps = qtdemux_audio_caps (qtdemux, stream, fourcc, NULL, 0,
6900         &codec);
6901
6902     switch (fourcc) {
6903       case FOURCC_in24:
6904       {
6905         GNode *enda;
6906         GNode *in24;
6907
6908         in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
6909
6910         enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
6911         if (!enda) {
6912           wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
6913           if (wave)
6914             enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
6915         }
6916         if (enda) {
6917           gst_caps_set_simple (stream->caps,
6918               "endianness", G_TYPE_INT, G_LITTLE_ENDIAN, NULL);
6919         }
6920         break;
6921       }
6922       case FOURCC_owma:
6923       {
6924         GNode *owma;
6925         const gchar *owma_data, *codec_name = NULL;
6926         guint owma_len;
6927         GstBuffer *buf;
6928         gint version = 1;
6929         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
6930         /* FIXME this should also be gst_riff_strf_auds,
6931          * but the latter one is actually missing bits-per-sample :( */
6932         typedef struct
6933         {
6934           gint16 wFormatTag;
6935           gint16 nChannels;
6936           gint32 nSamplesPerSec;
6937           gint32 nAvgBytesPerSec;
6938           gint16 nBlockAlign;
6939           gint16 wBitsPerSample;
6940           gint16 cbSize;
6941         } WAVEFORMATEX;
6942         WAVEFORMATEX *wfex;
6943
6944         GST_DEBUG_OBJECT (qtdemux, "parse owma");
6945         owma = qtdemux_tree_get_child_by_type (stsd, FOURCC_owma);
6946         if (!owma)
6947           break;
6948         owma_data = owma->data;
6949         owma_len = QT_UINT32 (owma_data);
6950         if (owma_len <= 54) {
6951           GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
6952           break;
6953         }
6954         wfex = (WAVEFORMATEX *) (owma_data + 36);
6955         buf = gst_buffer_new_and_alloc (owma_len - 54);
6956         memcpy (GST_BUFFER_DATA (buf), owma_data + 54, owma_len - 54);
6957         if (wfex->wFormatTag == 0x0161) {
6958           codec_name = "Windows Media Audio";
6959           version = 2;
6960         } else if (wfex->wFormatTag == 0x0162) {
6961           codec_name = "Windows Media Audio 9 Pro";
6962           version = 3;
6963         } else if (wfex->wFormatTag == 0x0163) {
6964           codec_name = "Windows Media Audio 9 Lossless";
6965           /* is that correct? gstffmpegcodecmap.c is missing it, but
6966            * fluendo codec seems to support it */
6967           version = 4;
6968         }
6969
6970         gst_caps_set_simple (stream->caps,
6971             "codec_data", GST_TYPE_BUFFER, buf,
6972             "wmaversion", G_TYPE_INT, version,
6973             "block_align", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->nBlockAlign),
6974             "bitrate", G_TYPE_INT, GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec),
6975             "width", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
6976             "depth", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
6977             NULL);
6978         gst_buffer_unref (buf);
6979
6980         if (codec_name) {
6981           g_free (codec);
6982           codec = g_strdup (codec_name);
6983         }
6984         break;
6985       }
6986       default:
6987         break;
6988     }
6989
6990     if (codec) {
6991       list = gst_tag_list_new ();
6992       gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
6993           GST_TAG_AUDIO_CODEC, codec, NULL);
6994       g_free (codec);
6995       codec = NULL;
6996     }
6997
6998     mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4a);
6999     wave = NULL;
7000     esds = NULL;
7001     if (mp4a) {
7002       wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
7003       if (wave)
7004         esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
7005       if (!esds)
7006         esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
7007     }
7008
7009
7010     /* If the fourcc's bottom 16 bits gives 'sm', then the top
7011        16 bits is a byte-swapped wave-style codec identifier,
7012        and we can find a WAVE header internally to a 'wave' atom here.
7013        This can more clearly be thought of as 'ms' as the top 16 bits, and a
7014        codec id as the bottom 16 bits - but byte-swapped to store in QT (which
7015        is big-endian).
7016      */
7017     if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
7018       if (len < offset + 20) {
7019         GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
7020       } else {
7021         guint32 datalen = QT_UINT32 (stsd_data + offset + 16);
7022         const guint8 *data = stsd_data + offset + 16;
7023         GNode *wavenode;
7024         GNode *waveheadernode;
7025
7026         wavenode = g_node_new ((guint8 *) data);
7027         if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
7028           const guint8 *waveheader;
7029           guint32 headerlen;
7030
7031           waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
7032           if (waveheadernode) {
7033             waveheader = (const guint8 *) waveheadernode->data;
7034             headerlen = QT_UINT32 (waveheader);
7035
7036             if (headerlen > 8) {
7037               gst_riff_strf_auds *header = NULL;
7038               GstBuffer *headerbuf;
7039               GstBuffer *extra;
7040
7041               waveheader += 8;
7042               headerlen -= 8;
7043
7044               headerbuf = gst_buffer_new ();
7045               GST_BUFFER_DATA (headerbuf) = (guint8 *) waveheader;
7046               GST_BUFFER_SIZE (headerbuf) = headerlen;
7047
7048               if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
7049                       headerbuf, &header, &extra)) {
7050                 gst_caps_unref (stream->caps);
7051                 stream->caps = gst_riff_create_audio_caps (header->format, NULL,
7052                     header, extra, NULL, NULL);
7053
7054                 if (extra)
7055                   gst_buffer_unref (extra);
7056               }
7057             }
7058           } else
7059             GST_DEBUG ("Didn't find waveheadernode for this codec");
7060         }
7061         g_node_destroy (wavenode);
7062       }
7063     } else if (esds) {
7064       gst_qtdemux_handle_esds (qtdemux, stream, esds, list);
7065     } else {
7066       switch (fourcc) {
7067 #if 0
7068           /* FIXME: what is in the chunk? */
7069         case FOURCC_QDMC:
7070         {
7071           gint len = QT_UINT32 (stsd_data);
7072
7073           /* seems to be always = 116 = 0x74 */
7074           break;
7075         }
7076 #endif
7077         case FOURCC_QDM2:
7078         {
7079           gint len = QT_UINT32 (stsd_data);
7080
7081           if (len > 0x4C) {
7082             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x4C);
7083
7084             memcpy (GST_BUFFER_DATA (buf), stsd_data + 0x4C, len - 0x4C);
7085             gst_caps_set_simple (stream->caps,
7086                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
7087             gst_buffer_unref (buf);
7088           }
7089           gst_caps_set_simple (stream->caps,
7090               "samplesize", G_TYPE_INT, samplesize, NULL);
7091           break;
7092         }
7093         case FOURCC_alac:
7094         {
7095           GNode *alac, *wave = NULL;
7096
7097           /* apparently, m4a has this atom appended directly in the stsd entry,
7098            * while mov has it in a wave atom */
7099           alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
7100           if (alac) {
7101             /* alac now refers to stsd entry atom */
7102             wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
7103             if (wave)
7104               alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
7105             else
7106               alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
7107           }
7108           if (alac) {
7109             gint len = QT_UINT32 (alac->data);
7110             GstBuffer *buf;
7111
7112             if (len < 36) {
7113               GST_DEBUG_OBJECT (qtdemux,
7114                   "discarding alac atom with unexpected len %d", len);
7115             } else {
7116               /* codec-data contains alac atom size and prefix,
7117                * ffmpeg likes it that way, not quite gst-ish though ...*/
7118               buf = gst_buffer_new_and_alloc (len);
7119               memcpy (GST_BUFFER_DATA (buf), alac->data, len);
7120               gst_caps_set_simple (stream->caps,
7121                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
7122               gst_buffer_unref (buf);
7123             }
7124           }
7125           gst_caps_set_simple (stream->caps,
7126               "samplesize", G_TYPE_INT, samplesize, NULL);
7127           break;
7128         }
7129         case FOURCC_samr:
7130         {
7131           gint len = QT_UINT32 (stsd_data);
7132
7133           if (len > 0x34) {
7134             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x34);
7135
7136             memcpy (GST_BUFFER_DATA (buf), stsd_data + 0x34, len - 0x34);
7137
7138             gst_caps_set_simple (stream->caps,
7139                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
7140             gst_buffer_unref (buf);
7141           }
7142           break;
7143         }
7144         default:
7145           break;
7146       }
7147     }
7148     GST_INFO_OBJECT (qtdemux,
7149         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
7150         GST_FOURCC_ARGS (fourcc), stream->caps);
7151
7152   } else if (stream->subtype == FOURCC_strm) {
7153     if (fourcc == FOURCC_rtsp) {
7154       stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
7155     } else {
7156       GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
7157           GST_FOURCC_ARGS (fourcc));
7158       goto unknown_stream;
7159     }
7160     stream->sampled = TRUE;
7161   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text) {
7162
7163     stream->sampled = TRUE;
7164
7165     offset = 16;
7166
7167     stream->caps =
7168         qtdemux_sub_caps (qtdemux, stream, fourcc, stsd_data, &codec);
7169     if (codec) {
7170       list = gst_tag_list_new ();
7171       gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
7172           GST_TAG_SUBTITLE_CODEC, codec, NULL);
7173       g_free (codec);
7174       codec = NULL;
7175     }
7176
7177     /* hunt for sort-of codec data */
7178     switch (fourcc) {
7179       case FOURCC_mp4s:
7180       {
7181         guint len;
7182         const guint8 *data;
7183
7184         /* look for palette */
7185         /* target mp4s atom */
7186         len = QT_UINT32 (stsd_data + offset);
7187         data = stsd_data + offset;
7188         /* verify sufficient length,
7189          * and esds present with decConfigDescr of expected size and position */
7190         if ((len >= 106 + 8)
7191             && (QT_FOURCC (data + 8 + 8 + 4) == FOURCC_esds)
7192             && (QT_UINT16 (data + 8 + 40) == 0x0540)) {
7193           GstStructure *s;
7194           guint32 clut[16];
7195           gint i;
7196
7197           /* move to decConfigDescr data */
7198           data = data + 8 + 42;
7199           for (i = 0; i < 16; i++) {
7200             clut[i] = QT_UINT32 (data);
7201             data += 4;
7202           }
7203
7204           s = gst_structure_new ("application/x-gst-dvd", "event",
7205               G_TYPE_STRING, "dvd-spu-clut-change",
7206               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
7207               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
7208               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
7209               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
7210               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
7211               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
7212               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
7213               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
7214               NULL);
7215
7216           /* store event and trigger custom processing */
7217           stream->pending_event =
7218               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
7219           stream->need_process = TRUE;
7220         }
7221         break;
7222       }
7223       default:
7224         break;
7225     }
7226   } else {
7227     goto unknown_stream;
7228   }
7229
7230   /* promote to sampled format */
7231   if (stream->fourcc == FOURCC_samr) {
7232     /* force mono 8000 Hz for AMR */
7233     stream->sampled = TRUE;
7234     stream->n_channels = 1;
7235     stream->rate = 8000;
7236   } else if (stream->fourcc == FOURCC_sawb) {
7237     /* force mono 16000 Hz for AMR-WB */
7238     stream->sampled = TRUE;
7239     stream->n_channels = 1;
7240     stream->rate = 16000;
7241   } else if (stream->fourcc == FOURCC_mp4a) {
7242     stream->sampled = TRUE;
7243   }
7244
7245   /* collect sample information */
7246   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
7247     goto samples_failed;
7248
7249   if (qtdemux->fragmented) {
7250     guint32 dummy;
7251     guint64 offset;
7252
7253     /* need all moov samples as basis; probably not many if any at all */
7254     /* prevent moof parsing taking of at this time */
7255     offset = qtdemux->moof_offset;
7256     qtdemux->moof_offset = 0;
7257     if (stream->n_samples &&
7258         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
7259       qtdemux->moof_offset = offset;
7260       goto samples_failed;
7261     }
7262     qtdemux->moof_offset = 0;
7263     /* movie duration more reliable in this case (e.g. mehd) */
7264     if (qtdemux->segment.duration &&
7265         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
7266       stream->duration = gst_util_uint64_scale (qtdemux->segment.duration,
7267           stream->timescale, GST_SECOND);
7268     /* need defaults for fragments */
7269     qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
7270   }
7271
7272   /* configure segments */
7273   if (!qtdemux_parse_segments (qtdemux, stream, trak))
7274     goto segments_failed;
7275
7276   /* add some language tag, if useful */
7277   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
7278       strcmp (stream->lang_id, "und")) {
7279     const gchar *lang_code;
7280
7281     if (!list)
7282       list = gst_tag_list_new ();
7283
7284     /* convert ISO 639-2 code to ISO 639-1 */
7285     lang_code = gst_tag_get_language_code (stream->lang_id);
7286     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
7287         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
7288   }
7289
7290   /* now we are ready to add the stream */
7291   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
7292     goto too_many_streams;
7293
7294   stream->pending_tags = list;
7295   qtdemux->streams[qtdemux->n_streams] = stream;
7296   qtdemux->n_streams++;
7297   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
7298
7299   return TRUE;
7300
7301 /* ERRORS */
7302 corrupt_file:
7303   {
7304     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7305         (_("This file is corrupt and cannot be played.")), (NULL));
7306     g_free (stream);
7307     return FALSE;
7308   }
7309 error_encrypted:
7310   {
7311     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
7312     g_free (stream);
7313     return FALSE;
7314   }
7315 samples_failed:
7316 segments_failed:
7317   {
7318     /* we posted an error already */
7319     /* free stbl sub-atoms */
7320     gst_qtdemux_stbl_free (stream);
7321     g_free (stream);
7322     return FALSE;
7323   }
7324 unknown_stream:
7325   {
7326     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
7327         GST_FOURCC_ARGS (stream->subtype));
7328     g_free (stream);
7329     return TRUE;
7330   }
7331 too_many_streams:
7332   {
7333     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
7334         (_("This file contains too many streams. Only playing first %d"),
7335             GST_QTDEMUX_MAX_STREAMS), (NULL));
7336     return TRUE;
7337   }
7338 }
7339
7340 static GstFlowReturn
7341 qtdemux_expose_streams (GstQTDemux * qtdemux)
7342 {
7343   gint i;
7344   GstFlowReturn ret = GST_FLOW_OK;
7345
7346   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
7347
7348   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
7349     QtDemuxStream *stream = qtdemux->streams[i];
7350     guint32 sample_num = 0;
7351     guint samples = 20;
7352     GArray *durations;
7353     GstTagList *list;
7354
7355     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
7356         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
7357
7358     if (qtdemux->fragmented) {
7359       /* need all moov samples first */
7360       GST_OBJECT_LOCK (qtdemux);
7361       while (stream->n_samples == 0)
7362         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
7363           break;
7364       GST_OBJECT_UNLOCK (qtdemux);
7365     } else {
7366       /* discard any stray moof */
7367       qtdemux->moof_offset = 0;
7368     }
7369
7370     /* prepare braking */
7371     if (ret != GST_FLOW_ERROR)
7372       ret = GST_FLOW_OK;
7373
7374     /* in pull mode, we should have parsed some sample info by now;
7375      * and quite some code will not handle no samples.
7376      * in push mode, we'll just have to deal with it */
7377     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
7378       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
7379       gst_qtdemux_stream_free (qtdemux, stream);
7380       memmove (&(qtdemux->streams[i]), &(qtdemux->streams[i + 1]),
7381           sizeof (QtDemuxStream *) * (GST_QTDEMUX_MAX_STREAMS - i - 1));
7382       qtdemux->streams[GST_QTDEMUX_MAX_STREAMS - 1] = NULL;
7383       qtdemux->n_streams--;
7384       i--;
7385       continue;
7386     }
7387
7388     /* parse number of initial sample to set frame rate cap */
7389     while (sample_num < stream->n_samples && sample_num < samples) {
7390       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
7391         break;
7392       ++sample_num;
7393     }
7394     /* collect and sort durations */
7395     samples = MIN (stream->stbl_index + 1, samples);
7396     GST_DEBUG_OBJECT (qtdemux, "%d samples for framerate", samples);
7397     if (samples) {
7398       durations = g_array_sized_new (FALSE, FALSE, sizeof (guint32), samples);
7399       sample_num = 0;
7400       while (sample_num < samples) {
7401         g_array_append_val (durations, stream->samples[sample_num].duration);
7402         sample_num++;
7403       }
7404       g_array_sort (durations, less_than);
7405       stream->min_duration = g_array_index (durations, guint32, samples / 2);
7406       g_array_free (durations, TRUE);
7407     }
7408
7409     /* now we have all info and can expose */
7410     list = stream->pending_tags;
7411     stream->pending_tags = NULL;
7412     gst_qtdemux_add_stream (qtdemux, stream, list);
7413   }
7414
7415   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
7416
7417   /* check if we should post a redirect in case there is a single trak
7418    * and it is a redirecting trak */
7419   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
7420     GstMessage *m;
7421
7422     qtdemux_post_global_tags (qtdemux);
7423
7424     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
7425         "an external content");
7426     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
7427         gst_structure_new ("redirect",
7428             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
7429             NULL));
7430     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
7431     qtdemux->posted_redirect = TRUE;
7432   }
7433
7434   return ret;
7435 }
7436
7437 /* check if major or compatible brand is 3GP */
7438 static inline gboolean
7439 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
7440 {
7441   if (major) {
7442     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
7443         GST_MAKE_FOURCC ('3', 'g', 0, 0));
7444   } else if (qtdemux->comp_brands != NULL) {
7445     guint8 *data = GST_BUFFER_DATA (qtdemux->comp_brands);
7446     guint size = GST_BUFFER_SIZE (qtdemux->comp_brands);
7447     gboolean res = FALSE;
7448
7449     while (size >= 4) {
7450       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
7451           GST_MAKE_FOURCC ('3', 'g', 0, 0));
7452       data += 4;
7453       size -= 4;
7454     }
7455     return res;
7456   } else {
7457     return FALSE;
7458   }
7459 }
7460
7461 /* check if tag is a spec'ed 3GP tag keyword storing a string */
7462 static inline gboolean
7463 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
7464 {
7465   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
7466       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
7467       || fourcc == FOURCC_albm;
7468 }
7469
7470 static void
7471 qtdemux_tag_add_location (GstQTDemux * qtdemux, const char *tag,
7472     const char *dummy, GNode * node)
7473 {
7474   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
7475   int offset;
7476   char *name;
7477   gchar *data;
7478   gdouble longitude, latitude, altitude;
7479   gint len;
7480
7481   len = QT_UINT32 (node->data);
7482   if (len <= 14)
7483     goto short_read;
7484
7485   data = node->data;
7486   offset = 14;
7487
7488   /* TODO: language code skipped */
7489
7490   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
7491
7492   if (!name) {
7493     /* do not alarm in trivial case, but bail out otherwise */
7494     if (*(data + offset) != 0) {
7495       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
7496           "giving up", tag);
7497     }
7498   } else {
7499     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
7500         GST_TAG_GEO_LOCATION_NAME, name, NULL);
7501     offset += strlen (name);
7502     g_free (name);
7503   }
7504
7505   if (len < offset + 2 + 4 + 4 + 4)
7506     goto short_read;
7507
7508   /* +1 +1 = skip null-terminator and location role byte */
7509   offset += 1 + 1;
7510   /* table in spec says unsigned, semantics say negative has meaning ... */
7511   longitude = QT_SFP32 (data + offset);
7512
7513   offset += 4;
7514   latitude = QT_SFP32 (data + offset);
7515
7516   offset += 4;
7517   altitude = QT_SFP32 (data + offset);
7518
7519   /* one invalid means all are invalid */
7520   if (longitude >= -180.0 && longitude <= 180.0 &&
7521       latitude >= -90.0 && latitude <= 90.0) {
7522     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
7523         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
7524         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
7525         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
7526   }
7527
7528   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
7529
7530   return;
7531
7532   /* ERRORS */
7533 short_read:
7534   {
7535     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
7536     return;
7537   }
7538 }
7539
7540
7541 static void
7542 qtdemux_tag_add_year (GstQTDemux * qtdemux, const char *tag, const char *dummy,
7543     GNode * node)
7544 {
7545   guint16 y;
7546   GDate *date;
7547   gint len;
7548
7549   len = QT_UINT32 (node->data);
7550   if (len < 14)
7551     return;
7552
7553   y = QT_UINT16 ((guint8 *) node->data + 12);
7554   if (y == 0) {
7555     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
7556     return;
7557   }
7558   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
7559
7560   date = g_date_new_dmy (1, 1, y);
7561   gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag, date, NULL);
7562   g_date_free (date);
7563 }
7564
7565 static void
7566 qtdemux_tag_add_classification (GstQTDemux * qtdemux, const char *tag,
7567     const char *dummy, GNode * node)
7568 {
7569   int offset;
7570   char *tag_str = NULL;
7571   guint8 *entity;
7572   guint16 table;
7573   gint len;
7574
7575   len = QT_UINT32 (node->data);
7576   if (len <= 20)
7577     goto short_read;
7578
7579   offset = 12;
7580   entity = (guint8 *) node->data + offset;
7581   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
7582     GST_DEBUG_OBJECT (qtdemux,
7583         "classification info: %c%c%c%c invalid classification entity",
7584         entity[0], entity[1], entity[2], entity[3]);
7585     return;
7586   }
7587
7588   offset += 4;
7589   table = QT_UINT16 ((guint8 *) node->data + offset);
7590
7591   /* Language code skipped */
7592
7593   offset += 4;
7594
7595   /* Tag format: "XXXX://Y[YYYY]/classification info string"
7596    * XXXX: classification entity, fixed length 4 chars.
7597    * Y[YYYY]: classification table, max 5 chars.
7598    */
7599   tag_str = g_strdup_printf ("----://%u/%s",
7600       table, (char *) node->data + offset);
7601
7602   /* memcpy To be sure we're preserving byte order */
7603   memcpy (tag_str, entity, 4);
7604   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
7605
7606   gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_APPEND, tag,
7607       tag_str, NULL);
7608
7609   g_free (tag_str);
7610
7611   return;
7612
7613   /* ERRORS */
7614 short_read:
7615   {
7616     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
7617     return;
7618   }
7619 }
7620
7621 static gboolean
7622 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, const char *tag,
7623     const char *dummy, GNode * node)
7624 {
7625   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
7626   GNode *data;
7627   char *s;
7628   int len;
7629   guint32 type;
7630   int offset;
7631   gboolean ret = TRUE;
7632
7633   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
7634   if (data) {
7635     len = QT_UINT32 (data->data);
7636     type = QT_UINT32 ((guint8 *) data->data + 8);
7637     if (type == 0x00000001 && len > 16) {
7638       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
7639           env_vars);
7640       if (s) {
7641         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
7642         gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag, s,
7643             NULL);
7644         g_free (s);
7645       } else {
7646         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
7647       }
7648     }
7649   } else {
7650     len = QT_UINT32 (node->data);
7651     type = QT_UINT32 ((guint8 *) node->data + 4);
7652     if ((type >> 24) == 0xa9) {
7653       /* Type starts with the (C) symbol, so the next 32 bits are
7654        * the language code, which we ignore */
7655       offset = 12;
7656       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
7657     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
7658             QT_FOURCC ((guint8 *) node->data + 4))) {
7659       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
7660
7661       /* we go for 3GP style encoding if major brands claims so,
7662        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
7663       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
7664           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
7665               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
7666         offset = 14;
7667         /* 16-bit Language code is ignored here as well */
7668         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
7669       } else {
7670         goto normal;
7671       }
7672     } else {
7673     normal:
7674       offset = 8;
7675       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
7676       ret = FALSE;              /* may have to fallback */
7677     }
7678     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
7679         len - offset, env_vars);
7680     if (s) {
7681       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
7682       gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag, s, NULL);
7683       g_free (s);
7684       ret = TRUE;
7685     } else {
7686       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
7687     }
7688   }
7689   return ret;
7690 }
7691
7692 static void
7693 qtdemux_tag_add_str (GstQTDemux * qtdemux, const char *tag,
7694     const char *dummy, GNode * node)
7695 {
7696   qtdemux_tag_add_str_full (qtdemux, tag, dummy, node);
7697 }
7698
7699 static void
7700 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, const char *tag,
7701     const char *dummy, GNode * node)
7702 {
7703   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
7704   guint8 *data;
7705   char *s, *t, *k = NULL;
7706   int len;
7707   int offset;
7708   int count;
7709
7710   /* first try normal string tag if major brand not 3GP */
7711   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
7712     if (!qtdemux_tag_add_str_full (qtdemux, tag, dummy, node)) {
7713       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
7714        * let's try it 3gpp way after minor safety check */
7715       data = node->data;
7716       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
7717         return;
7718     } else
7719       return;
7720   }
7721
7722   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
7723
7724   data = node->data;
7725
7726   len = QT_UINT32 (data);
7727   if (len < 15)
7728     goto short_read;
7729
7730   count = QT_UINT8 (data + 14);
7731   offset = 15;
7732   for (; count; count--) {
7733     gint slen;
7734
7735     if (offset + 1 > len)
7736       goto short_read;
7737     slen = QT_UINT8 (data + offset);
7738     offset += 1;
7739     if (offset + slen > len)
7740       goto short_read;
7741     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
7742         slen, env_vars);
7743     if (s) {
7744       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
7745       if (k) {
7746         t = g_strjoin (",", k, s, NULL);
7747         g_free (s);
7748         g_free (k);
7749         k = t;
7750       } else {
7751         k = s;
7752       }
7753     } else {
7754       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
7755     }
7756     offset += slen;
7757   }
7758
7759 done:
7760   if (k) {
7761     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
7762     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag, k, NULL);
7763   }
7764   g_free (k);
7765
7766   return;
7767
7768   /* ERRORS */
7769 short_read:
7770   {
7771     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
7772     goto done;
7773   }
7774 }
7775
7776 static void
7777 qtdemux_tag_add_num (GstQTDemux * qtdemux, const char *tag1,
7778     const char *tag2, GNode * node)
7779 {
7780   GNode *data;
7781   int len;
7782   int type;
7783   int n1, n2;
7784
7785   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
7786   if (data) {
7787     len = QT_UINT32 (data->data);
7788     type = QT_UINT32 ((guint8 *) data->data + 8);
7789     if (type == 0x00000000 && len >= 22) {
7790       n1 = QT_UINT16 ((guint8 *) data->data + 18);
7791       n2 = QT_UINT16 ((guint8 *) data->data + 20);
7792       if (n1 > 0) {
7793         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
7794         gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
7795             tag1, n1, NULL);
7796       }
7797       if (n2 > 0) {
7798         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
7799         gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
7800             tag2, n2, NULL);
7801       }
7802     }
7803   }
7804 }
7805
7806 static void
7807 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, const char *tag1, const char *dummy,
7808     GNode * node)
7809 {
7810   GNode *data;
7811   int len;
7812   int type;
7813   int n1;
7814
7815   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
7816   if (data) {
7817     len = QT_UINT32 (data->data);
7818     type = QT_UINT32 ((guint8 *) data->data + 8);
7819     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
7820     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
7821     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
7822       n1 = QT_UINT16 ((guint8 *) data->data + 16);
7823       if (n1) {
7824         /* do not add bpm=0 */
7825         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
7826         gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
7827             tag1, (gdouble) n1, NULL);
7828       }
7829     }
7830   }
7831 }
7832
7833 static void
7834 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, const char *tag1,
7835     const char *dummy, GNode * node)
7836 {
7837   GNode *data;
7838   int len;
7839   int type;
7840   guint32 num;
7841
7842   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
7843   if (data) {
7844     len = QT_UINT32 (data->data);
7845     type = QT_UINT32 ((guint8 *) data->data + 8);
7846     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
7847     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
7848     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
7849       num = QT_UINT32 ((guint8 *) data->data + 16);
7850       if (num) {
7851         /* do not add num=0 */
7852         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
7853         gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
7854             tag1, num, NULL);
7855       }
7856     }
7857   }
7858 }
7859
7860 static void
7861 qtdemux_tag_add_covr (GstQTDemux * qtdemux, const char *tag1, const char *dummy,
7862     GNode * node)
7863 {
7864   GNode *data;
7865   int len;
7866   int type;
7867   GstBuffer *buf;
7868
7869   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
7870   if (data) {
7871     len = QT_UINT32 (data->data);
7872     type = QT_UINT32 ((guint8 *) data->data + 8);
7873     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
7874     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
7875       if ((buf = gst_tag_image_data_to_image_buffer ((guint8 *) data->data + 16,
7876                   len - 16, GST_TAG_IMAGE_TYPE_NONE))) {
7877         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
7878         gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
7879             tag1, buf, NULL);
7880         gst_buffer_unref (buf);
7881       }
7882     }
7883   }
7884 }
7885
7886 static void
7887 qtdemux_tag_add_date (GstQTDemux * qtdemux, const char *tag, const char *dummy,
7888     GNode * node)
7889 {
7890   GNode *data;
7891   char *s;
7892   int len;
7893   int type;
7894
7895   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
7896   if (data) {
7897     len = QT_UINT32 (data->data);
7898     type = QT_UINT32 ((guint8 *) data->data + 8);
7899     if (type == 0x00000001 && len > 16) {
7900       guint y, m = 1, d = 1;
7901       gint ret;
7902
7903       s = g_strndup ((char *) data->data + 16, len - 16);
7904       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
7905       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
7906       if (ret >= 1 && y > 1500 && y < 3000) {
7907         GDate *date;
7908
7909         date = g_date_new_dmy (d, m, y);
7910         gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag,
7911             date, NULL);
7912         g_date_free (date);
7913       } else {
7914         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
7915       }
7916       g_free (s);
7917     }
7918   }
7919 }
7920
7921 static void
7922 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, const char *tag, const char *dummy,
7923     GNode * node)
7924 {
7925   GNode *data;
7926
7927   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
7928
7929   /* re-route to normal string tag if major brand says so
7930    * or no data atom and compatible brand suggests so */
7931   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
7932       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
7933     qtdemux_tag_add_str (qtdemux, tag, dummy, node);
7934     return;
7935   }
7936
7937   if (data) {
7938     guint len, type, n;
7939
7940     len = QT_UINT32 (data->data);
7941     type = QT_UINT32 ((guint8 *) data->data + 8);
7942     if (type == 0x00000000 && len >= 18) {
7943       n = QT_UINT16 ((guint8 *) data->data + 16);
7944       if (n > 0) {
7945         const gchar *genre;
7946
7947         genre = gst_tag_id3_genre_get (n - 1);
7948         if (genre != NULL) {
7949           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
7950           gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
7951               tag, genre, NULL);
7952         }
7953       }
7954     }
7955   }
7956 }
7957
7958 static void
7959 qtdemux_add_double_tag_from_str (GstQTDemux * demux, const gchar * tag,
7960     guint8 * data, guint32 datasize)
7961 {
7962   gdouble value;
7963   gchar *datacopy;
7964
7965   /* make a copy to have \0 at the end */
7966   datacopy = g_strndup ((gchar *) data, datasize);
7967
7968   /* convert the str to double */
7969   if (sscanf (datacopy, "%lf", &value) == 1) {
7970     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
7971     gst_tag_list_add (demux->tag_list, GST_TAG_MERGE_REPLACE, tag, value, NULL);
7972   } else {
7973     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
7974         datacopy);
7975   }
7976   g_free (datacopy);
7977 }
7978
7979
7980 static void
7981 qtdemux_tag_add_revdns (GstQTDemux * demux, const char *tag,
7982     const char *tag_bis, GNode * node)
7983 {
7984   GNode *mean;
7985   GNode *name;
7986   GNode *data;
7987   guint32 meansize;
7988   guint32 namesize;
7989   guint32 datatype;
7990   guint32 datasize;
7991   const gchar *meanstr;
7992   const gchar *namestr;
7993
7994   /* checking the whole ---- atom size for consistency */
7995   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
7996     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
7997     return;
7998   }
7999
8000   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
8001   if (!mean) {
8002     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
8003     return;
8004   }
8005
8006   meansize = QT_UINT32 (mean->data);
8007   if (meansize <= 12) {
8008     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
8009     return;
8010   }
8011   meanstr = ((gchar *) mean->data) + 12;
8012
8013   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
8014   if (!name) {
8015     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
8016     return;
8017   }
8018
8019   namesize = QT_UINT32 (name->data);
8020   if (namesize <= 12) {
8021     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
8022     return;
8023   }
8024   namestr = ((gchar *) name->data) + 12;
8025
8026   /*
8027    * Data atom is:
8028    * uint32 - size
8029    * uint32 - name
8030    * uint8  - version
8031    * uint24 - data type
8032    * uint32 - all 0
8033    * rest   - the data
8034    */
8035   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
8036   if (!data) {
8037     GST_WARNING_OBJECT (demux, "No data atom in this tag");
8038     return;
8039   }
8040   datasize = QT_UINT32 (data->data);
8041   if (datasize <= 16) {
8042     GST_WARNING_OBJECT (demux, "Data atom too small");
8043     return;
8044   }
8045   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
8046
8047   if (strncmp (meanstr, "com.apple.iTunes", meansize - 12) == 0) {
8048     static const struct
8049     {
8050       const gchar name[28];
8051       const gchar tag[28];
8052     } tags[] = {
8053       {
8054       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
8055       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
8056       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
8057       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
8058       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
8059       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
8060       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
8061       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
8062     };
8063     int i;
8064
8065     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
8066       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize - 12)) {
8067         switch (gst_tag_get_type (tags[i].tag)) {
8068           case G_TYPE_DOUBLE:
8069             qtdemux_add_double_tag_from_str (demux, tags[i].tag,
8070                 ((guint8 *) data->data) + 16, datasize - 16);
8071             break;
8072           case G_TYPE_STRING:
8073             qtdemux_tag_add_str (demux, tags[i].tag, NULL, node);
8074             break;
8075           default:
8076             /* not reached */
8077             break;
8078         }
8079         break;
8080       }
8081     }
8082     if (i == G_N_ELEMENTS (tags))
8083       goto unknown_tag;
8084   } else {
8085     goto unknown_tag;
8086   }
8087
8088   return;
8089
8090 /* errors */
8091 unknown_tag:
8092   {
8093     gchar *namestr_dbg;
8094     gchar *meanstr_dbg;
8095
8096     meanstr_dbg = g_strndup (meanstr, meansize - 12);
8097     namestr_dbg = g_strndup (namestr, namesize - 12);
8098
8099     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
8100         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
8101
8102     g_free (namestr_dbg);
8103     g_free (meanstr_dbg);
8104     return;
8105   }
8106 }
8107
8108 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux,
8109     const char *tag, const char *tag_bis, GNode * node);
8110
8111 /* unmapped tags
8112 FOURCC_pcst -> if media is a podcast -> bool
8113 FOURCC_cpil -> if media is part of a compilation -> bool
8114 FOURCC_pgap -> if media is part of a gapless context -> bool
8115 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
8116 */
8117
8118 static const struct
8119 {
8120   guint32 fourcc;
8121   const gchar *gst_tag;
8122   const gchar *gst_tag_bis;
8123   const GstQTDemuxAddTagFunc func;
8124 } add_funcs[] = {
8125   {
8126   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
8127   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
8128   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
8129   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
8130   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
8131   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
8132   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
8133   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
8134   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
8135   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
8136   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
8137   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
8138   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
8139   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
8140   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
8141   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
8142   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
8143   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
8144   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
8145   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
8146   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
8147   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
8148   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
8149         qtdemux_tag_add_num}, {
8150   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
8151         qtdemux_tag_add_num}, {
8152   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
8153   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
8154   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
8155   FOURCC_covr, GST_TAG_PREVIEW_IMAGE, NULL, qtdemux_tag_add_covr}, {
8156   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
8157   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
8158   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
8159   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
8160   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
8161   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
8162   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
8163   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
8164   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
8165   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
8166   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
8167   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
8168   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
8169   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
8170         qtdemux_tag_add_classification}, {
8171
8172     /* This is a special case, some tags are stored in this
8173      * 'reverse dns naming', according to:
8174      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
8175      * bug #614471
8176      */
8177   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}
8178 };
8179
8180 static void
8181 qtdemux_tag_add_blob (GNode * node, GstQTDemux * demux)
8182 {
8183   gint len;
8184   guint8 *data;
8185   GstBuffer *buf;
8186   gchar *media_type;
8187   const gchar *style;
8188   GstCaps *caps;
8189   guint i;
8190   guint8 ndata[4];
8191
8192   data = node->data;
8193   len = QT_UINT32 (data);
8194   buf = gst_buffer_new_and_alloc (len);
8195   memcpy (GST_BUFFER_DATA (buf), data, len);
8196
8197   /* heuristic to determine style of tag */
8198   if (QT_FOURCC (data + 4) == FOURCC_____ ||
8199       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
8200     style = "itunes";
8201   else if (demux->major_brand == FOURCC_qt__)
8202     style = "quicktime";
8203   /* fall back to assuming iso/3gp tag style */
8204   else
8205     style = "iso";
8206
8207   /* santize the name for the caps. */
8208   for (i = 0; i < 4; i++) {
8209     guint8 d = data[4 + i];
8210     if (g_ascii_isalnum (d))
8211       ndata[i] = g_ascii_tolower (d);
8212     else
8213       ndata[i] = '_';
8214   }
8215
8216   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
8217       ndata[0], ndata[1], ndata[2], ndata[3]);
8218   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
8219
8220   caps = gst_caps_new_simple (media_type, "style", G_TYPE_STRING, style, NULL);
8221   gst_buffer_set_caps (buf, caps);
8222   gst_caps_unref (caps);
8223   g_free (media_type);
8224
8225   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, caps %" GST_PTR_FORMAT,
8226       GST_BUFFER_SIZE (buf), caps);
8227
8228   gst_tag_list_add (demux->tag_list, GST_TAG_MERGE_APPEND,
8229       GST_QT_DEMUX_PRIVATE_TAG, buf, NULL);
8230   gst_buffer_unref (buf);
8231 }
8232
8233 static void
8234 qtdemux_parse_udta (GstQTDemux * qtdemux, GNode * udta)
8235 {
8236   GNode *meta;
8237   GNode *ilst;
8238   GNode *xmp_;
8239   GNode *node;
8240   gint i;
8241
8242   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
8243   if (meta != NULL) {
8244     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
8245     if (ilst == NULL) {
8246       GST_LOG_OBJECT (qtdemux, "no ilst");
8247       return;
8248     }
8249   } else {
8250     ilst = udta;
8251     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
8252   }
8253
8254   GST_DEBUG_OBJECT (qtdemux, "new tag list");
8255   if (!qtdemux->tag_list)
8256     qtdemux->tag_list = gst_tag_list_new ();
8257
8258   i = 0;
8259   while (i < G_N_ELEMENTS (add_funcs)) {
8260     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
8261     if (node) {
8262       gint len;
8263
8264       len = QT_UINT32 (node->data);
8265       if (len < 12) {
8266         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
8267             GST_FOURCC_ARGS (add_funcs[i].fourcc));
8268       } else {
8269         add_funcs[i].func (qtdemux, add_funcs[i].gst_tag,
8270             add_funcs[i].gst_tag_bis, node);
8271       }
8272       g_node_destroy (node);
8273     } else {
8274       i++;
8275     }
8276   }
8277
8278   /* parsed nodes have been removed, pass along remainder as blob */
8279   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
8280       (GNodeForeachFunc) qtdemux_tag_add_blob, qtdemux);
8281
8282   /* parse up XMP_ node if existing */
8283   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
8284   if (xmp_ != NULL) {
8285     GstBuffer *buf;
8286     GstTagList *taglist;
8287
8288     buf = gst_buffer_new ();
8289     GST_BUFFER_DATA (buf) = ((guint8 *) xmp_->data) + 8;
8290     GST_BUFFER_SIZE (buf) = QT_UINT32 ((guint8 *) xmp_->data) - 8;
8291
8292     taglist = gst_tag_list_from_xmp_buffer (buf);
8293     gst_buffer_unref (buf);
8294
8295     qtdemux_handle_xmp_taglist (qtdemux, taglist);
8296   } else {
8297     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
8298   }
8299
8300 }
8301
8302 typedef struct
8303 {
8304   GstStructure *structure;      /* helper for sort function */
8305   gchar *location;
8306   guint min_req_bitrate;
8307   guint min_req_qt_version;
8308 } GstQtReference;
8309
8310 static gint
8311 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
8312 {
8313   GstQtReference *ref_a = (GstQtReference *) a;
8314   GstQtReference *ref_b = (GstQtReference *) b;
8315
8316   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
8317     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
8318
8319   /* known bitrates go before unknown; higher bitrates go first */
8320   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
8321 }
8322
8323 /* sort the redirects and post a message for the application.
8324  */
8325 static void
8326 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
8327 {
8328   GstQtReference *best;
8329   GstStructure *s;
8330   GstMessage *msg;
8331   GValue list_val = { 0, };
8332   GList *l;
8333
8334   g_assert (references != NULL);
8335
8336   references = g_list_sort (references, qtdemux_redirects_sort_func);
8337
8338   best = (GstQtReference *) references->data;
8339
8340   g_value_init (&list_val, GST_TYPE_LIST);
8341
8342   for (l = references; l != NULL; l = l->next) {
8343     GstQtReference *ref = (GstQtReference *) l->data;
8344     GValue struct_val = { 0, };
8345
8346     ref->structure = gst_structure_new ("redirect",
8347         "new-location", G_TYPE_STRING, ref->location, NULL);
8348
8349     if (ref->min_req_bitrate > 0) {
8350       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
8351           ref->min_req_bitrate, NULL);
8352     }
8353
8354     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
8355     g_value_set_boxed (&struct_val, ref->structure);
8356     gst_value_list_append_value (&list_val, &struct_val);
8357     g_value_unset (&struct_val);
8358     /* don't free anything here yet, since we need best->structure below */
8359   }
8360
8361   g_assert (best != NULL);
8362   s = gst_structure_copy (best->structure);
8363
8364   if (g_list_length (references) > 1) {
8365     gst_structure_set_value (s, "locations", &list_val);
8366   }
8367
8368   g_value_unset (&list_val);
8369
8370   for (l = references; l != NULL; l = l->next) {
8371     GstQtReference *ref = (GstQtReference *) l->data;
8372
8373     gst_structure_free (ref->structure);
8374     g_free (ref->location);
8375     g_free (ref);
8376   }
8377   g_list_free (references);
8378
8379   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
8380   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
8381   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
8382   qtdemux->posted_redirect = TRUE;
8383 }
8384
8385 /* look for redirect nodes, collect all redirect information and
8386  * process it.
8387  */
8388 static gboolean
8389 qtdemux_parse_redirects (GstQTDemux * qtdemux)
8390 {
8391   GNode *rmra, *rmda, *rdrf;
8392
8393   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
8394   if (rmra) {
8395     GList *redirects = NULL;
8396
8397     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
8398     while (rmda) {
8399       GstQtReference ref = { NULL, NULL, 0, 0 };
8400       GNode *rmdr, *rmvc;
8401
8402       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
8403         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
8404         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
8405             ref.min_req_bitrate);
8406       }
8407
8408       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
8409         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
8410         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
8411
8412 #ifndef GST_DISABLE_GST_DEBUG
8413         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
8414 #endif
8415         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
8416
8417         GST_LOG_OBJECT (qtdemux,
8418             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
8419             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
8420             bitmask, check_type);
8421         if (package == FOURCC_qtim && check_type == 0) {
8422           ref.min_req_qt_version = version;
8423         }
8424       }
8425
8426       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
8427       if (rdrf) {
8428         guint32 ref_type;
8429         guint8 *ref_data;
8430
8431         ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
8432         ref_data = (guint8 *) rdrf->data + 20;
8433         if (ref_type == FOURCC_alis) {
8434           guint record_len, record_version, fn_len;
8435
8436           /* MacOSX alias record, google for alias-layout.txt */
8437           record_len = QT_UINT16 (ref_data + 4);
8438           record_version = QT_UINT16 (ref_data + 4 + 2);
8439           fn_len = QT_UINT8 (ref_data + 50);
8440           if (record_len > 50 && record_version == 2 && fn_len > 0) {
8441             ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
8442           }
8443         } else if (ref_type == FOURCC_url_) {
8444           ref.location = g_strdup ((gchar *) ref_data);
8445         } else {
8446           GST_DEBUG_OBJECT (qtdemux,
8447               "unknown rdrf reference type %" GST_FOURCC_FORMAT,
8448               GST_FOURCC_ARGS (ref_type));
8449         }
8450         if (ref.location != NULL) {
8451           GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
8452           redirects = g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
8453         } else {
8454           GST_WARNING_OBJECT (qtdemux,
8455               "Failed to extract redirect location from rdrf atom");
8456         }
8457       }
8458
8459       /* look for others */
8460       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
8461     }
8462
8463     if (redirects != NULL) {
8464       qtdemux_process_redirects (qtdemux, redirects);
8465     }
8466   }
8467   return TRUE;
8468 }
8469
8470 static GstTagList *
8471 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
8472 {
8473   const gchar *fmt;
8474
8475   if (tags == NULL)
8476     tags = gst_tag_list_new ();
8477
8478   if (qtdemux->major_brand == FOURCC_mjp2)
8479     fmt = "Motion JPEG 2000";
8480   else if ((qtdemux->major_brand & 0xffff) == GST_MAKE_FOURCC ('3', 'g', 0, 0))
8481     fmt = "3GP";
8482   else if (qtdemux->major_brand == FOURCC_qt__)
8483     fmt = "Quicktime";
8484   else if (qtdemux->fragmented)
8485     fmt = "ISO fMP4";
8486   else
8487     fmt = "ISO MP4/M4A";
8488
8489   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
8490       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
8491
8492   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
8493       fmt, NULL);
8494
8495   return tags;
8496 }
8497
8498 /* we have read th complete moov node now.
8499  * This function parses all of the relevant info, creates the traks and
8500  * prepares all data structures for playback
8501  */
8502 static gboolean
8503 qtdemux_parse_tree (GstQTDemux * qtdemux)
8504 {
8505   GNode *mvhd;
8506   GNode *trak;
8507   GNode *udta;
8508   GNode *mvex;
8509   gint64 duration;
8510   guint64 creation_time;
8511   GstDateTime *datetime = NULL;
8512   gint version;
8513
8514   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
8515   if (mvhd == NULL) {
8516     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
8517     return qtdemux_parse_redirects (qtdemux);
8518   }
8519
8520   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
8521   if (version == 1) {
8522     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
8523     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
8524     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
8525   } else if (version == 0) {
8526     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
8527     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
8528     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
8529   } else {
8530     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
8531     return FALSE;
8532   }
8533
8534   /* Moving qt creation time (secs since 1904) to unix time */
8535   if (creation_time != 0) {
8536     if (creation_time > QTDEMUX_SECONDS_FROM_1904_TO_1970) {
8537       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
8538       datetime = gst_date_time_new_from_unix_epoch_local_time (creation_time);
8539     } else {
8540       GST_WARNING_OBJECT (qtdemux, "Can't handle datetimes before 1970 yet, "
8541           "please file a bug at http://bugzilla.gnome.org");
8542     }
8543   }
8544   if (datetime) {
8545     if (!qtdemux->tag_list)
8546       qtdemux->tag_list = gst_tag_list_new ();
8547
8548     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
8549     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
8550         datetime, NULL);
8551     gst_date_time_unref (datetime);
8552   }
8553
8554   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
8555   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
8556
8557   /* check for fragmented file and get some (default) data */
8558   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
8559   if (mvex) {
8560     GNode *mehd;
8561     GstByteReader mehd_data;
8562
8563     /* let track parsing or anyone know weird stuff might happen ... */
8564     qtdemux->fragmented = TRUE;
8565
8566     /* compensate for total duration */
8567     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
8568     if (mehd)
8569       qtdemux_parse_mehd (qtdemux, &mehd_data);
8570   }
8571
8572   /* set duration in the segment info */
8573   gst_qtdemux_get_duration (qtdemux, &duration);
8574   if (duration)
8575     gst_segment_set_duration (&qtdemux->segment, GST_FORMAT_TIME, duration);
8576
8577   /* parse all traks */
8578   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
8579   while (trak) {
8580     qtdemux_parse_trak (qtdemux, trak);
8581     /* iterate all siblings */
8582     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
8583   }
8584
8585   /* find tags */
8586   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
8587   if (udta) {
8588     qtdemux_parse_udta (qtdemux, udta);
8589   } else {
8590     GST_LOG_OBJECT (qtdemux, "No udta node found.");
8591   }
8592
8593   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
8594
8595   return TRUE;
8596 }
8597
8598 /* taken from ffmpeg */
8599 static unsigned int
8600 get_size (guint8 * ptr, guint8 ** end)
8601 {
8602   int count = 4;
8603   int len = 0;
8604
8605   while (count--) {
8606     int c = *ptr;
8607
8608     ptr++;
8609     len = (len << 7) | (c & 0x7f);
8610     if (!(c & 0x80))
8611       break;
8612   }
8613   if (end)
8614     *end = ptr;
8615   return len;
8616 }
8617
8618 /* this can change the codec originally present in @list */
8619 static void
8620 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
8621     GNode * esds, GstTagList * list)
8622 {
8623   int len = QT_UINT32 (esds->data);
8624   guint8 *ptr = esds->data;
8625   guint8 *end = ptr + len;
8626   int tag;
8627   guint8 *data_ptr = NULL;
8628   int data_len = 0;
8629   guint8 object_type_id = 0;
8630   const char *codec_name = NULL;
8631   GstCaps *caps = NULL;
8632
8633   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
8634   ptr += 8;
8635   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
8636   ptr += 4;
8637   while (ptr < end) {
8638     tag = QT_UINT8 (ptr);
8639     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
8640     ptr++;
8641     len = get_size (ptr, &ptr);
8642     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
8643
8644     switch (tag) {
8645       case 0x03:
8646         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
8647         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
8648         ptr += 3;
8649         break;
8650       case 0x04:{
8651         guint max_bitrate, avg_bitrate;
8652
8653         object_type_id = QT_UINT8 (ptr);
8654         max_bitrate = QT_UINT32 (ptr + 5);
8655         avg_bitrate = QT_UINT32 (ptr + 9);
8656         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
8657         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
8658         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
8659         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
8660         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
8661         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
8662           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
8663               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
8664         }
8665         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
8666           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
8667               avg_bitrate, NULL);
8668         }
8669         ptr += 13;
8670         break;
8671       }
8672       case 0x05:
8673         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
8674         data_ptr = ptr;
8675         data_len = len;
8676         ptr += len;
8677         break;
8678       case 0x06:
8679         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
8680         ptr += 1;
8681         break;
8682       default:
8683         GST_ERROR_OBJECT (qtdemux, "parse error");
8684         break;
8685     }
8686   }
8687
8688   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
8689    * in use, and should also be used to override some other parameters for some
8690    * codecs. */
8691   switch (object_type_id) {
8692     case 0x20:                 /* MPEG-4 */
8693       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
8694        * profile_and_level_indication */
8695       if (data_ptr != NULL && data_len >= 5 &&
8696           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
8697         gst_codec_utils_mpeg4video_caps_set_level_and_profile (stream->caps,
8698             data_ptr + 4, data_len - 4);
8699       }
8700       break;                    /* Nothing special needed here */
8701     case 0x21:                 /* H.264 */
8702       codec_name = "H.264 / AVC";
8703       caps = gst_caps_new_simple ("video/x-h264",
8704           "stream-format", G_TYPE_STRING, "avc",
8705           "alignment", G_TYPE_STRING, "au", NULL);
8706       break;
8707     case 0x40:                 /* AAC (any) */
8708     case 0x66:                 /* AAC Main */
8709     case 0x67:                 /* AAC LC */
8710     case 0x68:                 /* AAC SSR */
8711       /* Override channels and rate based on the codec_data, as it's often
8712        * wrong. */
8713       /* Only do so for basic setup without HE-AAC extension */
8714       if (data_ptr && data_len == 2) {
8715         guint channels, rateindex, rate;
8716
8717         /* FIXME: add gst_codec_utils_aac_get_{channels|sample_rate}()? */
8718         channels = (data_ptr[1] & 0x7f) >> 3;
8719         if (channels > 0 && channels < 7) {
8720           stream->n_channels = channels;
8721         } else if (channels == 7) {
8722           stream->n_channels = 8;
8723         }
8724
8725         rateindex = ((data_ptr[0] & 0x7) << 1) | ((data_ptr[1] & 0x80) >> 7);
8726         rate = gst_codec_utils_aac_get_sample_rate_from_index (rateindex);
8727         if (rate > 0)
8728           stream->rate = rate;
8729       }
8730
8731       /* Set level and profile if possible */
8732       if (data_ptr != NULL && data_len >= 2) {
8733         gst_codec_utils_aac_caps_set_level_and_profile (stream->caps,
8734             data_ptr, data_len);
8735       }
8736       break;
8737     case 0x60:                 /* MPEG-2, various profiles */
8738     case 0x61:
8739     case 0x62:
8740     case 0x63:
8741     case 0x64:
8742     case 0x65:
8743       codec_name = "MPEG-2 video";
8744
8745       gst_caps_unref (stream->caps);
8746       stream->caps = gst_caps_new_simple ("video/mpeg",
8747           "mpegversion", G_TYPE_INT, 2,
8748           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
8749       break;
8750     case 0x69:                 /* MP3 has two different values, accept either */
8751     case 0x6B:
8752       /* change to mpeg1 layer 3 audio */
8753       gst_caps_set_simple (stream->caps, "layer", G_TYPE_INT, 3,
8754           "mpegversion", G_TYPE_INT, 1, NULL);
8755       codec_name = "MPEG-1 layer 3";
8756       break;
8757     case 0x6A:                 /* MPEG-1 */
8758       codec_name = "MPEG-1 video";
8759
8760       gst_caps_unref (stream->caps);
8761       stream->caps = gst_caps_new_simple ("video/mpeg",
8762           "mpegversion", G_TYPE_INT, 1,
8763           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
8764       break;
8765     case 0x6C:                 /* MJPEG */
8766       caps = gst_caps_new_simple ("image/jpeg", NULL);
8767       codec_name = "Motion-JPEG";
8768       break;
8769     case 0x6D:                 /* PNG */
8770       caps = gst_caps_new_simple ("image/png", NULL);
8771       codec_name = "PNG still images";
8772       break;
8773     case 0x6E:                 /* JPEG2000 */
8774       codec_name = "JPEG-2000";
8775       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
8776       break;
8777     case 0xA4:                 /* Dirac */
8778       codec_name = "Dirac";
8779       caps = gst_caps_new_simple ("video/x-dirac", NULL);
8780       break;
8781     case 0xA5:                 /* AC3 */
8782       codec_name = "AC-3 audio";
8783       caps = gst_caps_new_simple ("audio/x-ac3",
8784           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
8785       break;
8786     case 0xE1:                 /* QCELP */
8787       /* QCELP, the codec_data is a riff tag (little endian) with
8788        * 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). */
8789       caps = gst_caps_new_simple ("audio/qcelp", NULL);
8790       codec_name = "QCELP";
8791       break;
8792     default:
8793       break;
8794   }
8795
8796   /* If we have a replacement caps, then change our caps for this stream */
8797   if (caps) {
8798     gst_caps_unref (stream->caps);
8799     stream->caps = caps;
8800   }
8801
8802   if (codec_name && list)
8803     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
8804         GST_TAG_AUDIO_CODEC, codec_name, NULL);
8805
8806   /* Add the codec_data attribute to caps, if we have it */
8807   if (data_ptr) {
8808     GstBuffer *buffer;
8809
8810     buffer = gst_buffer_new_and_alloc (data_len);
8811     memcpy (GST_BUFFER_DATA (buffer), data_ptr, data_len);
8812
8813     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
8814     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
8815
8816     gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
8817         buffer, NULL);
8818     gst_buffer_unref (buffer);
8819   }
8820
8821 }
8822
8823 #define _codec(name) \
8824   do { \
8825     if (codec_name) { \
8826       *codec_name = g_strdup (name); \
8827     } \
8828   } while (0)
8829
8830 static GstCaps *
8831 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
8832     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
8833 {
8834   GstCaps *caps;
8835   const GstStructure *s;
8836   const gchar *name;
8837
8838   switch (fourcc) {
8839     case GST_MAKE_FOURCC ('p', 'n', 'g', ' '):
8840       _codec ("PNG still images");
8841       caps = gst_caps_new_simple ("image/png", NULL);
8842       break;
8843     case GST_MAKE_FOURCC ('j', 'p', 'e', 'g'):
8844       _codec ("JPEG still images");
8845       caps = gst_caps_new_simple ("image/jpeg", NULL);
8846       break;
8847     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
8848     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
8849     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
8850     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
8851       _codec ("Motion-JPEG");
8852       caps = gst_caps_new_simple ("image/jpeg", NULL);
8853       break;
8854     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
8855       _codec ("Motion-JPEG format B");
8856       caps = gst_caps_new_simple ("video/x-mjpeg-b", NULL);
8857       break;
8858     case GST_MAKE_FOURCC ('m', 'j', 'p', '2'):
8859       _codec ("JPEG-2000");
8860       /* override to what it should be according to spec, avoid palette_data */
8861       stream->bits_per_sample = 24;
8862       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
8863       break;
8864     case GST_MAKE_FOURCC ('S', 'V', 'Q', '3'):
8865       _codec ("Sorensen video v.3");
8866       caps = gst_caps_new_simple ("video/x-svq",
8867           "svqversion", G_TYPE_INT, 3, NULL);
8868       break;
8869     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
8870     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
8871       _codec ("Sorensen video v.1");
8872       caps = gst_caps_new_simple ("video/x-svq",
8873           "svqversion", G_TYPE_INT, 1, NULL);
8874       break;
8875     case GST_MAKE_FOURCC ('r', 'a', 'w', ' '):
8876     {
8877       guint16 bps;
8878
8879       _codec ("Raw RGB video");
8880       bps = QT_UINT16 (stsd_data + 98);
8881       /* set common stuff */
8882       caps = gst_caps_new_simple ("video/x-raw-rgb",
8883           "endianness", G_TYPE_INT, G_BYTE_ORDER, "depth", G_TYPE_INT, bps,
8884           NULL);
8885
8886       switch (bps) {
8887         case 15:
8888           gst_caps_set_simple (caps,
8889               "bpp", G_TYPE_INT, 16,
8890               "endianness", G_TYPE_INT, G_BIG_ENDIAN,
8891               "red_mask", G_TYPE_INT, 0x7c00,
8892               "green_mask", G_TYPE_INT, 0x03e0,
8893               "blue_mask", G_TYPE_INT, 0x001f, NULL);
8894           break;
8895         case 16:
8896           gst_caps_set_simple (caps,
8897               "bpp", G_TYPE_INT, 16,
8898               "endianness", G_TYPE_INT, G_BIG_ENDIAN,
8899               "red_mask", G_TYPE_INT, 0xf800,
8900               "green_mask", G_TYPE_INT, 0x07e0,
8901               "blue_mask", G_TYPE_INT, 0x001f, NULL);
8902           break;
8903         case 24:
8904           gst_caps_set_simple (caps,
8905               "bpp", G_TYPE_INT, 24,
8906               "endianness", G_TYPE_INT, G_BIG_ENDIAN,
8907               "red_mask", G_TYPE_INT, 0xff0000,
8908               "green_mask", G_TYPE_INT, 0x00ff00,
8909               "blue_mask", G_TYPE_INT, 0x0000ff, NULL);
8910           break;
8911         case 32:
8912           gst_caps_set_simple (caps,
8913               "bpp", G_TYPE_INT, 32,
8914               "endianness", G_TYPE_INT, G_BIG_ENDIAN,
8915               "alpha_mask", G_TYPE_INT, 0xff000000,
8916               "red_mask", G_TYPE_INT, 0x00ff0000,
8917               "green_mask", G_TYPE_INT, 0x0000ff00,
8918               "blue_mask", G_TYPE_INT, 0x000000ff, NULL);
8919           break;
8920         default:
8921           /* unknown */
8922           break;
8923       }
8924       break;
8925     }
8926     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
8927       _codec ("Raw planar YUV 4:2:0");
8928       caps = gst_caps_new_simple ("video/x-raw-yuv",
8929           "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
8930           NULL);
8931       break;
8932     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
8933     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
8934       _codec ("Raw packed YUV 4:2:2");
8935       caps = gst_caps_new_simple ("video/x-raw-yuv",
8936           "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'),
8937           NULL);
8938       break;
8939     case GST_MAKE_FOURCC ('2', 'v', 'u', 'y'):
8940     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
8941       _codec ("Raw packed YUV 4:2:2");
8942       caps = gst_caps_new_simple ("video/x-raw-yuv",
8943           "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'),
8944           NULL);
8945       break;
8946     case GST_MAKE_FOURCC ('v', '2', '1', '0'):
8947       _codec ("Raw packed YUV 10-bit 4:2:2");
8948       caps = gst_caps_new_simple ("video/x-raw-yuv",
8949           "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('v', '2', '1', '0'),
8950           NULL);
8951       break;
8952     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
8953       _codec ("Raw packed RGB 10-bit 4:4:4");
8954       caps = gst_caps_new_simple ("video/x-raw-rgb",
8955           "endianness", G_TYPE_INT, G_BIG_ENDIAN, "depth", G_TYPE_INT, 30,
8956           "bpp", G_TYPE_INT, 32,
8957           "endianness", G_TYPE_INT, G_BIG_ENDIAN,
8958           "red_mask", G_TYPE_INT, 0x3ff00000,
8959           "green_mask", G_TYPE_INT, 0x000ffc00,
8960           "blue_mask", G_TYPE_INT, 0x000003ff, NULL);
8961       break;
8962     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
8963     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
8964       _codec ("MPEG-1 video");
8965       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
8966           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
8967       break;
8968     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
8969     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
8970     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
8971     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
8972     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080i60 */
8973     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
8974     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
8975     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
8976     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
8977     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
8978     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
8979     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 */
8980     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
8981     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
8982       _codec ("MPEG-2 video");
8983       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
8984           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
8985       break;
8986     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
8987       _codec ("GIF still images");
8988       caps = gst_caps_new_simple ("image/gif", NULL);
8989       break;
8990     case GST_MAKE_FOURCC ('h', '2', '6', '3'):
8991     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
8992     case GST_MAKE_FOURCC ('s', '2', '6', '3'):
8993     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
8994       _codec ("H.263");
8995       /* ffmpeg uses the height/width props, don't know why */
8996       caps = gst_caps_new_simple ("video/x-h263", NULL);
8997       break;
8998     case GST_MAKE_FOURCC ('m', 'p', '4', 'v'):
8999     case GST_MAKE_FOURCC ('M', 'P', '4', 'V'):
9000       _codec ("MPEG-4 video");
9001       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
9002           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
9003       break;
9004     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
9005     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
9006       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
9007       caps = gst_caps_new_simple ("video/x-msmpeg",
9008           "msmpegversion", G_TYPE_INT, 43, NULL);
9009       break;
9010     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
9011     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
9012       _codec ("3ivX video");
9013       caps = gst_caps_new_simple ("video/x-3ivx", NULL);
9014       break;
9015     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
9016       _codec ("DivX 3");
9017       caps = gst_caps_new_simple ("video/x-divx",
9018           "divxversion", G_TYPE_INT, 3, NULL);
9019       break;
9020     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
9021     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
9022       _codec ("DivX 4");
9023       caps = gst_caps_new_simple ("video/x-divx",
9024           "divxversion", G_TYPE_INT, 4, NULL);
9025       break;
9026     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
9027       _codec ("DivX 5");
9028       caps = gst_caps_new_simple ("video/x-divx",
9029           "divxversion", G_TYPE_INT, 5, NULL);
9030       break;
9031     case GST_MAKE_FOURCC ('X', 'V', 'I', 'D'):
9032     case GST_MAKE_FOURCC ('x', 'v', 'i', 'd'):
9033       _codec ("XVID MPEG-4");
9034       caps = gst_caps_new_simple ("video/x-xvid", NULL);
9035       break;
9036
9037     case GST_MAKE_FOURCC ('F', 'M', 'P', '4'):
9038     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
9039       caps = gst_caps_new_simple ("video/mpeg",
9040           "mpegversion", G_TYPE_INT, 4, NULL);
9041       if (codec_name)
9042         *codec_name = g_strdup ("FFmpeg MPEG-4");
9043       break;
9044
9045     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
9046       _codec ("Cinepak");
9047       caps = gst_caps_new_simple ("video/x-cinepak", NULL);
9048       break;
9049     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
9050       _codec ("Apple QuickDraw");
9051       caps = gst_caps_new_simple ("video/x-qdrw", NULL);
9052       break;
9053     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
9054       _codec ("Apple video");
9055       caps = gst_caps_new_simple ("video/x-apple-video", NULL);
9056       break;
9057     case GST_MAKE_FOURCC ('a', 'v', 'c', '1'):
9058       _codec ("H.264 / AVC");
9059       caps = gst_caps_new_simple ("video/x-h264",
9060           "stream-format", G_TYPE_STRING, "avc",
9061           "alignment", G_TYPE_STRING, "au", NULL);
9062       break;
9063     case GST_MAKE_FOURCC ('r', 'l', 'e', ' '):
9064       _codec ("Run-length encoding");
9065       caps = gst_caps_new_simple ("video/x-rle",
9066           "layout", G_TYPE_STRING, "quicktime", NULL);
9067       break;
9068     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
9069     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
9070       _codec ("Indeo Video 3");
9071       caps = gst_caps_new_simple ("video/x-indeo",
9072           "indeoversion", G_TYPE_INT, 3, NULL);
9073       break;
9074     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
9075     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
9076       _codec ("Intel Video 4");
9077       caps = gst_caps_new_simple ("video/x-indeo",
9078           "indeoversion", G_TYPE_INT, 4, NULL);
9079       break;
9080     case GST_MAKE_FOURCC ('d', 'v', 'c', 'p'):
9081     case GST_MAKE_FOURCC ('d', 'v', 'c', ' '):
9082     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
9083     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
9084     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
9085     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
9086     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
9087     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
9088       _codec ("DV Video");
9089       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
9090           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
9091       break;
9092     case GST_MAKE_FOURCC ('d', 'v', '5', 'n'): /* DVCPRO50 NTSC */
9093     case GST_MAKE_FOURCC ('d', 'v', '5', 'p'): /* DVCPRO50 PAL */
9094       _codec ("DVCPro50 Video");
9095       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
9096           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
9097       break;
9098     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
9099     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
9100       _codec ("DVCProHD Video");
9101       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
9102           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
9103       break;
9104     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
9105       _codec ("Apple Graphics (SMC)");
9106       caps = gst_caps_new_simple ("video/x-smc", NULL);
9107       break;
9108     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
9109       _codec ("VP3");
9110       caps = gst_caps_new_simple ("video/x-vp3", NULL);
9111       break;
9112     case GST_MAKE_FOURCC ('X', 'i', 'T', 'h'):
9113       _codec ("Theora");
9114       caps = gst_caps_new_simple ("video/x-theora", NULL);
9115       /* theora uses one byte of padding in the data stream because it does not
9116        * allow 0 sized packets while theora does */
9117       stream->padding = 1;
9118       break;
9119     case GST_MAKE_FOURCC ('d', 'r', 'a', 'c'):
9120       _codec ("Dirac");
9121       caps = gst_caps_new_simple ("video/x-dirac", NULL);
9122       break;
9123     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
9124       _codec ("TIFF still images");
9125       caps = gst_caps_new_simple ("image/tiff", NULL);
9126       break;
9127     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
9128       _codec ("Apple Intermediate Codec");
9129       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
9130       break;
9131     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
9132       _codec ("AVID DNxHD");
9133       caps = gst_caps_from_string ("video/x-dnxhd");
9134       break;
9135     case GST_MAKE_FOURCC ('V', 'P', '8', '0'):
9136       _codec ("On2 VP8");
9137       caps = gst_caps_from_string ("video/x-vp8");
9138     case FOURCC_ovc1:
9139       _codec ("VC-1");
9140       caps = gst_caps_new_simple ("video/x-wmv",
9141           "wmvversion", G_TYPE_INT, 3,
9142           "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('W', 'V', 'C', '1'),
9143           NULL);
9144       break;
9145     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
9146     default:
9147     {
9148       char *s;
9149
9150       s = g_strdup_printf ("video/x-gst-fourcc-%" GST_FOURCC_FORMAT,
9151           GST_FOURCC_ARGS (fourcc));
9152       caps = gst_caps_new_simple (s, NULL);
9153       break;
9154     }
9155   }
9156
9157   /* enable clipping for raw video streams */
9158   s = gst_caps_get_structure (caps, 0);
9159   name = gst_structure_get_name (s);
9160   if (g_str_has_prefix (name, "video/x-raw-")) {
9161     stream->need_clip = TRUE;
9162   }
9163   return caps;
9164 }
9165
9166 static GstCaps *
9167 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
9168     guint32 fourcc, const guint8 * data, int len, gchar ** codec_name)
9169 {
9170   GstCaps *caps;
9171   const GstStructure *s;
9172   const gchar *name;
9173   gint endian = 0;
9174
9175   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc %08x", fourcc);
9176
9177   switch (fourcc) {
9178     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
9179     case GST_MAKE_FOURCC ('r', 'a', 'w', ' '):
9180       _codec ("Raw 8-bit PCM audio");
9181       caps = gst_caps_new_simple ("audio/x-raw-int", "width", G_TYPE_INT, 8,
9182           "depth", G_TYPE_INT, 8, "signed", G_TYPE_BOOLEAN, FALSE, NULL);
9183       break;
9184     case GST_MAKE_FOURCC ('t', 'w', 'o', 's'):
9185       endian = G_BIG_ENDIAN;
9186       /* fall-through */
9187     case GST_MAKE_FOURCC ('s', 'o', 'w', 't'):
9188     {
9189       gchar *str;
9190       gint depth;
9191
9192       if (!endian)
9193         endian = G_LITTLE_ENDIAN;
9194
9195       depth = stream->bytes_per_packet * 8;
9196       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
9197       _codec (str);
9198       g_free (str);
9199       caps = gst_caps_new_simple ("audio/x-raw-int",
9200           "width", G_TYPE_INT, depth, "depth", G_TYPE_INT, depth,
9201           "endianness", G_TYPE_INT, endian,
9202           "signed", G_TYPE_BOOLEAN, TRUE, NULL);
9203       break;
9204     }
9205     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
9206       _codec ("Raw 64-bit floating-point audio");
9207       caps = gst_caps_new_simple ("audio/x-raw-float", "width", G_TYPE_INT, 64,
9208           "endianness", G_TYPE_INT, G_BIG_ENDIAN, NULL);
9209       break;
9210     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
9211       _codec ("Raw 32-bit floating-point audio");
9212       caps = gst_caps_new_simple ("audio/x-raw-float", "width", G_TYPE_INT, 32,
9213           "endianness", G_TYPE_INT, G_BIG_ENDIAN, NULL);
9214       break;
9215     case FOURCC_in24:
9216       _codec ("Raw 24-bit PCM audio");
9217       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
9218        * endian later */
9219       caps = gst_caps_new_simple ("audio/x-raw-int", "width", G_TYPE_INT, 24,
9220           "depth", G_TYPE_INT, 24,
9221           "endianness", G_TYPE_INT, G_BIG_ENDIAN,
9222           "signed", G_TYPE_BOOLEAN, TRUE, NULL);
9223       break;
9224     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
9225       _codec ("Raw 32-bit PCM audio");
9226       caps = gst_caps_new_simple ("audio/x-raw-int", "width", G_TYPE_INT, 32,
9227           "depth", G_TYPE_INT, 32,
9228           "endianness", G_TYPE_INT, G_BIG_ENDIAN,
9229           "signed", G_TYPE_BOOLEAN, TRUE, NULL);
9230       break;
9231     case GST_MAKE_FOURCC ('u', 'l', 'a', 'w'):
9232       _codec ("Mu-law audio");
9233       caps = gst_caps_new_simple ("audio/x-mulaw", NULL);
9234       break;
9235     case GST_MAKE_FOURCC ('a', 'l', 'a', 'w'):
9236       _codec ("A-law audio");
9237       caps = gst_caps_new_simple ("audio/x-alaw", NULL);
9238       break;
9239     case 0x0200736d:
9240     case 0x6d730002:
9241       _codec ("Microsoft ADPCM");
9242       /* Microsoft ADPCM-ACM code 2 */
9243       caps = gst_caps_new_simple ("audio/x-adpcm",
9244           "layout", G_TYPE_STRING, "microsoft", NULL);
9245       break;
9246     case 0x1100736d:
9247     case 0x6d730011:
9248       _codec ("DVI/IMA ADPCM");
9249       caps = gst_caps_new_simple ("audio/x-adpcm",
9250           "layout", G_TYPE_STRING, "dvi", NULL);
9251       break;
9252     case 0x1700736d:
9253     case 0x6d730017:
9254       _codec ("DVI/Intel IMA ADPCM");
9255       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
9256       caps = gst_caps_new_simple ("audio/x-adpcm",
9257           "layout", G_TYPE_STRING, "quicktime", NULL);
9258       break;
9259     case 0x5500736d:
9260     case 0x6d730055:
9261       /* MPEG layer 3, CBR only (pre QT4.1) */
9262     case GST_MAKE_FOURCC ('.', 'm', 'p', '3'):
9263       _codec ("MPEG-1 layer 3");
9264       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
9265       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
9266           "mpegversion", G_TYPE_INT, 1, NULL);
9267       break;
9268     case 0x20736d:
9269     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
9270       _codec ("EAC-3 audio");
9271       caps = gst_caps_new_simple ("audio/x-eac3",
9272           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
9273       stream->sampled = TRUE;
9274       break;
9275     case GST_MAKE_FOURCC ('a', 'c', '-', '3'):
9276       _codec ("AC-3 audio");
9277       caps = gst_caps_new_simple ("audio/x-ac3",
9278           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
9279       stream->sampled = TRUE;
9280       break;
9281     case GST_MAKE_FOURCC ('M', 'A', 'C', '3'):
9282       _codec ("MACE-3");
9283       caps = gst_caps_new_simple ("audio/x-mace",
9284           "maceversion", G_TYPE_INT, 3, NULL);
9285       break;
9286     case GST_MAKE_FOURCC ('M', 'A', 'C', '6'):
9287       _codec ("MACE-6");
9288       caps = gst_caps_new_simple ("audio/x-mace",
9289           "maceversion", G_TYPE_INT, 6, NULL);
9290       break;
9291     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
9292       /* ogg/vorbis */
9293       caps = gst_caps_new_simple ("application/ogg", NULL);
9294       break;
9295     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
9296       _codec ("DV audio");
9297       caps = gst_caps_new_simple ("audio/x-dv", NULL);
9298       break;
9299     case GST_MAKE_FOURCC ('m', 'p', '4', 'a'):
9300       _codec ("MPEG-4 AAC audio");
9301       caps = gst_caps_new_simple ("audio/mpeg",
9302           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
9303           "stream-format", G_TYPE_STRING, "raw", NULL);
9304       break;
9305     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
9306       _codec ("QDesign Music");
9307       caps = gst_caps_new_simple ("audio/x-qdm", NULL);
9308       break;
9309     case GST_MAKE_FOURCC ('Q', 'D', 'M', '2'):
9310       _codec ("QDesign Music v.2");
9311       /* FIXME: QDesign music version 2 (no constant) */
9312       if (data) {
9313         caps = gst_caps_new_simple ("audio/x-qdm2",
9314             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
9315             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
9316             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
9317       } else {
9318         caps = gst_caps_new_simple ("audio/x-qdm2", NULL);
9319       }
9320       break;
9321     case GST_MAKE_FOURCC ('a', 'g', 's', 'm'):
9322       _codec ("GSM audio");
9323       caps = gst_caps_new_simple ("audio/x-gsm", NULL);
9324       break;
9325     case GST_MAKE_FOURCC ('s', 'a', 'm', 'r'):
9326       _codec ("AMR audio");
9327       caps = gst_caps_new_simple ("audio/AMR", NULL);
9328       break;
9329     case GST_MAKE_FOURCC ('s', 'a', 'w', 'b'):
9330       _codec ("AMR-WB audio");
9331       caps = gst_caps_new_simple ("audio/AMR-WB", NULL);
9332       break;
9333     case GST_MAKE_FOURCC ('i', 'm', 'a', '4'):
9334       _codec ("Quicktime IMA ADPCM");
9335       caps = gst_caps_new_simple ("audio/x-adpcm",
9336           "layout", G_TYPE_STRING, "quicktime", NULL);
9337       break;
9338     case GST_MAKE_FOURCC ('a', 'l', 'a', 'c'):
9339       _codec ("Apple lossless audio");
9340       caps = gst_caps_new_simple ("audio/x-alac", NULL);
9341       break;
9342     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
9343       _codec ("QualComm PureVoice");
9344       caps = gst_caps_from_string ("audio/qcelp");
9345       break;
9346     case FOURCC_owma:
9347       _codec ("WMA");
9348       caps = gst_caps_new_simple ("audio/x-wma", NULL);
9349       break;
9350     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
9351       /* ? */
9352     default:
9353     {
9354       char *s;
9355
9356       s = g_strdup_printf ("audio/x-gst-fourcc-%" GST_FOURCC_FORMAT,
9357           GST_FOURCC_ARGS (fourcc));
9358       caps = gst_caps_new_simple (s, NULL);
9359       break;
9360     }
9361   }
9362
9363   /* enable clipping for raw audio streams */
9364   s = gst_caps_get_structure (caps, 0);
9365   name = gst_structure_get_name (s);
9366   if (g_str_has_prefix (name, "audio/x-raw-")) {
9367     stream->need_clip = TRUE;
9368   }
9369   return caps;
9370 }
9371
9372 static GstCaps *
9373 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
9374     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
9375 {
9376   GstCaps *caps;
9377
9378   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc %08x", fourcc);
9379
9380   switch (fourcc) {
9381     case GST_MAKE_FOURCC ('m', 'p', '4', 's'):
9382       _codec ("DVD subtitle");
9383       caps = gst_caps_new_simple ("video/x-dvd-subpicture", NULL);
9384       break;
9385     case GST_MAKE_FOURCC ('t', 'e', 'x', 't'):
9386       _codec ("Quicktime timed text");
9387       goto text;
9388     case GST_MAKE_FOURCC ('t', 'x', '3', 'g'):
9389       _codec ("3GPP timed text");
9390     text:
9391       caps = gst_caps_new_simple ("text/plain", NULL);
9392       /* actual text piece needs to be extracted */
9393       stream->need_process = TRUE;
9394       break;
9395     default:
9396     {
9397       char *s;
9398
9399       s = g_strdup_printf ("text/x-gst-fourcc-%" GST_FOURCC_FORMAT,
9400           GST_FOURCC_ARGS (fourcc));
9401       caps = gst_caps_new_simple (s, NULL);
9402       break;
9403     }
9404   }
9405   return caps;
9406 }