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