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