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