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