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