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