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