qtdemux: avoid looping reading the 'moof' atom forever
[platform/upstream/gstreamer.git] / gst / isomp4 / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  * 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       } else {
3317         qtdemux->offset += length;      /* skip moof and keep going */
3318       }
3319       if (qtdemux->got_moov) {
3320         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
3321         ret = GST_FLOW_EOS;
3322         goto beach;
3323       }
3324       break;
3325     case FOURCC_mdat:
3326     case FOURCC_free:
3327     case FOURCC_wide:
3328     case FOURCC_PICT:
3329     case FOURCC_pnot:
3330     {
3331       GST_LOG_OBJECT (qtdemux,
3332           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
3333           GST_FOURCC_ARGS (fourcc), cur_offset);
3334       qtdemux->offset = add_offset (qtdemux->offset, length);
3335       break;
3336     }
3337     case FOURCC_moov:
3338     {
3339       GstBuffer *moov = NULL;
3340
3341       if (qtdemux->got_moov) {
3342         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
3343         qtdemux->offset = add_offset (qtdemux->offset, length);
3344         goto beach;
3345       }
3346
3347       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
3348       if (ret != GST_FLOW_OK)
3349         goto beach;
3350       gst_buffer_map (moov, &map, GST_MAP_READ);
3351
3352       if (length != map.size) {
3353         /* Some files have a 'moov' atom at the end of the file which contains
3354          * a terminal 'free' atom where the body of the atom is missing.
3355          * Check for, and permit, this special case.
3356          */
3357         if (map.size >= 8) {
3358           guint8 *final_data = map.data + (map.size - 8);
3359           guint32 final_length = QT_UINT32 (final_data);
3360           guint32 final_fourcc = QT_FOURCC (final_data + 4);
3361
3362           if (final_fourcc == FOURCC_free
3363               && map.size + final_length - 8 == length) {
3364             /* Ok, we've found that special case. Allocate a new buffer with
3365              * that free atom actually present. */
3366             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
3367             gst_buffer_fill (newmoov, 0, map.data, map.size);
3368             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
3369             gst_buffer_unmap (moov, &map);
3370             gst_buffer_unref (moov);
3371             moov = newmoov;
3372             gst_buffer_map (moov, &map, GST_MAP_READ);
3373           }
3374         }
3375       }
3376
3377       if (length != map.size) {
3378         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
3379             (_("This file is incomplete and cannot be played.")),
3380             ("We got less than expected (received %" G_GSIZE_FORMAT
3381                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
3382                 (guint) length, cur_offset));
3383         gst_buffer_unmap (moov, &map);
3384         gst_buffer_unref (moov);
3385         ret = GST_FLOW_ERROR;
3386         goto beach;
3387       }
3388       qtdemux->offset += length;
3389
3390       qtdemux_parse_moov (qtdemux, map.data, length);
3391       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
3392
3393       qtdemux_parse_tree (qtdemux);
3394       g_node_destroy (qtdemux->moov_node);
3395       gst_buffer_unmap (moov, &map);
3396       gst_buffer_unref (moov);
3397       qtdemux->moov_node = NULL;
3398       qtdemux->got_moov = TRUE;
3399
3400       break;
3401     }
3402     case FOURCC_ftyp:
3403     {
3404       GstBuffer *ftyp = NULL;
3405
3406       /* extract major brand; might come in handy for ISO vs QT issues */
3407       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
3408       if (ret != GST_FLOW_OK)
3409         goto beach;
3410       qtdemux->offset += length;
3411       gst_buffer_map (ftyp, &map, GST_MAP_READ);
3412       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
3413       gst_buffer_unmap (ftyp, &map);
3414       gst_buffer_unref (ftyp);
3415       break;
3416     }
3417     case FOURCC_uuid:
3418     {
3419       GstBuffer *uuid = NULL;
3420
3421       /* uuid are extension atoms */
3422       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
3423       if (ret != GST_FLOW_OK)
3424         goto beach;
3425       qtdemux->offset += length;
3426       gst_buffer_map (uuid, &map, GST_MAP_READ);
3427       qtdemux_parse_uuid (qtdemux, map.data, map.size);
3428       gst_buffer_unmap (uuid, &map);
3429       gst_buffer_unref (uuid);
3430       break;
3431     }
3432     case FOURCC_sidx:
3433     {
3434       GstBuffer *sidx = NULL;
3435       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
3436       if (ret != GST_FLOW_OK)
3437         goto beach;
3438       qtdemux->offset += length;
3439       gst_buffer_map (sidx, &map, GST_MAP_READ);
3440       qtdemux_parse_sidx (qtdemux, map.data, map.size);
3441       gst_buffer_unmap (sidx, &map);
3442       gst_buffer_unref (sidx);
3443       break;
3444     }
3445     default:
3446     {
3447       GstBuffer *unknown = NULL;
3448
3449       GST_LOG_OBJECT (qtdemux,
3450           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
3451           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
3452           cur_offset);
3453       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
3454       if (ret != GST_FLOW_OK)
3455         goto beach;
3456       gst_buffer_map (unknown, &map, GST_MAP_READ);
3457       GST_MEMDUMP ("Unknown tag", map.data, map.size);
3458       gst_buffer_unmap (unknown, &map);
3459       gst_buffer_unref (unknown);
3460       qtdemux->offset += length;
3461       break;
3462     }
3463   }
3464
3465 beach:
3466   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
3467     /* digested all data, show what we have */
3468     qtdemux_prepare_streams (qtdemux);
3469     ret = qtdemux_expose_streams (qtdemux);
3470
3471     qtdemux->state = QTDEMUX_STATE_MOVIE;
3472     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
3473         qtdemux->state);
3474     return ret;
3475   }
3476   return ret;
3477 }
3478
3479 /* Seeks to the previous keyframe of the indexed stream and
3480  * aligns other streams with respect to the keyframe timestamp
3481  * of indexed stream. Only called in case of Reverse Playback
3482  */
3483 static GstFlowReturn
3484 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
3485 {
3486   guint8 n = 0;
3487   guint32 seg_idx = 0, k_index = 0;
3488   guint32 ref_seg_idx, ref_k_index;
3489   GstClockTime k_pos = 0, last_stop = 0;
3490   QtDemuxSegment *seg = NULL;
3491   QtDemuxStream *ref_str = NULL;
3492   guint64 seg_media_start_mov;  /* segment media start time in mov format */
3493   guint64 target_ts;
3494
3495   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
3496    * and finally align all the other streams on that timestamp with their
3497    * respective keyframes */
3498   for (n = 0; n < qtdemux->n_streams; n++) {
3499     QtDemuxStream *str = qtdemux->streams[n];
3500
3501     /* No candidate yet, take the first stream */
3502     if (!ref_str) {
3503       ref_str = str;
3504       continue;
3505     }
3506
3507     /* So that stream has a segment, we prefer video streams */
3508     if (str->subtype == FOURCC_vide) {
3509       ref_str = str;
3510       break;
3511     }
3512   }
3513
3514   if (G_UNLIKELY (!ref_str)) {
3515     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
3516     goto eos;
3517   }
3518
3519   if (G_UNLIKELY (!ref_str->from_sample)) {
3520     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
3521     goto eos;
3522   }
3523
3524   /* So that stream has been playing from from_sample to to_sample. We will
3525    * get the timestamp of the previous sample and search for a keyframe before
3526    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
3527   if (ref_str->subtype == FOURCC_vide) {
3528     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
3529         ref_str->from_sample - 1);
3530   } else {
3531     if (ref_str->from_sample >= 10)
3532       k_index = ref_str->from_sample - 10;
3533     else
3534       k_index = 0;
3535   }
3536
3537   target_ts =
3538       ref_str->samples[k_index].timestamp +
3539       ref_str->samples[k_index].pts_offset;
3540
3541   /* get current segment for that stream */
3542   seg = &ref_str->segments[ref_str->segment_index];
3543   /* Use segment start in original timescale for comparisons */
3544   seg_media_start_mov = seg->trak_media_start;
3545
3546   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
3547       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
3548       k_index, target_ts, seg_media_start_mov,
3549       GST_TIME_ARGS (seg->media_start));
3550
3551   /* Crawl back through segments to find the one containing this I frame */
3552   while (target_ts < seg_media_start_mov) {
3553     GST_DEBUG_OBJECT (qtdemux,
3554         "keyframe position (sample %u) is out of segment %u " " target %"
3555         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
3556         ref_str->segment_index, target_ts, seg_media_start_mov);
3557
3558     if (G_UNLIKELY (!ref_str->segment_index)) {
3559       /* Reached first segment, let's consider it's EOS */
3560       goto eos;
3561     }
3562     ref_str->segment_index--;
3563     seg = &ref_str->segments[ref_str->segment_index];
3564     /* Use segment start in original timescale for comparisons */
3565     seg_media_start_mov = seg->trak_media_start;
3566   }
3567   /* Calculate time position of the keyframe and where we should stop */
3568   k_pos =
3569       QTSTREAMTIME_TO_GSTTIME (ref_str,
3570       target_ts - seg->trak_media_start) + seg->time;
3571   last_stop =
3572       QTSTREAMTIME_TO_GSTTIME (ref_str,
3573       ref_str->samples[ref_str->from_sample].timestamp -
3574       seg->trak_media_start) + seg->time;
3575
3576   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
3577       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
3578       k_index, GST_TIME_ARGS (k_pos));
3579
3580   /* Set last_stop with the keyframe timestamp we pushed of that stream */
3581   qtdemux->segment.position = last_stop;
3582   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
3583       GST_TIME_ARGS (last_stop));
3584
3585   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
3586     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
3587     goto eos;
3588   }
3589
3590   ref_seg_idx = ref_str->segment_index;
3591   ref_k_index = k_index;
3592
3593   /* Align them all on this */
3594   for (n = 0; n < qtdemux->n_streams; n++) {
3595     guint32 index = 0;
3596     GstClockTime seg_time = 0;
3597     QtDemuxStream *str = qtdemux->streams[n];
3598
3599     /* aligning reference stream again might lead to backing up to yet another
3600      * keyframe (due to timestamp rounding issues),
3601      * potentially putting more load on downstream; so let's try to avoid */
3602     if (str == ref_str) {
3603       seg_idx = ref_seg_idx;
3604       seg = &str->segments[seg_idx];
3605       k_index = ref_k_index;
3606       GST_DEBUG_OBJECT (qtdemux, "reference stream %d segment %d, "
3607           "sample at index %d", n, ref_str->segment_index, k_index);
3608     } else {
3609       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
3610       GST_DEBUG_OBJECT (qtdemux,
3611           "stream %d align segment %d for keyframe pos %" GST_TIME_FORMAT, n,
3612           seg_idx, GST_TIME_ARGS (k_pos));
3613
3614       /* get segment and time in the segment */
3615       seg = &str->segments[seg_idx];
3616       seg_time = k_pos - seg->time;
3617
3618       /* get the media time in the segment.
3619        * No adjustment for empty "filler" segments */
3620       if (seg->media_start != GST_CLOCK_TIME_NONE)
3621         seg_time += seg->media_start;
3622
3623       /* get the index of the sample with media time */
3624       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
3625       GST_DEBUG_OBJECT (qtdemux,
3626           "stream %d sample for %" GST_TIME_FORMAT " at %u", n,
3627           GST_TIME_ARGS (seg_time), index);
3628
3629       /* find previous keyframe */
3630       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index);
3631     }
3632
3633     /* Remember until where we want to go */
3634     str->to_sample = str->from_sample - 1;
3635     /* Define our time position */
3636     target_ts =
3637         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
3638     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
3639     if (seg->media_start != GST_CLOCK_TIME_NONE)
3640       str->time_position -= seg->media_start;
3641
3642     /* Now seek back in time */
3643     gst_qtdemux_move_stream (qtdemux, str, k_index);
3644     GST_DEBUG_OBJECT (qtdemux, "stream %d keyframe at %u, time position %"
3645         GST_TIME_FORMAT " playing from sample %u to %u", n, k_index,
3646         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
3647   }
3648
3649   return GST_FLOW_OK;
3650
3651 eos:
3652   return GST_FLOW_EOS;
3653 }
3654
3655 /* activate the given segment number @seg_idx of @stream at time @offset.
3656  * @offset is an absolute global position over all the segments.
3657  *
3658  * This will push out a NEWSEGMENT event with the right values and
3659  * position the stream index to the first decodable sample before
3660  * @offset.
3661  *
3662  * PULL-BASED
3663  */
3664 static gboolean
3665 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
3666     guint32 seg_idx, GstClockTime offset)
3667 {
3668   GstEvent *event;
3669   QtDemuxSegment *segment;
3670   guint32 index, kf_index;
3671   GstClockTime seg_time;
3672   GstClockTime start, stop, time;
3673   gdouble rate;
3674
3675   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
3676       seg_idx, GST_TIME_ARGS (offset));
3677
3678   /* update the current segment */
3679   stream->segment_index = seg_idx;
3680
3681   /* get the segment */
3682   segment = &stream->segments[seg_idx];
3683
3684   if (G_UNLIKELY (offset < segment->time)) {
3685     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
3686         GST_TIME_ARGS (segment->time));
3687     return FALSE;
3688   }
3689
3690   /* segment lies beyond total indicated duration */
3691   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
3692           segment->time > qtdemux->segment.duration)) {
3693     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
3694         " < segment->time %" GST_TIME_FORMAT,
3695         GST_TIME_ARGS (qtdemux->segment.duration),
3696         GST_TIME_ARGS (segment->time));
3697     return FALSE;
3698   }
3699
3700   /* get time in this segment */
3701   seg_time = offset - segment->time;
3702
3703   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
3704       GST_TIME_ARGS (seg_time));
3705
3706   if (G_UNLIKELY (seg_time > segment->duration)) {
3707     GST_LOG_OBJECT (stream->pad,
3708         "seg_time > segment->duration %" GST_TIME_FORMAT,
3709         GST_TIME_ARGS (segment->duration));
3710     seg_time = segment->duration;
3711   }
3712
3713   /* qtdemux->segment.stop is in outside-time-realm, whereas
3714    * segment->media_stop is in track-time-realm.
3715    *
3716    * In order to compare the two, we need to bring segment.stop
3717    * into the track-time-realm */
3718
3719   stop = qtdemux->segment.stop;
3720   if (stop == GST_CLOCK_TIME_NONE)
3721     stop = qtdemux->segment.duration;
3722   if (stop == GST_CLOCK_TIME_NONE)
3723     stop = segment->media_stop;
3724   else
3725     stop =
3726         MIN (segment->media_stop, stop - segment->time + segment->media_start);
3727
3728   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
3729     start = segment->time + seg_time;
3730     time = offset;
3731     stop = start - seg_time + segment->duration;
3732   } else if (qtdemux->segment.rate >= 0) {
3733     start = MIN (segment->media_start + seg_time, stop);
3734     time = offset;
3735   } else {
3736     if (segment->media_start >= qtdemux->segment.start) {
3737       time = segment->time;
3738     } else {
3739       time = segment->time + (qtdemux->segment.start - segment->media_start);
3740     }
3741
3742     start = MAX (segment->media_start, qtdemux->segment.start);
3743     stop = MIN (segment->media_start + seg_time, stop);
3744   }
3745
3746   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
3747       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
3748       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
3749
3750   /* combine global rate with that of the segment */
3751   rate = segment->rate * qtdemux->segment.rate;
3752
3753   /* Copy flags from main segment */
3754   stream->segment.flags = qtdemux->segment.flags;
3755
3756   /* accumulate previous segments */
3757   if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
3758     stream->accumulated_base += (stream->segment.stop - stream->segment.start) /
3759         ABS (stream->segment.rate);
3760
3761   /* update the segment values used for clipping */
3762   stream->segment.offset = qtdemux->segment.offset;
3763   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
3764   stream->segment.applied_rate = qtdemux->segment.applied_rate;
3765   stream->segment.rate = rate;
3766   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
3767       stream->cslg_shift);
3768   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
3769       stream->cslg_shift);
3770   stream->segment.time = time;
3771   stream->segment.position = stream->segment.start;
3772
3773   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
3774       &stream->segment);
3775
3776   /* now prepare and send the segment */
3777   if (stream->pad) {
3778     event = gst_event_new_segment (&stream->segment);
3779     if (stream->segment_seqnum) {
3780       gst_event_set_seqnum (event, stream->segment_seqnum);
3781     }
3782     gst_pad_push_event (stream->pad, event);
3783     /* assume we can send more data now */
3784     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
3785     /* clear to send tags on this pad now */
3786     gst_qtdemux_push_tags (qtdemux, stream);
3787   }
3788
3789   /* in the fragmented case, we pick a fragment that starts before our
3790    * desired position and rely on downstream to wait for a keyframe
3791    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
3792    * tfra entries tells us which trun/sample the key unit is in, but we don't
3793    * make use of this additional information at the moment) */
3794   if (qtdemux->fragmented) {
3795     stream->to_sample = G_MAXUINT32;
3796     return TRUE;
3797   }
3798
3799   /* and move to the keyframe before the indicated media time of the
3800    * segment */
3801   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
3802     if (qtdemux->segment.rate >= 0) {
3803       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
3804       stream->to_sample = G_MAXUINT32;
3805       GST_DEBUG_OBJECT (stream->pad,
3806           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
3807           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
3808           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
3809     } else {
3810       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
3811       stream->to_sample = index;
3812       GST_DEBUG_OBJECT (stream->pad,
3813           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
3814           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
3815           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
3816     }
3817   } else {
3818     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
3819         "this is an empty segment");
3820     return TRUE;
3821   }
3822
3823   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
3824    * encountered an error and printed a message so we return appropriately */
3825   if (index == -1)
3826     return FALSE;
3827
3828   /* we're at the right spot */
3829   if (index == stream->sample_index) {
3830     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
3831     return TRUE;
3832   }
3833
3834   /* find keyframe of the target index */
3835   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index);
3836
3837 /* *INDENT-OFF* */
3838 /* indent does stupid stuff with stream->samples[].timestamp */
3839
3840   /* if we move forwards, we don't have to go back to the previous
3841    * keyframe since we already sent that. We can also just jump to
3842    * the keyframe right before the target index if there is one. */
3843   if (index > stream->sample_index) {
3844     /* moving forwards check if we move past a keyframe */
3845     if (kf_index > stream->sample_index) {
3846       GST_DEBUG_OBJECT (stream->pad,
3847            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
3848            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
3849            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
3850       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
3851     } else {
3852       GST_DEBUG_OBJECT (stream->pad,
3853           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
3854           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
3855           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
3856     }
3857   } else {
3858     GST_DEBUG_OBJECT (stream->pad,
3859         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
3860         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
3861         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
3862     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
3863   }
3864
3865 /* *INDENT-ON* */
3866
3867   return TRUE;
3868 }
3869
3870 /* prepare to get the current sample of @stream, getting essential values.
3871  *
3872  * This function will also prepare and send the segment when needed.
3873  *
3874  * Return FALSE if the stream is EOS.
3875  *
3876  * PULL-BASED
3877  */
3878 static gboolean
3879 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
3880     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
3881     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
3882     gboolean * keyframe)
3883 {
3884   QtDemuxSample *sample;
3885   GstClockTime time_position;
3886   guint32 seg_idx;
3887
3888   g_return_val_if_fail (stream != NULL, FALSE);
3889
3890   time_position = stream->time_position;
3891   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
3892     goto eos;
3893
3894   seg_idx = stream->segment_index;
3895   if (G_UNLIKELY (seg_idx == -1)) {
3896     /* find segment corresponding to time_position if we are looking
3897      * for a segment. */
3898     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
3899   }
3900
3901   /* different segment, activate it, sample_index will be set. */
3902   if (G_UNLIKELY (stream->segment_index != seg_idx))
3903     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
3904
3905   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
3906                   segment_index]))) {
3907     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
3908
3909     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
3910         " prepare empty sample");
3911
3912     *empty = TRUE;
3913     *pts = *dts = time_position;
3914     *duration = seg->duration - (time_position - seg->time);
3915
3916     return TRUE;
3917   }
3918
3919   *empty = FALSE;
3920
3921   if (stream->sample_index == -1)
3922     stream->sample_index = 0;
3923
3924   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
3925       stream->sample_index, stream->n_samples);
3926
3927   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
3928     if (!qtdemux->fragmented)
3929       goto eos;
3930
3931     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
3932     do {
3933       GstFlowReturn flow;
3934
3935       GST_OBJECT_LOCK (qtdemux);
3936       flow = qtdemux_add_fragmented_samples (qtdemux);
3937       GST_OBJECT_UNLOCK (qtdemux);
3938
3939       if (flow != GST_FLOW_OK)
3940         goto eos;
3941     }
3942     while (stream->sample_index >= stream->n_samples);
3943   }
3944
3945   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
3946     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
3947         stream->sample_index);
3948     return FALSE;
3949   }
3950
3951   /* now get the info for the sample we're at */
3952   sample = &stream->samples[stream->sample_index];
3953
3954   *dts = QTSAMPLE_DTS (stream, sample);
3955   *pts = QTSAMPLE_PTS (stream, sample);
3956   *offset = sample->offset;
3957   *size = sample->size;
3958   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
3959   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
3960
3961   return TRUE;
3962
3963   /* special cases */
3964 eos:
3965   {
3966     stream->time_position = GST_CLOCK_TIME_NONE;
3967     return FALSE;
3968   }
3969 }
3970
3971 /* move to the next sample in @stream.
3972  *
3973  * Moves to the next segment when needed.
3974  */
3975 static void
3976 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
3977 {
3978   QtDemuxSample *sample;
3979   QtDemuxSegment *segment;
3980
3981   /* get current segment */
3982   segment = &stream->segments[stream->segment_index];
3983
3984   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
3985     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
3986     goto next_segment;
3987   }
3988
3989   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
3990     /* Mark the stream as EOS */
3991     GST_DEBUG_OBJECT (qtdemux,
3992         "reached max allowed sample %u, mark EOS", stream->to_sample);
3993     stream->time_position = GST_CLOCK_TIME_NONE;
3994     return;
3995   }
3996
3997   /* move to next sample */
3998   stream->sample_index++;
3999   stream->offset_in_sample = 0;
4000
4001   /* reached the last sample, we need the next segment */
4002   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
4003     goto next_segment;
4004
4005   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4006     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4007         stream->sample_index);
4008     return;
4009   }
4010
4011   /* get next sample */
4012   sample = &stream->samples[stream->sample_index];
4013
4014   /* see if we are past the segment */
4015   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
4016     goto next_segment;
4017
4018   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
4019     /* inside the segment, update time_position, looks very familiar to
4020      * GStreamer segments, doesn't it? */
4021     stream->time_position =
4022         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
4023   } else {
4024     /* not yet in segment, time does not yet increment. This means
4025      * that we are still prerolling keyframes to the decoder so it can
4026      * decode the first sample of the segment. */
4027     stream->time_position = segment->time;
4028   }
4029   return;
4030
4031   /* move to the next segment */
4032 next_segment:
4033   {
4034     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
4035
4036     if (stream->segment_index == stream->n_segments - 1) {
4037       /* are we at the end of the last segment, we're EOS */
4038       stream->time_position = GST_CLOCK_TIME_NONE;
4039     } else {
4040       /* else we're only at the end of the current segment */
4041       stream->time_position = segment->stop_time;
4042     }
4043     /* make sure we select a new segment */
4044     stream->segment_index = -1;
4045   }
4046 }
4047
4048 static void
4049 gst_qtdemux_sync_streams (GstQTDemux * demux)
4050 {
4051   gint i;
4052
4053   if (demux->n_streams <= 1)
4054     return;
4055
4056   for (i = 0; i < demux->n_streams; i++) {
4057     QtDemuxStream *stream;
4058     GstClockTime end_time;
4059
4060     stream = demux->streams[i];
4061
4062     if (!stream->pad)
4063       continue;
4064
4065     /* TODO advance time on subtitle streams here, if any some day */
4066
4067     /* some clips/trailers may have unbalanced streams at the end,
4068      * so send EOS on shorter stream to prevent stalling others */
4069
4070     /* do not mess with EOS if SEGMENT seeking */
4071     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
4072       continue;
4073
4074     if (demux->pullbased) {
4075       /* loop mode is sample time based */
4076       if (!STREAM_IS_EOS (stream))
4077         continue;
4078     } else {
4079       /* push mode is byte position based */
4080       if (stream->n_samples &&
4081           stream->samples[stream->n_samples - 1].offset >= demux->offset)
4082         continue;
4083     }
4084
4085     if (stream->sent_eos)
4086       continue;
4087
4088     /* only act if some gap */
4089     end_time = stream->segments[stream->n_segments - 1].stop_time;
4090     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
4091         ", stream end: %" GST_TIME_FORMAT,
4092         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
4093     if (GST_CLOCK_TIME_IS_VALID (end_time)
4094         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
4095       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
4096           GST_PAD_NAME (stream->pad));
4097       stream->sent_eos = TRUE;
4098       gst_pad_push_event (stream->pad, gst_event_new_eos ());
4099     }
4100   }
4101 }
4102
4103 /* EOS and NOT_LINKED need to be combined. This means that we return:
4104  *
4105  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
4106  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
4107  */
4108 static GstFlowReturn
4109 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
4110     GstFlowReturn ret)
4111 {
4112   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
4113
4114   if (stream->pad)
4115     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
4116         ret);
4117   else
4118     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
4119
4120   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
4121   return ret;
4122 }
4123
4124 /* the input buffer metadata must be writable. Returns NULL when the buffer is
4125  * completely clipped
4126  *
4127  * Should be used only with raw buffers */
4128 static GstBuffer *
4129 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
4130     GstBuffer * buf)
4131 {
4132   guint64 start, stop, cstart, cstop, diff;
4133   GstClockTime pts, duration;
4134   gsize size, osize;
4135   gint num_rate, denom_rate;
4136   gint frame_size;
4137   gboolean clip_data;
4138   guint offset;
4139
4140   osize = size = gst_buffer_get_size (buf);
4141   offset = 0;
4142
4143   /* depending on the type, setup the clip parameters */
4144   if (stream->subtype == FOURCC_soun) {
4145     frame_size = stream->bytes_per_frame;
4146     num_rate = GST_SECOND;
4147     denom_rate = (gint) stream->rate;
4148     clip_data = TRUE;
4149   } else if (stream->subtype == FOURCC_vide) {
4150     frame_size = size;
4151     num_rate = stream->fps_n;
4152     denom_rate = stream->fps_d;
4153     clip_data = FALSE;
4154   } else
4155     goto wrong_type;
4156
4157   if (frame_size <= 0)
4158     goto bad_frame_size;
4159
4160   /* we can only clip if we have a valid pts */
4161   pts = GST_BUFFER_PTS (buf);
4162   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
4163     goto no_pts;
4164
4165   duration = GST_BUFFER_DURATION (buf);
4166
4167   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
4168     duration =
4169         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
4170   }
4171
4172   start = pts;
4173   stop = start + duration;
4174
4175   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
4176               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
4177     goto clipped;
4178
4179   /* see if some clipping happened */
4180   diff = cstart - start;
4181   if (diff > 0) {
4182     pts += diff;
4183     duration -= diff;
4184
4185     if (clip_data) {
4186       /* bring clipped time to samples and to bytes */
4187       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
4188       diff *= frame_size;
4189
4190       GST_DEBUG_OBJECT (qtdemux,
4191           "clipping start to %" GST_TIME_FORMAT " %"
4192           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
4193
4194       offset = diff;
4195       size -= diff;
4196     }
4197   }
4198   diff = stop - cstop;
4199   if (diff > 0) {
4200     duration -= diff;
4201
4202     if (clip_data) {
4203       /* bring clipped time to samples and then to bytes */
4204       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
4205       diff *= frame_size;
4206       GST_DEBUG_OBJECT (qtdemux,
4207           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
4208           " bytes", GST_TIME_ARGS (cstop), diff);
4209       size -= diff;
4210     }
4211   }
4212
4213   if (offset != 0 || size != osize)
4214     gst_buffer_resize (buf, offset, size);
4215
4216   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
4217   GST_BUFFER_PTS (buf) = pts;
4218   GST_BUFFER_DURATION (buf) = duration;
4219
4220   return buf;
4221
4222   /* dropped buffer */
4223 wrong_type:
4224   {
4225     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
4226     return buf;
4227   }
4228 bad_frame_size:
4229   {
4230     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
4231     return buf;
4232   }
4233 no_pts:
4234   {
4235     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
4236     return buf;
4237   }
4238 clipped:
4239   {
4240     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
4241     gst_buffer_unref (buf);
4242     return NULL;
4243   }
4244 }
4245
4246 /* the input buffer metadata must be writable,
4247  * but time/duration etc not yet set and need not be preserved */
4248 static GstBuffer *
4249 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
4250     GstBuffer * buf)
4251 {
4252   GstMapInfo map;
4253   guint nsize = 0;
4254   gchar *str;
4255
4256   /* not many cases for now */
4257   if (G_UNLIKELY (stream->fourcc == FOURCC_mp4s)) {
4258     /* send a one time dvd clut event */
4259     if (stream->pending_event && stream->pad)
4260       gst_pad_push_event (stream->pad, stream->pending_event);
4261     stream->pending_event = NULL;
4262   }
4263
4264   if (G_UNLIKELY (stream->subtype != FOURCC_text
4265           && stream->subtype != FOURCC_sbtl &&
4266           stream->subtype != FOURCC_subp)) {
4267     return buf;
4268   }
4269
4270   gst_buffer_map (buf, &map, GST_MAP_READ);
4271
4272   /* empty buffer is sent to terminate previous subtitle */
4273   if (map.size <= 2) {
4274     gst_buffer_unmap (buf, &map);
4275     gst_buffer_unref (buf);
4276     return NULL;
4277   }
4278   if (stream->subtype == FOURCC_subp) {
4279     /* That's all the processing needed for subpictures */
4280     gst_buffer_unmap (buf, &map);
4281     return buf;
4282   }
4283
4284   nsize = GST_READ_UINT16_BE (map.data);
4285   nsize = MIN (nsize, map.size - 2);
4286
4287   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
4288       nsize, map.size);
4289
4290   /* takes care of UTF-8 validation or UTF-16 recognition,
4291    * no other encoding expected */
4292   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
4293   gst_buffer_unmap (buf, &map);
4294   if (str) {
4295     gst_buffer_unref (buf);
4296     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
4297   } else {
4298     /* this should not really happen unless the subtitle is corrupted */
4299     gst_buffer_unref (buf);
4300     buf = NULL;
4301   }
4302
4303   /* FIXME ? convert optional subsequent style info to markup */
4304
4305   return buf;
4306 }
4307
4308 /* Sets a buffer's attributes properly and pushes it downstream.
4309  * Also checks for additional actions and custom processing that may
4310  * need to be done first.
4311  */
4312 static GstFlowReturn
4313 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
4314     QtDemuxStream * stream, GstBuffer * buf,
4315     GstClockTime dts, GstClockTime pts, GstClockTime duration,
4316     gboolean keyframe, GstClockTime position, guint64 byte_position)
4317 {
4318   GstFlowReturn ret = GST_FLOW_OK;
4319
4320   /* offset the timestamps according to the edit list */
4321
4322   if (G_UNLIKELY (stream->fourcc == FOURCC_rtsp)) {
4323     gchar *url;
4324     GstMapInfo map;
4325
4326     gst_buffer_map (buf, &map, GST_MAP_READ);
4327     url = g_strndup ((gchar *) map.data, map.size);
4328     gst_buffer_unmap (buf, &map);
4329     if (url != NULL && strlen (url) != 0) {
4330       /* we have RTSP redirect now */
4331       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
4332           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
4333               gst_structure_new ("redirect",
4334                   "new-location", G_TYPE_STRING, url, NULL)));
4335       qtdemux->posted_redirect = TRUE;
4336     } else {
4337       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
4338           "posting");
4339     }
4340     g_free (url);
4341   }
4342
4343   /* position reporting */
4344   if (qtdemux->segment.rate >= 0) {
4345     qtdemux->segment.position = position;
4346     gst_qtdemux_sync_streams (qtdemux);
4347   }
4348
4349   if (G_UNLIKELY (!stream->pad)) {
4350     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
4351     gst_buffer_unref (buf);
4352     goto exit;
4353   }
4354
4355   /* send out pending buffers */
4356   while (stream->buffers) {
4357     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
4358
4359     if (G_UNLIKELY (stream->discont)) {
4360       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
4361       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
4362       stream->discont = FALSE;
4363     } else {
4364       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
4365     }
4366
4367     gst_pad_push (stream->pad, buffer);
4368
4369     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
4370   }
4371
4372   /* we're going to modify the metadata */
4373   buf = gst_buffer_make_writable (buf);
4374
4375   if (G_UNLIKELY (stream->need_process))
4376     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
4377
4378   if (!buf) {
4379     goto exit;
4380   }
4381
4382   GST_BUFFER_DTS (buf) = dts;
4383   GST_BUFFER_PTS (buf) = pts;
4384   GST_BUFFER_DURATION (buf) = duration;
4385   GST_BUFFER_OFFSET (buf) = -1;
4386   GST_BUFFER_OFFSET_END (buf) = -1;
4387
4388   if (G_UNLIKELY (stream->rgb8_palette))
4389     gst_buffer_append_memory (buf, gst_memory_ref (stream->rgb8_palette));
4390
4391   if (G_UNLIKELY (stream->padding)) {
4392     gst_buffer_resize (buf, stream->padding, -1);
4393   }
4394 #if 0
4395   if (G_UNLIKELY (qtdemux->element_index)) {
4396     GstClockTime stream_time;
4397
4398     stream_time =
4399         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
4400         timestamp);
4401     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
4402       GST_LOG_OBJECT (qtdemux,
4403           "adding association %" GST_TIME_FORMAT "-> %"
4404           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
4405       gst_index_add_association (qtdemux->element_index,
4406           qtdemux->index_id,
4407           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
4408           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
4409           GST_FORMAT_BYTES, byte_position, NULL);
4410     }
4411   }
4412 #endif
4413
4414   if (stream->need_clip)
4415     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
4416
4417   if (G_UNLIKELY (buf == NULL))
4418     goto exit;
4419
4420   if (G_UNLIKELY (stream->discont)) {
4421     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
4422     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
4423     stream->discont = FALSE;
4424   } else {
4425     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
4426   }
4427
4428   if (!keyframe) {
4429     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
4430     stream->on_keyframe = FALSE;
4431   } else {
4432     stream->on_keyframe = TRUE;
4433   }
4434
4435
4436   GST_LOG_OBJECT (qtdemux,
4437       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
4438       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
4439       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
4440       GST_PAD_NAME (stream->pad));
4441
4442   ret = gst_pad_push (stream->pad, buf);
4443
4444   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
4445     /* mark position in stream, we'll need this to know when to send GAP event */
4446     stream->segment.position = pts + duration;
4447   }
4448
4449 exit:
4450   return ret;
4451 }
4452
4453 static const QtDemuxRandomAccessEntry *
4454 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4455     GstClockTime pos, gboolean after)
4456 {
4457   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
4458   guint n_entries = stream->n_ra_entries;
4459   guint i;
4460
4461   /* we assume the table is sorted */
4462   for (i = 0; i < n_entries; ++i) {
4463     if (entries[i].ts > pos)
4464       break;
4465   }
4466
4467   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
4468    * probably okay to assume that the index lists the very first fragment */
4469   if (i == 0)
4470     return &entries[0];
4471
4472   if (after)
4473     return &entries[i];
4474   else
4475     return &entries[i - 1];
4476 }
4477
4478 static gboolean
4479 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
4480 {
4481   const QtDemuxRandomAccessEntry *best_entry = NULL;
4482   guint i;
4483
4484   GST_OBJECT_LOCK (qtdemux);
4485
4486   g_assert (qtdemux->n_streams > 0);
4487
4488   for (i = 0; i < qtdemux->n_streams; i++) {
4489     const QtDemuxRandomAccessEntry *entry;
4490     QtDemuxStream *stream;
4491     gboolean is_audio_or_video;
4492
4493     stream = qtdemux->streams[i];
4494
4495     g_free (stream->samples);
4496     stream->samples = NULL;
4497     stream->n_samples = 0;
4498     stream->stbl_index = -1;    /* no samples have yet been parsed */
4499     stream->sample_index = -1;
4500
4501     if (stream->ra_entries == NULL)
4502       continue;
4503
4504     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
4505       is_audio_or_video = TRUE;
4506     else
4507       is_audio_or_video = FALSE;
4508
4509     entry =
4510         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
4511         stream->time_position, !is_audio_or_video);
4512
4513     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
4514         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
4515
4516     stream->pending_seek = entry;
4517
4518     /* decide position to jump to just based on audio/video tracks, not subs */
4519     if (!is_audio_or_video)
4520       continue;
4521
4522     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
4523       best_entry = entry;
4524   }
4525
4526   if (best_entry == NULL) {
4527     GST_OBJECT_UNLOCK (qtdemux);
4528     return FALSE;
4529   }
4530
4531   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
4532       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
4533       GST_TIME_ARGS (qtdemux->streams[0]->time_position),
4534       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
4535
4536   qtdemux->moof_offset = best_entry->moof_offset;
4537
4538   qtdemux_add_fragmented_samples (qtdemux);
4539
4540   GST_OBJECT_UNLOCK (qtdemux);
4541   return TRUE;
4542 }
4543
4544 static GstFlowReturn
4545 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
4546 {
4547   GstFlowReturn ret = GST_FLOW_OK;
4548   GstBuffer *buf = NULL;
4549   QtDemuxStream *stream;
4550   GstClockTime min_time;
4551   guint64 offset = 0;
4552   GstClockTime dts = GST_CLOCK_TIME_NONE;
4553   GstClockTime pts = GST_CLOCK_TIME_NONE;
4554   GstClockTime duration = 0;
4555   gboolean keyframe = FALSE;
4556   guint sample_size = 0;
4557   gboolean empty = 0;
4558   guint size;
4559   gint index;
4560   gint i;
4561
4562   gst_qtdemux_push_pending_newsegment (qtdemux);
4563
4564   if (qtdemux->fragmented_seek_pending) {
4565     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
4566     gst_qtdemux_do_fragmented_seek (qtdemux);
4567     GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
4568     qtdemux->fragmented_seek_pending = FALSE;
4569   }
4570
4571   /* Figure out the next stream sample to output, min_time is expressed in
4572    * global time and runs over the edit list segments. */
4573   min_time = G_MAXUINT64;
4574   index = -1;
4575   for (i = 0; i < qtdemux->n_streams; i++) {
4576     GstClockTime position;
4577
4578     stream = qtdemux->streams[i];
4579     position = stream->time_position;
4580
4581     /* position of -1 is EOS */
4582     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
4583       min_time = position;
4584       index = i;
4585     }
4586   }
4587   /* all are EOS */
4588   if (G_UNLIKELY (index == -1)) {
4589     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
4590     goto eos;
4591   }
4592
4593   /* check for segment end */
4594   if (G_UNLIKELY (qtdemux->segment.stop != -1
4595           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
4596               || (qtdemux->segment.rate < 0
4597                   && qtdemux->segment.start > min_time))
4598           && qtdemux->streams[index]->on_keyframe)) {
4599     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
4600     qtdemux->streams[index]->time_position = GST_CLOCK_TIME_NONE;
4601     goto eos_stream;
4602   }
4603
4604   /* gap events for subtitle streams */
4605   for (i = 0; i < qtdemux->n_streams; i++) {
4606     stream = qtdemux->streams[i];
4607     if (stream->pad && (stream->subtype == FOURCC_subp
4608             || stream->subtype == FOURCC_text
4609             || stream->subtype == FOURCC_sbtl)) {
4610       /* send one second gap events until the stream catches up */
4611       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
4612       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
4613           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
4614           stream->segment.position + GST_SECOND < min_time) {
4615         GstEvent *gap =
4616             gst_event_new_gap (stream->segment.position, GST_SECOND);
4617         gst_pad_push_event (stream->pad, gap);
4618         stream->segment.position += GST_SECOND;
4619       }
4620     }
4621   }
4622
4623   stream = qtdemux->streams[index];
4624   if (stream->new_caps) {
4625     gst_qtdemux_configure_stream (qtdemux, stream);
4626     qtdemux_do_allocation (qtdemux, stream);
4627   }
4628
4629   /* fetch info for the current sample of this stream */
4630   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
4631               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
4632     goto eos_stream;
4633
4634   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
4635   if (G_UNLIKELY (qtdemux->
4636           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
4637     if (stream->subtype == FOURCC_vide && !keyframe) {
4638       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on stream %d", index);
4639       goto next;
4640     }
4641   }
4642
4643   GST_DEBUG_OBJECT (qtdemux,
4644       "pushing from stream %d, empty %d offset %" G_GUINT64_FORMAT
4645       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
4646       ", duration %" GST_TIME_FORMAT, index, empty, offset, sample_size,
4647       GST_TIME_ARGS (dts), GST_TIME_ARGS (pts), GST_TIME_ARGS (duration));
4648
4649   if (G_UNLIKELY (empty)) {
4650     /* empty segment, push a gap and move to the next one */
4651     gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
4652     stream->segment.position = pts + duration;
4653     goto next;
4654   }
4655
4656   /* hmm, empty sample, skip and move to next sample */
4657   if (G_UNLIKELY (sample_size <= 0))
4658     goto next;
4659
4660   /* last pushed sample was out of boundary, goto next sample */
4661   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
4662     goto next;
4663
4664   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
4665     size = sample_size;
4666   } else {
4667     GST_DEBUG_OBJECT (qtdemux,
4668         "size %d larger than stream max_buffer_size %d, trimming",
4669         sample_size, stream->max_buffer_size);
4670     size =
4671         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
4672   }
4673
4674   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
4675       offset);
4676
4677   if (stream->use_allocator) {
4678     /* if we have a per-stream allocator, use it */
4679     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
4680   }
4681
4682   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
4683       size, &buf);
4684   if (G_UNLIKELY (ret != GST_FLOW_OK))
4685     goto beach;
4686
4687   if (size != sample_size) {
4688     pts += gst_util_uint64_scale_int (GST_SECOND,
4689         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
4690     dts += gst_util_uint64_scale_int (GST_SECOND,
4691         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
4692     duration = gst_util_uint64_scale_int (GST_SECOND,
4693         size / stream->bytes_per_frame, stream->timescale);
4694   }
4695
4696   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
4697       dts, pts, duration, keyframe, min_time, offset);
4698
4699   if (size != sample_size) {
4700     QtDemuxSample *sample = &stream->samples[stream->sample_index];
4701     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
4702
4703     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
4704         sample->timestamp + stream->offset_in_sample / stream->bytes_per_frame);
4705     if (time_position >= segment->media_start) {
4706       /* inside the segment, update time_position, looks very familiar to
4707        * GStreamer segments, doesn't it? */
4708       stream->time_position = (time_position - segment->media_start) +
4709           segment->time;
4710     } else {
4711       /* not yet in segment, time does not yet increment. This means
4712        * that we are still prerolling keyframes to the decoder so it can
4713        * decode the first sample of the segment. */
4714       stream->time_position = segment->time;
4715     }
4716   }
4717
4718   /* combine flows */
4719   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
4720   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
4721    * we have no more data for the pad to push */
4722   if (ret == GST_FLOW_EOS)
4723     ret = GST_FLOW_OK;
4724
4725   stream->offset_in_sample += size;
4726   if (stream->offset_in_sample >= sample_size) {
4727     gst_qtdemux_advance_sample (qtdemux, stream);
4728   }
4729   goto beach;
4730
4731 next:
4732   gst_qtdemux_advance_sample (qtdemux, stream);
4733
4734 beach:
4735   return ret;
4736
4737   /* special cases */
4738 eos:
4739   {
4740     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
4741     ret = GST_FLOW_EOS;
4742     goto beach;
4743   }
4744 eos_stream:
4745   {
4746     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
4747     /* EOS will be raised if all are EOS */
4748     ret = GST_FLOW_OK;
4749     goto beach;
4750   }
4751 }
4752
4753 static void
4754 gst_qtdemux_loop (GstPad * pad)
4755 {
4756   GstQTDemux *qtdemux;
4757   guint64 cur_offset;
4758   GstFlowReturn ret;
4759
4760   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
4761
4762   cur_offset = qtdemux->offset;
4763   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %d",
4764       cur_offset, qtdemux->state);
4765
4766   switch (qtdemux->state) {
4767     case QTDEMUX_STATE_INITIAL:
4768     case QTDEMUX_STATE_HEADER:
4769       ret = gst_qtdemux_loop_state_header (qtdemux);
4770       break;
4771     case QTDEMUX_STATE_MOVIE:
4772       ret = gst_qtdemux_loop_state_movie (qtdemux);
4773       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
4774         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
4775       }
4776       break;
4777     default:
4778       /* ouch */
4779       goto invalid_state;
4780   }
4781
4782   /* if something went wrong, pause */
4783   if (ret != GST_FLOW_OK)
4784     goto pause;
4785
4786 done:
4787   gst_object_unref (qtdemux);
4788   return;
4789
4790   /* ERRORS */
4791 invalid_state:
4792   {
4793     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
4794         (NULL), ("streaming stopped, invalid state"));
4795     gst_pad_pause_task (pad);
4796     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
4797     goto done;
4798   }
4799 pause:
4800   {
4801     const gchar *reason = gst_flow_get_name (ret);
4802
4803     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
4804
4805     gst_pad_pause_task (pad);
4806
4807     /* fatal errors need special actions */
4808     /* check EOS */
4809     if (ret == GST_FLOW_EOS) {
4810       if (qtdemux->n_streams == 0) {
4811         /* we have no streams, post an error */
4812         gst_qtdemux_post_no_playable_stream_error (qtdemux);
4813       }
4814       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
4815         gint64 stop;
4816
4817         if ((stop = qtdemux->segment.stop) == -1)
4818           stop = qtdemux->segment.duration;
4819
4820         if (qtdemux->segment.rate >= 0) {
4821           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
4822           gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
4823               gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
4824                   GST_FORMAT_TIME, stop));
4825           gst_qtdemux_push_event (qtdemux,
4826               gst_event_new_segment_done (GST_FORMAT_TIME, stop));
4827         } else {
4828           /*  For Reverse Playback */
4829           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
4830           gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
4831               gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
4832                   GST_FORMAT_TIME, qtdemux->segment.start));
4833           gst_qtdemux_push_event (qtdemux,
4834               gst_event_new_segment_done (GST_FORMAT_TIME,
4835                   qtdemux->segment.start));
4836         }
4837       } else {
4838         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
4839         gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
4840       }
4841     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
4842       GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
4843           (NULL), ("streaming stopped, reason %s", reason));
4844       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
4845     }
4846     goto done;
4847   }
4848 }
4849
4850 /*
4851  * has_next_entry
4852  *
4853  * Returns if there are samples to be played.
4854  */
4855 static gboolean
4856 has_next_entry (GstQTDemux * demux)
4857 {
4858   QtDemuxStream *stream;
4859   int i;
4860
4861   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
4862
4863   for (i = 0; i < demux->n_streams; i++) {
4864     stream = demux->streams[i];
4865
4866     if (stream->sample_index == -1) {
4867       stream->sample_index = 0;
4868       stream->offset_in_sample = 0;
4869     }
4870
4871     if (stream->sample_index >= stream->n_samples) {
4872       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
4873       continue;
4874     }
4875     GST_DEBUG_OBJECT (demux, "Found a sample");
4876     return TRUE;
4877   }
4878
4879   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
4880   return FALSE;
4881 }
4882
4883 /*
4884  * next_entry_size
4885  *
4886  * Returns the size of the first entry at the current offset.
4887  * If -1, there are none (which means EOS or empty file).
4888  */
4889 static guint64
4890 next_entry_size (GstQTDemux * demux)
4891 {
4892   QtDemuxStream *stream;
4893   int i;
4894   int smallidx = -1;
4895   guint64 smalloffs = (guint64) - 1;
4896   QtDemuxSample *sample;
4897
4898   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
4899       demux->offset);
4900
4901   for (i = 0; i < demux->n_streams; i++) {
4902     stream = demux->streams[i];
4903
4904     if (stream->sample_index == -1) {
4905       stream->sample_index = 0;
4906       stream->offset_in_sample = 0;
4907     }
4908
4909     if (stream->sample_index >= stream->n_samples) {
4910       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
4911       continue;
4912     }
4913
4914     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
4915       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
4916           stream->sample_index);
4917       return -1;
4918     }
4919
4920     sample = &stream->samples[stream->sample_index];
4921
4922     GST_LOG_OBJECT (demux,
4923         "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
4924         " / size:%" G_GUINT32_FORMAT ")", i, stream->sample_index,
4925         sample->offset, sample->size);
4926
4927     if (((smalloffs == -1)
4928             || (sample->offset < smalloffs)) && (sample->size)) {
4929       smallidx = i;
4930       smalloffs = sample->offset;
4931     }
4932   }
4933
4934   GST_LOG_OBJECT (demux,
4935       "stream %d offset %" G_GUINT64_FORMAT " demux->offset :%"
4936       G_GUINT64_FORMAT, smallidx, smalloffs, demux->offset);
4937
4938   if (smallidx == -1)
4939     return -1;
4940
4941   stream = demux->streams[smallidx];
4942   sample = &stream->samples[stream->sample_index];
4943
4944   if (sample->offset >= demux->offset) {
4945     demux->todrop = sample->offset - demux->offset;
4946     return sample->size + demux->todrop;
4947   }
4948
4949   GST_DEBUG_OBJECT (demux,
4950       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
4951   return -1;
4952 }
4953
4954 static void
4955 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
4956 {
4957   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
4958
4959   gst_element_post_message (GST_ELEMENT_CAST (demux),
4960       gst_message_new_element (GST_OBJECT_CAST (demux),
4961           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
4962 }
4963
4964 static gboolean
4965 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
4966 {
4967   GstEvent *event;
4968   gboolean res = 0;
4969
4970   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
4971
4972   event =
4973       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
4974       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
4975       GST_SEEK_TYPE_NONE, -1);
4976
4977   res = gst_pad_push_event (demux->sinkpad, event);
4978
4979   return res;
4980 }
4981
4982 /* check for seekable upstream, above and beyond a mere query */
4983 static void
4984 gst_qtdemux_check_seekability (GstQTDemux * demux)
4985 {
4986   GstQuery *query;
4987   gboolean seekable = FALSE;
4988   gint64 start = -1, stop = -1;
4989
4990   if (demux->upstream_size)
4991     return;
4992
4993   query = gst_query_new_seeking (GST_FORMAT_BYTES);
4994   if (!gst_pad_peer_query (demux->sinkpad, query)) {
4995     GST_DEBUG_OBJECT (demux, "seeking query failed");
4996     goto done;
4997   }
4998
4999   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
5000
5001   /* try harder to query upstream size if we didn't get it the first time */
5002   if (seekable && stop == -1) {
5003     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
5004     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
5005   }
5006
5007   /* if upstream doesn't know the size, it's likely that it's not seekable in
5008    * practice even if it technically may be seekable */
5009   if (seekable && (start != 0 || stop <= start)) {
5010     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
5011     seekable = FALSE;
5012   }
5013
5014 done:
5015   gst_query_unref (query);
5016
5017   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
5018       G_GUINT64_FORMAT ")", seekable, start, stop);
5019   demux->upstream_seekable = seekable;
5020   demux->upstream_size = seekable ? stop : -1;
5021 }
5022
5023 static void
5024 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
5025 {
5026   g_return_if_fail (bytes <= demux->todrop);
5027
5028   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
5029   gst_adapter_flush (demux->adapter, bytes);
5030   demux->neededbytes -= bytes;
5031   demux->offset += bytes;
5032   demux->todrop -= bytes;
5033 }
5034
5035 static GstFlowReturn
5036 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
5037 {
5038   GstQTDemux *demux;
5039
5040   demux = GST_QTDEMUX (parent);
5041
5042   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
5043     gint i;
5044
5045     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
5046
5047     for (i = 0; i < demux->n_streams; i++) {
5048       demux->streams[i]->discont = TRUE;
5049     }
5050
5051     /* Reverse fragmented playback, need to flush all we have before
5052      * consuming a new fragment.
5053      * The samples array have the timestamps calculated by accumulating the
5054      * durations but this won't work for reverse playback of fragments as
5055      * the timestamps of a subsequent fragment should be smaller than the
5056      * previously received one. */
5057     if (demux->fragmented && demux->segment.rate < 0) {
5058       gst_qtdemux_process_adapter (demux, TRUE);
5059       for (i = 0; i < demux->n_streams; i++)
5060         gst_qtdemux_stream_flush_samples_data (demux, demux->streams[i]);
5061     }
5062   }
5063
5064   gst_adapter_push (demux->adapter, inbuf);
5065
5066   GST_DEBUG_OBJECT (demux,
5067       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
5068       demux->neededbytes, gst_adapter_available (demux->adapter));
5069
5070   return gst_qtdemux_process_adapter (demux, FALSE);
5071 }
5072
5073 static GstFlowReturn
5074 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
5075 {
5076   GstFlowReturn ret = GST_FLOW_OK;
5077
5078   /* we never really mean to buffer that much */
5079   if (demux->neededbytes == -1) {
5080     goto eos;
5081   }
5082
5083   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
5084       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
5085
5086     GST_DEBUG_OBJECT (demux,
5087         "state:%d , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT,
5088         demux->state, demux->neededbytes, demux->offset);
5089
5090     switch (demux->state) {
5091       case QTDEMUX_STATE_INITIAL:{
5092         const guint8 *data;
5093         guint32 fourcc;
5094         guint64 size;
5095
5096         gst_qtdemux_check_seekability (demux);
5097
5098         data = gst_adapter_map (demux->adapter, demux->neededbytes);
5099
5100         /* get fourcc/length, set neededbytes */
5101         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
5102             &size, &fourcc);
5103         gst_adapter_unmap (demux->adapter);
5104         data = NULL;
5105         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
5106             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
5107         if (size == 0) {
5108           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
5109               (_("This file is invalid and cannot be played.")),
5110               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
5111                   GST_FOURCC_ARGS (fourcc)));
5112           ret = GST_FLOW_ERROR;
5113           break;
5114         }
5115         if (fourcc == FOURCC_mdat) {
5116           gint next_entry = next_entry_size (demux);
5117           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
5118             /* we have the headers, start playback */
5119             demux->state = QTDEMUX_STATE_MOVIE;
5120             demux->neededbytes = next_entry;
5121             demux->mdatleft = size;
5122           } else {
5123             /* no headers yet, try to get them */
5124             guint bs;
5125             gboolean res;
5126             guint64 old, target;
5127
5128           buffer_data:
5129             old = demux->offset;
5130             target = old + size;
5131
5132             /* try to jump over the atom with a seek */
5133             /* only bother if it seems worth doing so,
5134              * and avoids possible upstream/server problems */
5135             if (demux->upstream_seekable &&
5136                 demux->upstream_size > 4 * (1 << 20)) {
5137               res = qtdemux_seek_offset (demux, target);
5138             } else {
5139               GST_DEBUG_OBJECT (demux, "skipping seek");
5140               res = FALSE;
5141             }
5142
5143             if (res) {
5144               GST_DEBUG_OBJECT (demux, "seek success");
5145               /* remember the offset fo the first mdat so we can seek back to it
5146                * after we have the headers */
5147               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
5148                 demux->first_mdat = old;
5149                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
5150                     demux->first_mdat);
5151               }
5152               /* seek worked, continue reading */
5153               demux->offset = target;
5154               demux->neededbytes = 16;
5155               demux->state = QTDEMUX_STATE_INITIAL;
5156             } else {
5157               /* seek failed, need to buffer */
5158               demux->offset = old;
5159               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
5160               /* there may be multiple mdat (or alike) buffers */
5161               /* sanity check */
5162               if (demux->mdatbuffer)
5163                 bs = gst_buffer_get_size (demux->mdatbuffer);
5164               else
5165                 bs = 0;
5166               if (size + bs > 10 * (1 << 20))
5167                 goto no_moov;
5168               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
5169               demux->neededbytes = size;
5170               if (!demux->mdatbuffer)
5171                 demux->mdatoffset = demux->offset;
5172             }
5173           }
5174         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
5175           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
5176               (_("This file is invalid and cannot be played.")),
5177               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
5178                   GST_FOURCC_ARGS (fourcc), size));
5179           ret = GST_FLOW_ERROR;
5180           break;
5181         } else {
5182           /* this means we already started buffering and still no moov header,
5183            * let's continue buffering everything till we get moov */
5184           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
5185                   || fourcc == FOURCC_moof))
5186             goto buffer_data;
5187           demux->neededbytes = size;
5188           demux->state = QTDEMUX_STATE_HEADER;
5189         }
5190         break;
5191       }
5192       case QTDEMUX_STATE_HEADER:{
5193         const guint8 *data;
5194         guint32 fourcc;
5195
5196         GST_DEBUG_OBJECT (demux, "In header");
5197
5198         data = gst_adapter_map (demux->adapter, demux->neededbytes);
5199
5200         /* parse the header */
5201         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
5202             &fourcc);
5203         if (fourcc == FOURCC_moov) {
5204           /* in usual fragmented setup we could try to scan for more
5205            * and end up at the the moov (after mdat) again */
5206           if (demux->got_moov && demux->n_streams > 0 &&
5207               (!demux->fragmented
5208                   || demux->last_moov_offset == demux->offset)) {
5209             GST_DEBUG_OBJECT (demux,
5210                 "Skipping moov atom as we have (this) one already");
5211           } else {
5212             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
5213
5214             if (demux->got_moov && demux->fragmented) {
5215               GST_DEBUG_OBJECT (demux,
5216                   "Got a second moov, clean up data from old one");
5217               if (demux->moov_node)
5218                 g_node_destroy (demux->moov_node);
5219               demux->moov_node = NULL;
5220               demux->moov_node_compressed = NULL;
5221             } else {
5222               /* prepare newsegment to send when streaming actually starts */
5223               if (!demux->pending_newsegment)
5224                 demux->pending_newsegment =
5225                     gst_event_new_segment (&demux->segment);
5226             }
5227
5228             demux->last_moov_offset = demux->offset;
5229
5230             qtdemux_parse_moov (demux, data, demux->neededbytes);
5231             qtdemux_node_dump (demux, demux->moov_node);
5232             qtdemux_parse_tree (demux);
5233             qtdemux_prepare_streams (demux);
5234             if (!demux->got_moov)
5235               qtdemux_expose_streams (demux);
5236             else {
5237               gint n;
5238
5239               for (n = 0; n < demux->n_streams; n++) {
5240                 QtDemuxStream *stream = demux->streams[n];
5241
5242                 gst_qtdemux_configure_stream (demux, stream);
5243               }
5244             }
5245
5246             demux->got_moov = TRUE;
5247
5248             g_node_destroy (demux->moov_node);
5249             demux->moov_node = NULL;
5250             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
5251           }
5252         } else if (fourcc == FOURCC_moof) {
5253           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
5254             guint64 dist = 0;
5255             GstClockTime prev_pts;
5256             guint64 prev_offset;
5257
5258             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
5259
5260             /*
5261              * The timestamp of the moof buffer is relevant as some scenarios
5262              * won't have the initial timestamp in the atoms. Whenever a new
5263              * buffer has started, we get that buffer's PTS and use it as a base
5264              * timestamp for the trun entries.
5265              *
5266              * To keep track of the current buffer timestamp and starting point
5267              * we use gst_adapter_prev_pts that gives us the PTS and the distance
5268              * from the beggining of the buffer, with the distance and demux->offset
5269              * we know if it is still the same buffer or not.
5270              */
5271             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
5272             prev_offset = demux->offset - dist;
5273             if (demux->fragment_start_offset == -1
5274                 || prev_offset > demux->fragment_start_offset) {
5275               demux->fragment_start_offset = prev_offset;
5276               demux->fragment_start = prev_pts;
5277               GST_DEBUG_OBJECT (demux,
5278                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
5279                   GST_TIME_FORMAT, demux->fragment_start_offset,
5280                   GST_TIME_ARGS (demux->fragment_start));
5281             }
5282
5283             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
5284                     demux->offset, NULL)) {
5285               gst_adapter_unmap (demux->adapter);
5286               ret = GST_FLOW_ERROR;
5287               goto done;
5288             }
5289             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
5290             if (demux->mss_mode && !demux->exposed) {
5291               if (!demux->pending_newsegment) {
5292                 GstSegment segment;
5293                 gst_segment_init (&segment, GST_FORMAT_TIME);
5294                 GST_DEBUG_OBJECT (demux, "new pending_newsegment");
5295                 demux->pending_newsegment = gst_event_new_segment (&segment);
5296               }
5297               qtdemux_expose_streams (demux);
5298             }
5299           } else {
5300             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
5301           }
5302         } else if (fourcc == FOURCC_ftyp) {
5303           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
5304           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
5305         } else if (fourcc == FOURCC_uuid) {
5306           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
5307           qtdemux_parse_uuid (demux, data, demux->neededbytes);
5308         } else if (fourcc == FOURCC_sidx) {
5309           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
5310           qtdemux_parse_sidx (demux, data, demux->neededbytes);
5311         } else {
5312           GST_WARNING_OBJECT (demux,
5313               "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
5314               GST_FOURCC_ARGS (fourcc));
5315           /* Let's jump that one and go back to initial state */
5316         }
5317         gst_adapter_unmap (demux->adapter);
5318         data = NULL;
5319
5320         if (demux->mdatbuffer && demux->n_streams) {
5321           gsize remaining_data_size = 0;
5322
5323           /* the mdat was before the header */
5324           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
5325               demux->n_streams, demux->mdatbuffer);
5326           /* restore our adapter/offset view of things with upstream;
5327            * put preceding buffered data ahead of current moov data.
5328            * This should also handle evil mdat, moov, mdat cases and alike */
5329           gst_adapter_flush (demux->adapter, demux->neededbytes);
5330
5331           /* Store any remaining data after the mdat for later usage */
5332           remaining_data_size = gst_adapter_available (demux->adapter);
5333           if (remaining_data_size > 0) {
5334             g_assert (demux->restoredata_buffer == NULL);
5335             demux->restoredata_buffer =
5336                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
5337             demux->restoredata_offset = demux->offset + demux->neededbytes;
5338             GST_DEBUG_OBJECT (demux,
5339                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
5340                 G_GUINT64_FORMAT, remaining_data_size,
5341                 demux->restoredata_offset);
5342           }
5343
5344           gst_adapter_push (demux->adapter, demux->mdatbuffer);
5345           demux->mdatbuffer = NULL;
5346           demux->offset = demux->mdatoffset;
5347           demux->neededbytes = next_entry_size (demux);
5348           demux->state = QTDEMUX_STATE_MOVIE;
5349           demux->mdatleft = gst_adapter_available (demux->adapter);
5350         } else {
5351           GST_DEBUG_OBJECT (demux, "Carrying on normally");
5352           gst_adapter_flush (demux->adapter, demux->neededbytes);
5353
5354           /* only go back to the mdat if there are samples to play */
5355           if (demux->got_moov && demux->first_mdat != -1
5356               && has_next_entry (demux)) {
5357             gboolean res;
5358
5359             /* we need to seek back */
5360             res = qtdemux_seek_offset (demux, demux->first_mdat);
5361             if (res) {
5362               demux->offset = demux->first_mdat;
5363             } else {
5364               GST_DEBUG_OBJECT (demux, "Seek back failed");
5365             }
5366           } else {
5367             demux->offset += demux->neededbytes;
5368           }
5369           demux->neededbytes = 16;
5370           demux->state = QTDEMUX_STATE_INITIAL;
5371         }
5372
5373         break;
5374       }
5375       case QTDEMUX_STATE_BUFFER_MDAT:{
5376         GstBuffer *buf;
5377         guint8 fourcc[4];
5378
5379         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
5380             demux->offset);
5381         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
5382         gst_buffer_extract (buf, 0, fourcc, 4);
5383         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
5384             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
5385         if (demux->mdatbuffer)
5386           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
5387         else
5388           demux->mdatbuffer = buf;
5389         demux->offset += demux->neededbytes;
5390         demux->neededbytes = 16;
5391         demux->state = QTDEMUX_STATE_INITIAL;
5392         gst_qtdemux_post_progress (demux, 1, 1);
5393
5394         break;
5395       }
5396       case QTDEMUX_STATE_MOVIE:{
5397         QtDemuxStream *stream = NULL;
5398         QtDemuxSample *sample;
5399         int i = -1;
5400         GstClockTime dts, pts, duration;
5401         gboolean keyframe;
5402
5403         GST_DEBUG_OBJECT (demux,
5404             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
5405
5406         if (demux->fragmented) {
5407           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
5408               demux->mdatleft);
5409           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
5410             /* if needed data starts within this atom,
5411              * then it should not exceed this atom */
5412             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
5413               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
5414                   (_("This file is invalid and cannot be played.")),
5415                   ("sample data crosses atom boundary"));
5416               ret = GST_FLOW_ERROR;
5417               break;
5418             }
5419             demux->mdatleft -= demux->neededbytes;
5420           } else {
5421             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
5422             /* so we are dropping more than left in this atom */
5423             gst_qtdemux_drop_data (demux, demux->mdatleft);
5424             demux->mdatleft = 0;
5425
5426             /* need to resume atom parsing so we do not miss any other pieces */
5427             demux->state = QTDEMUX_STATE_INITIAL;
5428             demux->neededbytes = 16;
5429
5430             /* check if there was any stored post mdat data from previous buffers */
5431             if (demux->restoredata_buffer) {
5432               g_assert (gst_adapter_available (demux->adapter) == 0);
5433
5434               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
5435               demux->restoredata_buffer = NULL;
5436               demux->offset = demux->restoredata_offset;
5437             }
5438
5439             break;
5440           }
5441         }
5442
5443         if (demux->todrop) {
5444           gst_qtdemux_drop_data (demux, demux->todrop);
5445         }
5446
5447         /* first buffer? */
5448         /* initial newsegment sent here after having added pads,
5449          * possible others in sink_event */
5450         if (G_UNLIKELY (demux->pending_newsegment)) {
5451           gst_qtdemux_push_pending_newsegment (demux);
5452           /* clear to send tags on all streams */
5453           for (i = 0; i < demux->n_streams; i++) {
5454             stream = demux->streams[i];
5455             gst_qtdemux_push_tags (demux, stream);
5456             if (stream->sparse) {
5457               GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
5458               gst_pad_push_event (stream->pad,
5459                   gst_event_new_gap (stream->segment.position,
5460                       GST_CLOCK_TIME_NONE));
5461             }
5462           }
5463         }
5464
5465         /* Figure out which stream this packet belongs to */
5466         for (i = 0; i < demux->n_streams; i++) {
5467           stream = demux->streams[i];
5468           if (stream->sample_index >= stream->n_samples)
5469             continue;
5470           GST_LOG_OBJECT (demux,
5471               "Checking stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
5472               " / size:%d)", i, stream->sample_index,
5473               stream->samples[stream->sample_index].offset,
5474               stream->samples[stream->sample_index].size);
5475
5476           if (stream->samples[stream->sample_index].offset == demux->offset)
5477             break;
5478         }
5479
5480         if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
5481           goto unknown_stream;
5482
5483         if (stream->new_caps) {
5484           gst_qtdemux_configure_stream (demux, stream);
5485         }
5486
5487         /* Put data in a buffer, set timestamps, caps, ... */
5488         sample = &stream->samples[stream->sample_index];
5489
5490         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
5491           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
5492               GST_FOURCC_ARGS (stream->fourcc));
5493
5494           dts = QTSAMPLE_DTS (stream, sample);
5495           pts = QTSAMPLE_PTS (stream, sample);
5496           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
5497           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5498
5499           /* check for segment end */
5500           if (G_UNLIKELY (demux->segment.stop != -1
5501                   && demux->segment.stop <= pts && stream->on_keyframe)) {
5502             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
5503             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
5504
5505             /* skip this data, stream is EOS */
5506             gst_adapter_flush (demux->adapter, demux->neededbytes);
5507
5508             /* check if all streams are eos */
5509             ret = GST_FLOW_EOS;
5510             for (i = 0; i < demux->n_streams; i++) {
5511               if (!STREAM_IS_EOS (demux->streams[i])) {
5512                 ret = GST_FLOW_OK;
5513                 break;
5514               }
5515             }
5516
5517             if (ret == GST_FLOW_EOS) {
5518               GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
5519               goto eos;
5520             }
5521           } else {
5522             GstBuffer *outbuf;
5523
5524             outbuf =
5525                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
5526
5527             /* FIXME: should either be an assert or a plain check */
5528             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
5529
5530             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
5531                 dts, pts, duration, keyframe, dts, demux->offset);
5532           }
5533
5534           /* combine flows */
5535           ret = gst_qtdemux_combine_flows (demux, stream, ret);
5536         } else {
5537           /* skip this data, stream is EOS */
5538           gst_adapter_flush (demux->adapter, demux->neededbytes);
5539         }
5540
5541         stream->sample_index++;
5542         stream->offset_in_sample = 0;
5543
5544         /* update current offset and figure out size of next buffer */
5545         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
5546             demux->offset, demux->neededbytes);
5547         demux->offset += demux->neededbytes;
5548         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
5549             demux->offset);
5550
5551         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
5552           if (demux->fragmented) {
5553             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
5554             /* there may be more to follow, only finish this atom */
5555             demux->todrop = demux->mdatleft;
5556             demux->neededbytes = demux->todrop;
5557             break;
5558           }
5559           goto eos;
5560         }
5561         break;
5562       }
5563       default:
5564         goto invalid_state;
5565     }
5566   }
5567
5568   /* when buffering movie data, at least show user something is happening */
5569   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
5570       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
5571     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
5572         demux->neededbytes);
5573   }
5574 done:
5575
5576   return ret;
5577
5578   /* ERRORS */
5579 unknown_stream:
5580   {
5581     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
5582     ret = GST_FLOW_ERROR;
5583     goto done;
5584   }
5585 eos:
5586   {
5587     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
5588     ret = GST_FLOW_EOS;
5589     goto done;
5590   }
5591 invalid_state:
5592   {
5593     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
5594         (NULL), ("qtdemuxer invalid state %d", demux->state));
5595     ret = GST_FLOW_ERROR;
5596     goto done;
5597   }
5598 no_moov:
5599   {
5600     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
5601         (NULL), ("no 'moov' atom within the first 10 MB"));
5602     ret = GST_FLOW_ERROR;
5603     goto done;
5604   }
5605 }
5606
5607 static gboolean
5608 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
5609 {
5610   GstQuery *query;
5611   gboolean pull_mode;
5612
5613   query = gst_query_new_scheduling ();
5614
5615   if (!gst_pad_peer_query (sinkpad, query)) {
5616     gst_query_unref (query);
5617     goto activate_push;
5618   }
5619
5620   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
5621       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
5622   gst_query_unref (query);
5623
5624   if (!pull_mode)
5625     goto activate_push;
5626
5627   GST_DEBUG_OBJECT (sinkpad, "activating pull");
5628   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
5629
5630 activate_push:
5631   {
5632     GST_DEBUG_OBJECT (sinkpad, "activating push");
5633     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
5634   }
5635 }
5636
5637 static gboolean
5638 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
5639     GstPadMode mode, gboolean active)
5640 {
5641   gboolean res;
5642   GstQTDemux *demux = GST_QTDEMUX (parent);
5643
5644   switch (mode) {
5645     case GST_PAD_MODE_PUSH:
5646       demux->pullbased = FALSE;
5647       res = TRUE;
5648       break;
5649     case GST_PAD_MODE_PULL:
5650       if (active) {
5651         demux->pullbased = TRUE;
5652         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
5653             sinkpad, NULL);
5654       } else {
5655         res = gst_pad_stop_task (sinkpad);
5656       }
5657       break;
5658     default:
5659       res = FALSE;
5660       break;
5661   }
5662   return res;
5663 }
5664
5665 #ifdef HAVE_ZLIB
5666 static void *
5667 qtdemux_zalloc (void *opaque, unsigned int items, unsigned int size)
5668 {
5669   return g_malloc (items * size);
5670 }
5671
5672 static void
5673 qtdemux_zfree (void *opaque, void *addr)
5674 {
5675   g_free (addr);
5676 }
5677
5678 static void *
5679 qtdemux_inflate (void *z_buffer, guint z_length, guint length)
5680 {
5681   guint8 *buffer;
5682   z_stream *z;
5683   int ret;
5684
5685   z = g_new0 (z_stream, 1);
5686   z->zalloc = qtdemux_zalloc;
5687   z->zfree = qtdemux_zfree;
5688   z->opaque = NULL;
5689
5690   z->next_in = z_buffer;
5691   z->avail_in = z_length;
5692
5693   buffer = (guint8 *) g_malloc (length);
5694   ret = inflateInit (z);
5695   while (z->avail_in > 0) {
5696     if (z->avail_out == 0) {
5697       length += 1024;
5698       buffer = (guint8 *) g_realloc (buffer, length);
5699       z->next_out = buffer + z->total_out;
5700       z->avail_out = 1024;
5701     }
5702     ret = inflate (z, Z_SYNC_FLUSH);
5703     if (ret != Z_OK)
5704       break;
5705   }
5706   if (ret != Z_STREAM_END) {
5707     g_warning ("inflate() returned %d", ret);
5708   }
5709
5710   g_free (z);
5711   return buffer;
5712 }
5713 #endif /* HAVE_ZLIB */
5714
5715 static gboolean
5716 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
5717 {
5718   GNode *cmov;
5719
5720   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
5721
5722   /* counts as header data */
5723   qtdemux->header_size += length;
5724
5725   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
5726   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
5727
5728   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
5729   if (cmov) {
5730     guint32 method;
5731     GNode *dcom;
5732     GNode *cmvd;
5733
5734     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
5735     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
5736     if (dcom == NULL || cmvd == NULL)
5737       goto invalid_compression;
5738
5739     method = QT_FOURCC ((guint8 *) dcom->data + 8);
5740     switch (method) {
5741 #ifdef HAVE_ZLIB
5742       case GST_MAKE_FOURCC ('z', 'l', 'i', 'b'):{
5743         guint uncompressed_length;
5744         guint compressed_length;
5745         guint8 *buf;
5746
5747         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
5748         compressed_length = QT_UINT32 ((guint8 *) cmvd->data + 4) - 12;
5749         GST_LOG ("length = %u", uncompressed_length);
5750
5751         buf =
5752             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
5753             compressed_length, uncompressed_length);
5754
5755         qtdemux->moov_node_compressed = qtdemux->moov_node;
5756         qtdemux->moov_node = g_node_new (buf);
5757
5758         qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
5759             uncompressed_length);
5760         break;
5761       }
5762 #endif /* HAVE_ZLIB */
5763       default:
5764         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
5765             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
5766         break;
5767     }
5768   }
5769   return TRUE;
5770
5771   /* ERRORS */
5772 invalid_compression:
5773   {
5774     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
5775     return FALSE;
5776   }
5777 }
5778
5779 static gboolean
5780 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
5781     const guint8 * end)
5782 {
5783   while (G_UNLIKELY (buf < end)) {
5784     GNode *child;
5785     guint32 len;
5786
5787     if (G_UNLIKELY (buf + 4 > end)) {
5788       GST_LOG_OBJECT (qtdemux, "buffer overrun");
5789       break;
5790     }
5791     len = QT_UINT32 (buf);
5792     if (G_UNLIKELY (len == 0)) {
5793       GST_LOG_OBJECT (qtdemux, "empty container");
5794       break;
5795     }
5796     if (G_UNLIKELY (len < 8)) {
5797       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
5798       break;
5799     }
5800     if (G_UNLIKELY (len > (end - buf))) {
5801       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
5802           (gint) (end - buf));
5803       break;
5804     }
5805
5806     child = g_node_new ((guint8 *) buf);
5807     g_node_append (node, child);
5808     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
5809     qtdemux_parse_node (qtdemux, child, buf, len);
5810
5811     buf += len;
5812   }
5813   return TRUE;
5814 }
5815
5816 static gboolean
5817 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
5818     GNode * xdxt)
5819 {
5820   int len = QT_UINT32 (xdxt->data);
5821   guint8 *buf = xdxt->data;
5822   guint8 *end = buf + len;
5823   GstBuffer *buffer;
5824
5825   /* skip size and type */
5826   buf += 8;
5827   end -= 8;
5828
5829   while (buf < end) {
5830     gint size;
5831     guint32 type;
5832
5833     size = QT_UINT32 (buf);
5834     type = QT_FOURCC (buf + 4);
5835
5836     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
5837
5838     if (buf + size > end || size <= 0)
5839       break;
5840
5841     buf += 8;
5842     size -= 8;
5843
5844     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
5845         GST_FOURCC_ARGS (type));
5846
5847     switch (type) {
5848       case FOURCC_tCtH:
5849         buffer = gst_buffer_new_and_alloc (size);
5850         gst_buffer_fill (buffer, 0, buf, size);
5851         stream->buffers = g_slist_append (stream->buffers, buffer);
5852         GST_LOG_OBJECT (qtdemux, "parsing theora header");
5853         break;
5854       case FOURCC_tCt_:
5855         buffer = gst_buffer_new_and_alloc (size);
5856         gst_buffer_fill (buffer, 0, buf, size);
5857         stream->buffers = g_slist_append (stream->buffers, buffer);
5858         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
5859         break;
5860       case FOURCC_tCtC:
5861         buffer = gst_buffer_new_and_alloc (size);
5862         gst_buffer_fill (buffer, 0, buf, size);
5863         stream->buffers = g_slist_append (stream->buffers, buffer);
5864         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
5865         break;
5866       default:
5867         GST_WARNING_OBJECT (qtdemux,
5868             "unknown theora cookie %" GST_FOURCC_FORMAT,
5869             GST_FOURCC_ARGS (type));
5870         break;
5871     }
5872     buf += size;
5873   }
5874   return TRUE;
5875 }
5876
5877 static gboolean
5878 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
5879     guint length)
5880 {
5881   guint32 fourcc = 0;
5882   guint32 node_length = 0;
5883   const QtNodeType *type;
5884   const guint8 *end;
5885
5886   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
5887
5888   if (G_UNLIKELY (length < 8))
5889     goto not_enough_data;
5890
5891   node_length = QT_UINT32 (buffer);
5892   fourcc = QT_FOURCC (buffer + 4);
5893
5894   /* ignore empty nodes */
5895   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
5896     return TRUE;
5897
5898   type = qtdemux_type_get (fourcc);
5899
5900   end = buffer + length;
5901
5902   GST_LOG_OBJECT (qtdemux,
5903       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
5904       GST_FOURCC_ARGS (fourcc), node_length, type->name);
5905
5906   if (node_length > length)
5907     goto broken_atom_size;
5908
5909   if (type->flags & QT_FLAG_CONTAINER) {
5910     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
5911   } else {
5912     switch (fourcc) {
5913       case FOURCC_stsd:
5914       {
5915         if (node_length < 20) {
5916           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
5917           break;
5918         }
5919         GST_DEBUG_OBJECT (qtdemux,
5920             "parsing stsd (sample table, sample description) atom");
5921         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
5922         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
5923         break;
5924       }
5925       case FOURCC_mp4a:
5926       case FOURCC_alac:
5927       {
5928         guint32 version;
5929         guint32 offset;
5930         guint min_size;
5931
5932         /* also read alac (or whatever) in stead of mp4a in the following,
5933          * since a similar layout is used in other cases as well */
5934         if (fourcc == FOURCC_mp4a)
5935           min_size = 20;
5936         else
5937           min_size = 40;
5938
5939         /* There are two things we might encounter here: a true mp4a atom, and
5940            an mp4a entry in an stsd atom. The latter is what we're interested
5941            in, and it looks like an atom, but isn't really one. The true mp4a
5942            atom is short, so we detect it based on length here. */
5943         if (length < min_size) {
5944           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
5945               GST_FOURCC_ARGS (fourcc));
5946           break;
5947         }
5948
5949         /* 'version' here is the sound sample description version. Types 0 and
5950            1 are documented in the QTFF reference, but type 2 is not: it's
5951            described in Apple header files instead (struct SoundDescriptionV2
5952            in Movies.h) */
5953         version = QT_UINT16 (buffer + 16);
5954
5955         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
5956             GST_FOURCC_ARGS (fourcc), version);
5957
5958         /* parse any esds descriptors */
5959         switch (version) {
5960           case 0:
5961             offset = 0x24;
5962             break;
5963           case 1:
5964             offset = 0x34;
5965             break;
5966           case 2:
5967             offset = 0x48;
5968             break;
5969           default:
5970             GST_WARNING_OBJECT (qtdemux,
5971                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
5972                 GST_FOURCC_ARGS (fourcc), version);
5973             offset = 0;
5974             break;
5975         }
5976         if (offset)
5977           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
5978         break;
5979       }
5980       case FOURCC_mp4v:
5981       case FOURCC_MP4V:
5982       case FOURCC_fmp4:
5983       case FOURCC_FMP4:
5984       case FOURCC_apcs:
5985       case FOURCC_apch:
5986       case FOURCC_apcn:
5987       case FOURCC_apco:
5988       case FOURCC_ap4h:
5989       {
5990         const guint8 *buf;
5991         guint32 version;
5992         int tlen;
5993
5994         /* codec_data is contained inside these atoms, which all have
5995          * the same format. */
5996
5997         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
5998             GST_FOURCC_ARGS (fourcc));
5999         version = QT_UINT32 (buffer + 16);
6000         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
6001         if (1 || version == 0x00000000) {
6002           buf = buffer + 0x32;
6003
6004           /* FIXME Quicktime uses PASCAL string while
6005            * the iso format uses C strings. Check the file
6006            * type before attempting to parse the string here. */
6007           tlen = QT_UINT8 (buf);
6008           GST_DEBUG_OBJECT (qtdemux, "tlen = %d", tlen);
6009           buf++;
6010           GST_DEBUG_OBJECT (qtdemux, "string = %.*s", tlen, (char *) buf);
6011           /* the string has a reserved space of 32 bytes so skip
6012            * the remaining 31 */
6013           buf += 31;
6014           buf += 4;             /* and 4 bytes reserved */
6015
6016           GST_MEMDUMP_OBJECT (qtdemux, "mp4v", buf, end - buf);
6017
6018           qtdemux_parse_container (qtdemux, node, buf, end);
6019         }
6020         break;
6021       }
6022       case FOURCC_H264:
6023       {
6024         GST_MEMDUMP_OBJECT (qtdemux, "H264", buffer, end - buffer);
6025         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6026         break;
6027       }
6028       case FOURCC_avc1:
6029       {
6030         GST_MEMDUMP_OBJECT (qtdemux, "avc1", buffer, end - buffer);
6031         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6032         break;
6033       }
6034       case FOURCC_avc3:
6035       {
6036         GST_MEMDUMP_OBJECT (qtdemux, "avc3", buffer, end - buffer);
6037         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6038         break;
6039       }
6040       case FOURCC_H265:
6041       {
6042         GST_MEMDUMP_OBJECT (qtdemux, "H265", buffer, end - buffer);
6043         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6044         break;
6045       }
6046       case FOURCC_hvc1:
6047       {
6048         GST_MEMDUMP_OBJECT (qtdemux, "hvc1", buffer, end - buffer);
6049         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6050         break;
6051       }
6052       case FOURCC_hev1:
6053       {
6054         GST_MEMDUMP_OBJECT (qtdemux, "hev1", buffer, end - buffer);
6055         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6056         break;
6057       }
6058       case FOURCC_mjp2:
6059       {
6060         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
6061         break;
6062       }
6063       case FOURCC_meta:
6064       {
6065         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
6066         qtdemux_parse_container (qtdemux, node, buffer + 12, end);
6067         break;
6068       }
6069       case FOURCC_mp4s:
6070       {
6071         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
6072         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
6073         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
6074         break;
6075       }
6076       case FOURCC_XiTh:
6077       {
6078         guint32 version;
6079         guint32 offset;
6080
6081         version = QT_UINT32 (buffer + 12);
6082         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
6083
6084         switch (version) {
6085           case 0x00000001:
6086             offset = 0x62;
6087             break;
6088           default:
6089             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
6090             offset = 0;
6091             break;
6092         }
6093         if (offset)
6094           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
6095         break;
6096       }
6097       case FOURCC_in24:
6098       {
6099         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
6100         break;
6101       }
6102       case FOURCC_uuid:
6103       {
6104         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
6105         break;
6106       }
6107       default:
6108         if (!strcmp (type->name, "unknown"))
6109           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
6110         break;
6111     }
6112   }
6113   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
6114       GST_FOURCC_ARGS (fourcc));
6115   return TRUE;
6116
6117 /* ERRORS */
6118 not_enough_data:
6119   {
6120     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
6121         (_("This file is corrupt and cannot be played.")),
6122         ("Not enough data for an atom header, got only %u bytes", length));
6123     return FALSE;
6124   }
6125 broken_atom_size:
6126   {
6127     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
6128         (_("This file is corrupt and cannot be played.")),
6129         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
6130             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
6131             length));
6132     return FALSE;
6133   }
6134 }
6135
6136 static GNode *
6137 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
6138 {
6139   GNode *child;
6140   guint8 *buffer;
6141   guint32 child_fourcc;
6142
6143   for (child = g_node_first_child (node); child;
6144       child = g_node_next_sibling (child)) {
6145     buffer = (guint8 *) child->data;
6146
6147     child_fourcc = QT_FOURCC (buffer + 4);
6148
6149     if (G_UNLIKELY (child_fourcc == fourcc)) {
6150       return child;
6151     }
6152   }
6153   return NULL;
6154 }
6155
6156 static GNode *
6157 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
6158     GstByteReader * parser)
6159 {
6160   GNode *child;
6161   guint8 *buffer;
6162   guint32 child_fourcc, child_len;
6163
6164   for (child = g_node_first_child (node); child;
6165       child = g_node_next_sibling (child)) {
6166     buffer = (guint8 *) child->data;
6167
6168     child_len = QT_UINT32 (buffer);
6169     child_fourcc = QT_FOURCC (buffer + 4);
6170
6171     if (G_UNLIKELY (child_fourcc == fourcc)) {
6172       if (G_UNLIKELY (child_len < (4 + 4)))
6173         return NULL;
6174       /* FIXME: must verify if atom length < parent atom length */
6175       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
6176       return child;
6177     }
6178   }
6179   return NULL;
6180 }
6181
6182 static GNode *
6183 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
6184     GstByteReader * parser)
6185 {
6186   GNode *child;
6187   guint8 *buffer;
6188   guint32 child_fourcc, child_len;
6189
6190   for (child = g_node_next_sibling (node); child;
6191       child = g_node_next_sibling (child)) {
6192     buffer = (guint8 *) child->data;
6193
6194     child_fourcc = QT_FOURCC (buffer + 4);
6195
6196     if (child_fourcc == fourcc) {
6197       if (parser) {
6198         child_len = QT_UINT32 (buffer);
6199         if (G_UNLIKELY (child_len < (4 + 4)))
6200           return NULL;
6201         /* FIXME: must verify if atom length < parent atom length */
6202         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
6203       }
6204       return child;
6205     }
6206   }
6207   return NULL;
6208 }
6209
6210 static GNode *
6211 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
6212 {
6213   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
6214 }
6215
6216 static void
6217 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
6218 {
6219 /* FIXME: This can only reliably work if demuxers have a
6220  * separate streaming thread per srcpad. This should be
6221  * done in a demuxer base class, which integrates parts
6222  * of multiqueue
6223  *
6224  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
6225  */
6226 #if 0
6227   GstQuery *query;
6228
6229   query = gst_query_new_allocation (stream->caps, FALSE);
6230
6231   if (!gst_pad_peer_query (stream->pad, query)) {
6232     /* not a problem, just debug a little */
6233     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
6234   }
6235
6236   if (stream->allocator)
6237     gst_object_unref (stream->allocator);
6238
6239   if (gst_query_get_n_allocation_params (query) > 0) {
6240     /* try the allocator */
6241     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
6242         &stream->params);
6243     stream->use_allocator = TRUE;
6244   } else {
6245     stream->allocator = NULL;
6246     gst_allocation_params_init (&stream->params);
6247     stream->use_allocator = FALSE;
6248   }
6249   gst_query_unref (query);
6250 #endif
6251 }
6252
6253 static gboolean
6254 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
6255 {
6256   if (stream->subtype == FOURCC_vide) {
6257     /* fps is calculated base on the duration of the average framerate since
6258      * qt does not have a fixed framerate. */
6259     if ((stream->n_samples == 1) && (stream->first_duration == 0)) {
6260       /* still frame */
6261       stream->fps_n = 0;
6262       stream->fps_d = 1;
6263     } else {
6264       if (stream->duration == 0 || stream->n_samples < 2) {
6265         stream->fps_n = stream->timescale;
6266         stream->fps_d = 1;
6267       } else {
6268         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
6269         /* stream->duration is guint64, timescale, n_samples are guint32 */
6270         GstClockTime avg_duration =
6271             gst_util_uint64_scale_round (stream->duration -
6272             stream->first_duration, GST_SECOND,
6273             (guint64) (stream->timescale) * (stream->n_samples - 1));
6274
6275         GST_LOG_OBJECT (qtdemux,
6276             "Calculating avg sample duration based on stream duration %"
6277             G_GUINT64_FORMAT
6278             " minus first sample %u, leaving %d samples gives %"
6279             GST_TIME_FORMAT, stream->duration, stream->first_duration,
6280             stream->n_samples - 1, GST_TIME_ARGS (avg_duration));
6281
6282         gst_video_guess_framerate (avg_duration, &stream->fps_n,
6283             &stream->fps_d);
6284       }
6285       GST_DEBUG_OBJECT (qtdemux,
6286           "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
6287           stream->timescale, stream->fps_n, stream->fps_d);
6288     }
6289
6290     if (stream->caps) {
6291       stream->caps = gst_caps_make_writable (stream->caps);
6292
6293       gst_caps_set_simple (stream->caps,
6294           "width", G_TYPE_INT, stream->width,
6295           "height", G_TYPE_INT, stream->height,
6296           "framerate", GST_TYPE_FRACTION, stream->fps_n, stream->fps_d, NULL);
6297
6298       /* calculate pixel-aspect-ratio using display width and height */
6299       GST_DEBUG_OBJECT (qtdemux,
6300           "video size %dx%d, target display size %dx%d", stream->width,
6301           stream->height, stream->display_width, stream->display_height);
6302       /* qt file might have pasp atom */
6303       if (stream->par_w > 0 && stream->par_h > 0) {
6304         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", stream->par_w, stream->par_h);
6305         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
6306             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
6307       } else if (stream->display_width > 0 && stream->display_height > 0 &&
6308           stream->width > 0 && stream->height > 0) {
6309         gint n, d;
6310
6311         /* calculate the pixel aspect ratio using the display and pixel w/h */
6312         n = stream->display_width * stream->height;
6313         d = stream->display_height * stream->width;
6314         if (n == d)
6315           n = d = 1;
6316         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
6317         stream->par_w = n;
6318         stream->par_h = d;
6319         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
6320             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
6321       }
6322
6323       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
6324         guint par_w = 1, par_h = 1;
6325
6326         if (stream->par_w > 0 && stream->par_h > 0) {
6327           par_w = stream->par_w;
6328           par_h = stream->par_h;
6329         }
6330
6331         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
6332                 stream->width, stream->height, par_w, par_h)) {
6333           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
6334         }
6335
6336         gst_caps_set_simple (stream->caps,
6337             "multiview-mode", G_TYPE_STRING,
6338             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
6339             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
6340             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
6341       }
6342     }
6343   }
6344
6345   else if (stream->subtype == FOURCC_soun) {
6346     if (stream->caps) {
6347       stream->caps = gst_caps_make_writable (stream->caps);
6348       if (stream->rate > 0)
6349         gst_caps_set_simple (stream->caps,
6350             "rate", G_TYPE_INT, (int) stream->rate, NULL);
6351       if (stream->n_channels > 0)
6352         gst_caps_set_simple (stream->caps,
6353             "channels", G_TYPE_INT, stream->n_channels, NULL);
6354       if (stream->n_channels > 2) {
6355         /* FIXME: Need to parse the 'chan' atom to get channel layouts
6356          * correctly; this is just the minimum we can do - assume
6357          * we don't actually have any channel positions. */
6358         gst_caps_set_simple (stream->caps,
6359             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
6360       }
6361     }
6362   }
6363
6364   if (stream->pad) {
6365     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
6366     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
6367     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
6368     gst_pad_set_active (stream->pad, TRUE);
6369
6370     gst_pad_use_fixed_caps (stream->pad);
6371
6372     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT, stream->caps);
6373     if (stream->new_stream) {
6374       gchar *stream_id;
6375       GstEvent *event;
6376       GstStreamFlags stream_flags;
6377
6378       event =
6379           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
6380           0);
6381       if (event) {
6382         if (gst_event_parse_group_id (event, &qtdemux->group_id))
6383           qtdemux->have_group_id = TRUE;
6384         else
6385           qtdemux->have_group_id = FALSE;
6386         gst_event_unref (event);
6387       } else if (!qtdemux->have_group_id) {
6388         qtdemux->have_group_id = TRUE;
6389         qtdemux->group_id = gst_util_group_id_next ();
6390       }
6391
6392       stream->new_stream = FALSE;
6393       stream_id =
6394           gst_pad_create_stream_id_printf (stream->pad,
6395           GST_ELEMENT_CAST (qtdemux), "%03u", stream->track_id);
6396       event = gst_event_new_stream_start (stream_id);
6397       if (qtdemux->have_group_id)
6398         gst_event_set_group_id (event, qtdemux->group_id);
6399       stream_flags = GST_STREAM_FLAG_NONE;
6400       if (stream->disabled)
6401         stream_flags |= GST_STREAM_FLAG_UNSELECT;
6402       if (stream->sparse)
6403         stream_flags |= GST_STREAM_FLAG_SPARSE;
6404       gst_event_set_stream_flags (event, stream_flags);
6405       gst_pad_push_event (stream->pad, event);
6406       g_free (stream_id);
6407     }
6408     gst_pad_set_caps (stream->pad, stream->caps);
6409     stream->new_caps = FALSE;
6410   }
6411   return TRUE;
6412 }
6413
6414 static gboolean
6415 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
6416     QtDemuxStream * stream, GstTagList * list)
6417 {
6418   /* consistent default for push based mode */
6419   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
6420
6421   if (stream->subtype == FOURCC_vide) {
6422     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
6423
6424     stream->pad =
6425         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
6426     g_free (name);
6427
6428     gst_qtdemux_configure_stream (qtdemux, stream);
6429     qtdemux->n_video_streams++;
6430   } else if (stream->subtype == FOURCC_soun) {
6431     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
6432
6433     stream->pad =
6434         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
6435     g_free (name);
6436     gst_qtdemux_configure_stream (qtdemux, stream);
6437     qtdemux->n_audio_streams++;
6438   } else if (stream->subtype == FOURCC_strm) {
6439     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
6440   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
6441       || stream->subtype == FOURCC_sbtl) {
6442     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
6443
6444     stream->pad =
6445         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
6446     g_free (name);
6447     gst_qtdemux_configure_stream (qtdemux, stream);
6448     qtdemux->n_sub_streams++;
6449   } else if (stream->caps) {
6450     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
6451
6452     stream->pad =
6453         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
6454     g_free (name);
6455     gst_qtdemux_configure_stream (qtdemux, stream);
6456     qtdemux->n_video_streams++;
6457   } else {
6458     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
6459     goto done;
6460   }
6461
6462   if (stream->pad) {
6463     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
6464         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
6465     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
6466     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
6467
6468     if (stream->pending_tags)
6469       gst_tag_list_unref (stream->pending_tags);
6470     stream->pending_tags = list;
6471     list = NULL;
6472     /* global tags go on each pad anyway */
6473     stream->send_global_tags = TRUE;
6474   }
6475 done:
6476   if (list)
6477     gst_tag_list_unref (list);
6478   return TRUE;
6479 }
6480
6481 /* find next atom with @fourcc starting at @offset */
6482 static GstFlowReturn
6483 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
6484     guint64 * length, guint32 fourcc)
6485 {
6486   GstFlowReturn ret;
6487   guint32 lfourcc;
6488   GstBuffer *buf;
6489
6490   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
6491       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
6492
6493   while (TRUE) {
6494     GstMapInfo map;
6495
6496     buf = NULL;
6497     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
6498     if (G_UNLIKELY (ret != GST_FLOW_OK))
6499       goto locate_failed;
6500     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
6501       /* likely EOF */
6502       ret = GST_FLOW_EOS;
6503       gst_buffer_unref (buf);
6504       goto locate_failed;
6505     }
6506     gst_buffer_map (buf, &map, GST_MAP_READ);
6507     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
6508     gst_buffer_unmap (buf, &map);
6509     gst_buffer_unref (buf);
6510
6511     if (G_UNLIKELY (*length == 0)) {
6512       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
6513       ret = GST_FLOW_ERROR;
6514       goto locate_failed;
6515     }
6516
6517     if (lfourcc == fourcc) {
6518       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
6519           *offset);
6520       break;
6521     } else {
6522       GST_LOG_OBJECT (qtdemux,
6523           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
6524           GST_FOURCC_ARGS (fourcc), *offset);
6525       *offset += *length;
6526     }
6527   }
6528
6529   return GST_FLOW_OK;
6530
6531 locate_failed:
6532   {
6533     /* might simply have had last one */
6534     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
6535     return ret;
6536   }
6537 }
6538
6539 /* should only do something in pull mode */
6540 /* call with OBJECT lock */
6541 static GstFlowReturn
6542 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
6543 {
6544   guint64 length, offset;
6545   GstBuffer *buf = NULL;
6546   GstFlowReturn ret = GST_FLOW_OK;
6547   GstFlowReturn res = GST_FLOW_OK;
6548   GstMapInfo map;
6549
6550   offset = qtdemux->moof_offset;
6551   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
6552
6553   if (!offset) {
6554     GST_DEBUG_OBJECT (qtdemux, "no next moof");
6555     return GST_FLOW_EOS;
6556   }
6557
6558   /* best not do pull etc with lock held */
6559   GST_OBJECT_UNLOCK (qtdemux);
6560
6561   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
6562   if (ret != GST_FLOW_OK)
6563     goto flow_failed;
6564
6565   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
6566   if (G_UNLIKELY (ret != GST_FLOW_OK))
6567     goto flow_failed;
6568   gst_buffer_map (buf, &map, GST_MAP_READ);
6569   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
6570     gst_buffer_unmap (buf, &map);
6571     gst_buffer_unref (buf);
6572     buf = NULL;
6573     goto parse_failed;
6574   }
6575
6576   gst_buffer_unmap (buf, &map);
6577   gst_buffer_unref (buf);
6578   buf = NULL;
6579
6580   offset += length;
6581   /* look for next moof */
6582   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
6583   if (G_UNLIKELY (ret != GST_FLOW_OK))
6584     goto flow_failed;
6585
6586 exit:
6587   GST_OBJECT_LOCK (qtdemux);
6588
6589   qtdemux->moof_offset = offset;
6590
6591   return res;
6592
6593 parse_failed:
6594   {
6595     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
6596     offset = 0;
6597     res = GST_FLOW_ERROR;
6598     goto exit;
6599   }
6600 flow_failed:
6601   {
6602     /* maybe upstream temporarily flushing */
6603     if (ret != GST_FLOW_FLUSHING) {
6604       GST_DEBUG_OBJECT (qtdemux, "no next moof");
6605       offset = 0;
6606     } else {
6607       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
6608       /* resume at current position next time */
6609     }
6610     res = ret;
6611     goto exit;
6612   }
6613 }
6614
6615 /* initialise bytereaders for stbl sub-atoms */
6616 static gboolean
6617 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
6618 {
6619   stream->stbl_index = -1;      /* no samples have yet been parsed */
6620   stream->sample_index = -1;
6621
6622   /* time-to-sample atom */
6623   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
6624     goto corrupt_file;
6625
6626   /* copy atom data into a new buffer for later use */
6627   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
6628
6629   /* skip version + flags */
6630   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
6631       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
6632     goto corrupt_file;
6633   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
6634
6635   /* make sure there's enough data */
6636   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
6637     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
6638     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
6639         stream->n_sample_times);
6640     if (!stream->n_sample_times)
6641       goto corrupt_file;
6642   }
6643
6644   /* sync sample atom */
6645   stream->stps_present = FALSE;
6646   if ((stream->stss_present =
6647           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
6648               &stream->stss) ? TRUE : FALSE) == TRUE) {
6649     /* copy atom data into a new buffer for later use */
6650     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
6651
6652     /* skip version + flags */
6653     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
6654         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
6655       goto corrupt_file;
6656
6657     if (stream->n_sample_syncs) {
6658       /* make sure there's enough data */
6659       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
6660         goto corrupt_file;
6661     }
6662
6663     /* partial sync sample atom */
6664     if ((stream->stps_present =
6665             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
6666                 &stream->stps) ? TRUE : FALSE) == TRUE) {
6667       /* copy atom data into a new buffer for later use */
6668       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
6669
6670       /* skip version + flags */
6671       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
6672           !gst_byte_reader_get_uint32_be (&stream->stps,
6673               &stream->n_sample_partial_syncs))
6674         goto corrupt_file;
6675
6676       /* if there are no entries, the stss table contains the real
6677        * sync samples */
6678       if (stream->n_sample_partial_syncs) {
6679         /* make sure there's enough data */
6680         if (!qt_atom_parser_has_chunks (&stream->stps,
6681                 stream->n_sample_partial_syncs, 4))
6682           goto corrupt_file;
6683       }
6684     }
6685   }
6686
6687   /* sample size */
6688   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
6689     goto no_samples;
6690
6691   /* copy atom data into a new buffer for later use */
6692   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
6693
6694   /* skip version + flags */
6695   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
6696       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
6697     goto corrupt_file;
6698
6699   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
6700     goto corrupt_file;
6701
6702   if (!stream->n_samples)
6703     goto no_samples;
6704
6705   /* sample-to-chunk atom */
6706   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
6707     goto corrupt_file;
6708
6709   /* copy atom data into a new buffer for later use */
6710   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
6711
6712   /* skip version + flags */
6713   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
6714       !gst_byte_reader_get_uint32_be (&stream->stsc,
6715           &stream->n_samples_per_chunk))
6716     goto corrupt_file;
6717
6718   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
6719       stream->n_samples_per_chunk);
6720
6721   /* make sure there's enough data */
6722   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
6723           12))
6724     goto corrupt_file;
6725
6726
6727   /* chunk offset */
6728   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
6729     stream->co_size = sizeof (guint32);
6730   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
6731           &stream->stco))
6732     stream->co_size = sizeof (guint64);
6733   else
6734     goto corrupt_file;
6735
6736   /* copy atom data into a new buffer for later use */
6737   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
6738
6739   /* skip version + flags */
6740   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
6741     goto corrupt_file;
6742
6743   /* chunks_are_samples == TRUE means treat chunks as samples */
6744   stream->chunks_are_samples = stream->sample_size && !stream->sampled;
6745   if (stream->chunks_are_samples) {
6746     /* treat chunks as samples */
6747     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
6748       goto corrupt_file;
6749   } else {
6750     /* skip number of entries */
6751     if (!gst_byte_reader_skip (&stream->stco, 4))
6752       goto corrupt_file;
6753
6754     /* make sure there are enough data in the stsz atom */
6755     if (!stream->sample_size) {
6756       /* different sizes for each sample */
6757       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
6758         goto corrupt_file;
6759     }
6760   }
6761
6762   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
6763       stream->n_samples, (guint) sizeof (QtDemuxSample),
6764       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
6765
6766   if (stream->n_samples >=
6767       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
6768     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
6769         "be larger than %uMB (broken file?)", stream->n_samples,
6770         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
6771     return FALSE;
6772   }
6773
6774   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
6775   if (!stream->samples) {
6776     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
6777         stream->n_samples);
6778     return FALSE;
6779   }
6780
6781   /* composition time-to-sample */
6782   if ((stream->ctts_present =
6783           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
6784               &stream->ctts) ? TRUE : FALSE) == TRUE) {
6785     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
6786
6787     /* copy atom data into a new buffer for later use */
6788     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
6789
6790     /* skip version + flags */
6791     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
6792         || !gst_byte_reader_get_uint32_be (&stream->ctts,
6793             &stream->n_composition_times))
6794       goto corrupt_file;
6795
6796     /* make sure there's enough data */
6797     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
6798             4 + 4))
6799       goto corrupt_file;
6800
6801     /* This is optional, if missing we iterate the ctts */
6802     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
6803       if (!gst_byte_reader_skip (&cslg, 1 + 3)
6804           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
6805         g_free ((gpointer) cslg.data);
6806         goto corrupt_file;
6807       }
6808     } else {
6809       gint32 cslg_least = 0;
6810       guint num_entries, pos;
6811       gint i;
6812
6813       pos = gst_byte_reader_get_pos (&stream->ctts);
6814       num_entries = stream->n_composition_times;
6815
6816       stream->cslg_shift = 0;
6817
6818       for (i = 0; i < num_entries; i++) {
6819         gint32 offset;
6820
6821         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
6822         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
6823
6824         if (offset < cslg_least)
6825           cslg_least = offset;
6826       }
6827
6828       if (cslg_least < 0)
6829         stream->cslg_shift = ABS (cslg_least);
6830       else
6831         stream->cslg_shift = 0;
6832
6833       /* reset the reader so we can generate sample table */
6834       gst_byte_reader_set_pos (&stream->ctts, pos);
6835     }
6836   } else {
6837     /* Ensure the cslg_shift value is consistent so we can use it
6838      * unconditionnally to produce TS and Segment */
6839     stream->cslg_shift = 0;
6840   }
6841
6842   return TRUE;
6843
6844 corrupt_file:
6845   {
6846     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
6847         (_("This file is corrupt and cannot be played.")), (NULL));
6848     return FALSE;
6849   }
6850 no_samples:
6851   {
6852     gst_qtdemux_stbl_free (stream);
6853     if (!qtdemux->fragmented) {
6854       /* not quite good */
6855       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
6856       return FALSE;
6857     } else {
6858       /* may pick up samples elsewhere */
6859       return TRUE;
6860     }
6861   }
6862 }
6863
6864 /* collect samples from the next sample to be parsed up to sample @n for @stream
6865  * by reading the info from @stbl
6866  *
6867  * This code can be executed from both the streaming thread and the seeking
6868  * thread so it takes the object lock to protect itself
6869  */
6870 static gboolean
6871 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
6872 {
6873   gint i, j, k;
6874   QtDemuxSample *samples, *first, *cur, *last;
6875   guint32 n_samples_per_chunk;
6876   guint32 n_samples;
6877
6878   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
6879       GST_FOURCC_FORMAT ", pad %s", GST_FOURCC_ARGS (stream->fourcc),
6880       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
6881
6882   n_samples = stream->n_samples;
6883
6884   if (n >= n_samples)
6885     goto out_of_samples;
6886
6887   GST_OBJECT_LOCK (qtdemux);
6888   if (n <= stream->stbl_index)
6889     goto already_parsed;
6890
6891   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
6892
6893   if (!stream->stsz.data) {
6894     /* so we already parsed and passed all the moov samples;
6895      * onto fragmented ones */
6896     g_assert (qtdemux->fragmented);
6897     goto done;
6898   }
6899
6900   /* pointer to the sample table */
6901   samples = stream->samples;
6902
6903   /* starts from -1, moves to the next sample index to parse */
6904   stream->stbl_index++;
6905
6906   /* keep track of the first and last sample to fill */
6907   first = &samples[stream->stbl_index];
6908   last = &samples[n];
6909
6910   if (!stream->chunks_are_samples) {
6911     /* set the sample sizes */
6912     if (stream->sample_size == 0) {
6913       /* different sizes for each sample */
6914       for (cur = first; cur <= last; cur++) {
6915         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
6916         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
6917             (guint) (cur - samples), cur->size);
6918       }
6919     } else {
6920       /* samples have the same size */
6921       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
6922       for (cur = first; cur <= last; cur++)
6923         cur->size = stream->sample_size;
6924     }
6925   }
6926
6927   n_samples_per_chunk = stream->n_samples_per_chunk;
6928   cur = first;
6929
6930   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
6931     guint32 last_chunk;
6932
6933     if (stream->stsc_chunk_index >= stream->last_chunk
6934         || stream->stsc_chunk_index < stream->first_chunk) {
6935       stream->first_chunk =
6936           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
6937       stream->samples_per_chunk =
6938           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
6939       gst_byte_reader_skip_unchecked (&stream->stsc, 4);
6940
6941       /* chunk numbers are counted from 1 it seems */
6942       if (G_UNLIKELY (stream->first_chunk == 0))
6943         goto corrupt_file;
6944
6945       --stream->first_chunk;
6946
6947       /* the last chunk of each entry is calculated by taking the first chunk
6948        * of the next entry; except if there is no next, where we fake it with
6949        * INT_MAX */
6950       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
6951         stream->last_chunk = G_MAXUINT32;
6952       } else {
6953         stream->last_chunk =
6954             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
6955         if (G_UNLIKELY (stream->last_chunk == 0))
6956           goto corrupt_file;
6957
6958         --stream->last_chunk;
6959       }
6960
6961       GST_LOG_OBJECT (qtdemux,
6962           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d", i,
6963           stream->first_chunk, stream->last_chunk, stream->samples_per_chunk);
6964
6965       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
6966         goto corrupt_file;
6967
6968       if (stream->last_chunk != G_MAXUINT32) {
6969         if (!qt_atom_parser_peek_sub (&stream->stco,
6970                 stream->first_chunk * stream->co_size,
6971                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
6972                 &stream->co_chunk))
6973           goto corrupt_file;
6974
6975       } else {
6976         stream->co_chunk = stream->stco;
6977         if (!gst_byte_reader_skip (&stream->co_chunk,
6978                 stream->first_chunk * stream->co_size))
6979           goto corrupt_file;
6980       }
6981
6982       stream->stsc_chunk_index = stream->first_chunk;
6983     }
6984
6985     last_chunk = stream->last_chunk;
6986
6987     if (stream->chunks_are_samples) {
6988       cur = &samples[stream->stsc_chunk_index];
6989
6990       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
6991         if (j > n) {
6992           /* save state */
6993           stream->stsc_chunk_index = j;
6994           goto done;
6995         }
6996
6997         cur->offset =
6998             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
6999             stream->co_size);
7000
7001         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
7002             "%" G_GUINT64_FORMAT, j, cur->offset);
7003
7004         if (stream->samples_per_frame * stream->bytes_per_frame) {
7005           cur->size =
7006               (stream->samples_per_chunk * stream->n_channels) /
7007               stream->samples_per_frame * stream->bytes_per_frame;
7008         } else {
7009           cur->size = stream->samples_per_chunk;
7010         }
7011
7012         GST_DEBUG_OBJECT (qtdemux,
7013             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
7014             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
7015                     stream->stco_sample_index)), cur->size);
7016
7017         cur->timestamp = stream->stco_sample_index;
7018         cur->duration = stream->samples_per_chunk;
7019         cur->keyframe = TRUE;
7020         cur++;
7021
7022         stream->stco_sample_index += stream->samples_per_chunk;
7023       }
7024       stream->stsc_chunk_index = j;
7025     } else {
7026       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
7027         guint32 samples_per_chunk;
7028         guint64 chunk_offset;
7029
7030         if (!stream->stsc_sample_index
7031             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
7032                 &stream->chunk_offset))
7033           goto corrupt_file;
7034
7035         samples_per_chunk = stream->samples_per_chunk;
7036         chunk_offset = stream->chunk_offset;
7037
7038         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
7039           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
7040               G_GUINT64_FORMAT " and size %d",
7041               (guint) (cur - samples), chunk_offset, cur->size);
7042
7043           cur->offset = chunk_offset;
7044           chunk_offset += cur->size;
7045           cur++;
7046
7047           if (G_UNLIKELY (cur > last)) {
7048             /* save state */
7049             stream->stsc_sample_index = k + 1;
7050             stream->chunk_offset = chunk_offset;
7051             stream->stsc_chunk_index = j;
7052             goto done2;
7053           }
7054         }
7055         stream->stsc_sample_index = 0;
7056       }
7057       stream->stsc_chunk_index = j;
7058     }
7059     stream->stsc_index++;
7060   }
7061
7062   if (stream->chunks_are_samples)
7063     goto ctts;
7064 done2:
7065   {
7066     guint32 n_sample_times;
7067
7068     n_sample_times = stream->n_sample_times;
7069     cur = first;
7070
7071     for (i = stream->stts_index; i < n_sample_times; i++) {
7072       guint32 stts_samples;
7073       gint32 stts_duration;
7074       gint64 stts_time;
7075
7076       if (stream->stts_sample_index >= stream->stts_samples
7077           || !stream->stts_sample_index) {
7078
7079         stream->stts_samples =
7080             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
7081         stream->stts_duration =
7082             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
7083
7084         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
7085             i, stream->stts_samples, stream->stts_duration);
7086
7087         stream->stts_sample_index = 0;
7088       }
7089
7090       stts_samples = stream->stts_samples;
7091       stts_duration = stream->stts_duration;
7092       stts_time = stream->stts_time;
7093
7094       for (j = stream->stts_sample_index; j < stts_samples; j++) {
7095         GST_DEBUG_OBJECT (qtdemux,
7096             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
7097             (guint) (cur - samples), j,
7098             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
7099
7100         cur->timestamp = stts_time;
7101         cur->duration = stts_duration;
7102
7103         /* avoid 32-bit wrap-around,
7104          * but still mind possible 'negative' duration */
7105         stts_time += (gint64) stts_duration;
7106         cur++;
7107
7108         if (G_UNLIKELY (cur > last)) {
7109           /* save values */
7110           stream->stts_time = stts_time;
7111           stream->stts_sample_index = j + 1;
7112           goto done3;
7113         }
7114       }
7115       stream->stts_sample_index = 0;
7116       stream->stts_time = stts_time;
7117       stream->stts_index++;
7118     }
7119     /* fill up empty timestamps with the last timestamp, this can happen when
7120      * the last samples do not decode and so we don't have timestamps for them.
7121      * We however look at the last timestamp to estimate the track length so we
7122      * need something in here. */
7123     for (; cur < last; cur++) {
7124       GST_DEBUG_OBJECT (qtdemux,
7125           "fill sample %d: timestamp %" GST_TIME_FORMAT,
7126           (guint) (cur - samples),
7127           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
7128       cur->timestamp = stream->stts_time;
7129       cur->duration = -1;
7130     }
7131   }
7132 done3:
7133   {
7134     /* sample sync, can be NULL */
7135     if (stream->stss_present == TRUE) {
7136       guint32 n_sample_syncs;
7137
7138       n_sample_syncs = stream->n_sample_syncs;
7139
7140       if (!n_sample_syncs) {
7141         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
7142         stream->all_keyframe = TRUE;
7143       } else {
7144         for (i = stream->stss_index; i < n_sample_syncs; i++) {
7145           /* note that the first sample is index 1, not 0 */
7146           guint32 index;
7147
7148           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
7149
7150           if (G_LIKELY (index > 0 && index <= n_samples)) {
7151             index -= 1;
7152             samples[index].keyframe = TRUE;
7153             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
7154             /* and exit if we have enough samples */
7155             if (G_UNLIKELY (index >= n)) {
7156               i++;
7157               break;
7158             }
7159           }
7160         }
7161         /* save state */
7162         stream->stss_index = i;
7163       }
7164
7165       /* stps marks partial sync frames like open GOP I-Frames */
7166       if (stream->stps_present == TRUE) {
7167         guint32 n_sample_partial_syncs;
7168
7169         n_sample_partial_syncs = stream->n_sample_partial_syncs;
7170
7171         /* if there are no entries, the stss table contains the real
7172          * sync samples */
7173         if (n_sample_partial_syncs) {
7174           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
7175             /* note that the first sample is index 1, not 0 */
7176             guint32 index;
7177
7178             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
7179
7180             if (G_LIKELY (index > 0 && index <= n_samples)) {
7181               index -= 1;
7182               samples[index].keyframe = TRUE;
7183               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
7184               /* and exit if we have enough samples */
7185               if (G_UNLIKELY (index >= n)) {
7186                 i++;
7187                 break;
7188               }
7189             }
7190           }
7191           /* save state */
7192           stream->stps_index = i;
7193         }
7194       }
7195     } else {
7196       /* no stss, all samples are keyframes */
7197       stream->all_keyframe = TRUE;
7198       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
7199     }
7200   }
7201
7202 ctts:
7203   /* composition time to sample */
7204   if (stream->ctts_present == TRUE) {
7205     guint32 n_composition_times;
7206     guint32 ctts_count;
7207     gint32 ctts_soffset;
7208
7209     /* Fill in the pts_offsets */
7210     cur = first;
7211     n_composition_times = stream->n_composition_times;
7212
7213     for (i = stream->ctts_index; i < n_composition_times; i++) {
7214       if (stream->ctts_sample_index >= stream->ctts_count
7215           || !stream->ctts_sample_index) {
7216         stream->ctts_count =
7217             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
7218         stream->ctts_soffset =
7219             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
7220         stream->ctts_sample_index = 0;
7221       }
7222
7223       ctts_count = stream->ctts_count;
7224       ctts_soffset = stream->ctts_soffset;
7225
7226       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
7227         cur->pts_offset = ctts_soffset;
7228         cur++;
7229
7230         if (G_UNLIKELY (cur > last)) {
7231           /* save state */
7232           stream->ctts_sample_index = j + 1;
7233           goto done;
7234         }
7235       }
7236       stream->ctts_sample_index = 0;
7237       stream->ctts_index++;
7238     }
7239   }
7240 done:
7241   stream->stbl_index = n;
7242   /* if index has been completely parsed, free data that is no-longer needed */
7243   if (n + 1 == stream->n_samples) {
7244     gst_qtdemux_stbl_free (stream);
7245     GST_DEBUG_OBJECT (qtdemux,
7246         "parsed all available samples; checking for more");
7247     while (n + 1 == stream->n_samples)
7248       if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
7249         break;
7250   }
7251   GST_OBJECT_UNLOCK (qtdemux);
7252
7253   return TRUE;
7254
7255   /* SUCCESS */
7256 already_parsed:
7257   {
7258     GST_LOG_OBJECT (qtdemux,
7259         "Tried to parse up to sample %u but this sample has already been parsed",
7260         n);
7261     /* if fragmented, there may be more */
7262     if (qtdemux->fragmented && n == stream->stbl_index)
7263       goto done;
7264     GST_OBJECT_UNLOCK (qtdemux);
7265     return TRUE;
7266   }
7267   /* ERRORS */
7268 out_of_samples:
7269   {
7270     GST_LOG_OBJECT (qtdemux,
7271         "Tried to parse up to sample %u but there are only %u samples", n + 1,
7272         stream->n_samples);
7273     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7274         (_("This file is corrupt and cannot be played.")), (NULL));
7275     return FALSE;
7276   }
7277 corrupt_file:
7278   {
7279     GST_OBJECT_UNLOCK (qtdemux);
7280     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7281         (_("This file is corrupt and cannot be played.")), (NULL));
7282     return FALSE;
7283   }
7284 }
7285
7286 /* collect all segment info for @stream.
7287  */
7288 static gboolean
7289 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
7290     GNode * trak)
7291 {
7292   GNode *edts;
7293
7294   /* parse and prepare segment info from the edit list */
7295   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
7296   stream->n_segments = 0;
7297   stream->segments = NULL;
7298   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
7299     GNode *elst;
7300     gint n_segments;
7301     gint i, count;
7302     guint64 time;
7303     GstClockTime stime;
7304     guint8 *buffer;
7305
7306     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
7307     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
7308       goto done;
7309
7310     buffer = elst->data;
7311
7312     n_segments = QT_UINT32 (buffer + 12);
7313
7314     /* we might allocate a bit too much, at least allocate 1 segment */
7315     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
7316
7317     /* segments always start from 0 */
7318     time = 0;
7319     stime = 0;
7320     count = 0;
7321     for (i = 0; i < n_segments; i++) {
7322       guint64 duration;
7323       guint64 media_time;
7324       QtDemuxSegment *segment;
7325       guint32 rate_int;
7326
7327       media_time = QT_UINT32 (buffer + 20 + i * 12);
7328       duration = QT_UINT32 (buffer + 16 + i * 12);
7329
7330       segment = &stream->segments[count++];
7331
7332       /* time and duration expressed in global timescale */
7333       segment->time = stime;
7334       /* add non scaled values so we don't cause roundoff errors */
7335       time += duration;
7336       stime = QTTIME_TO_GSTTIME (qtdemux, time);
7337       segment->stop_time = stime;
7338       segment->duration = stime - segment->time;
7339
7340       segment->trak_media_start = media_time;
7341       /* media_time expressed in stream timescale */
7342       if (media_time != G_MAXUINT32) {
7343         segment->media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
7344         segment->media_stop = segment->media_start + segment->duration;
7345       } else {
7346         segment->media_start = GST_CLOCK_TIME_NONE;
7347         segment->media_stop = GST_CLOCK_TIME_NONE;
7348       }
7349       rate_int = GST_READ_UINT32_BE (buffer + 24 + i * 12);
7350
7351       if (rate_int <= 1) {
7352         /* 0 is not allowed, some programs write 1 instead of the floating point
7353          * value */
7354         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
7355             rate_int);
7356         segment->rate = 1;
7357       } else {
7358         segment->rate = rate_int / 65536.0;
7359       }
7360
7361       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
7362           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
7363           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
7364           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
7365           i, GST_TIME_ARGS (segment->time),
7366           GST_TIME_ARGS (segment->duration),
7367           GST_TIME_ARGS (segment->media_start), media_time,
7368           GST_TIME_ARGS (segment->media_stop),
7369           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
7370           stream->timescale);
7371       if (segment->stop_time > qtdemux->segment.stop) {
7372         GST_WARNING_OBJECT (qtdemux, "Segment %d "
7373             " extends to %" GST_TIME_FORMAT
7374             " past the end of the file duration %" GST_TIME_FORMAT
7375             " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
7376             GST_TIME_ARGS (qtdemux->segment.stop));
7377         qtdemux->segment.stop = segment->stop_time;
7378       }
7379     }
7380     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
7381     stream->n_segments = count;
7382   }
7383 done:
7384
7385   /* push based does not handle segments, so act accordingly here,
7386    * and warn if applicable */
7387   if (!qtdemux->pullbased) {
7388     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
7389     /* remove and use default one below, we stream like it anyway */
7390     g_free (stream->segments);
7391     stream->segments = NULL;
7392     stream->n_segments = 0;
7393   }
7394
7395   /* no segments, create one to play the complete trak */
7396   if (stream->n_segments == 0) {
7397     GstClockTime stream_duration =
7398         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
7399
7400     if (stream->segments == NULL)
7401       stream->segments = g_new (QtDemuxSegment, 1);
7402
7403     /* represent unknown our way */
7404     if (stream_duration == 0)
7405       stream_duration = GST_CLOCK_TIME_NONE;
7406
7407     stream->segments[0].time = 0;
7408     stream->segments[0].stop_time = stream_duration;
7409     stream->segments[0].duration = stream_duration;
7410     stream->segments[0].media_start = 0;
7411     stream->segments[0].media_stop = stream_duration;
7412     stream->segments[0].rate = 1.0;
7413     stream->segments[0].trak_media_start = 0;
7414
7415     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
7416         GST_TIME_ARGS (stream_duration));
7417     stream->n_segments = 1;
7418     stream->dummy_segment = TRUE;
7419   }
7420   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
7421
7422   return TRUE;
7423 }
7424
7425 /*
7426  * Parses the stsd atom of a svq3 trak looking for
7427  * the SMI and gama atoms.
7428  */
7429 static void
7430 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux, GNode * stsd,
7431     guint8 ** gamma, GstBuffer ** seqh)
7432 {
7433   guint8 *_gamma = NULL;
7434   GstBuffer *_seqh = NULL;
7435   guint8 *stsd_data = stsd->data;
7436   guint32 length = QT_UINT32 (stsd_data);
7437   guint16 version;
7438
7439   if (length < 32) {
7440     GST_WARNING_OBJECT (qtdemux, "stsd too short");
7441     goto end;
7442   }
7443
7444   stsd_data += 32;
7445   length -= 32;
7446   version = QT_UINT16 (stsd_data);
7447   if (version == 3) {
7448     if (length >= 70) {
7449       length -= 70;
7450       stsd_data += 70;
7451       while (length > 8) {
7452         guint32 fourcc, size;
7453         guint8 *data;
7454         size = QT_UINT32 (stsd_data);
7455         fourcc = QT_FOURCC (stsd_data + 4);
7456         data = stsd_data + 8;
7457
7458         if (size == 0) {
7459           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
7460               "svq3 atom parsing");
7461           goto end;
7462         }
7463
7464         switch (fourcc) {
7465           case FOURCC_gama:{
7466             if (size == 12) {
7467               _gamma = data;
7468             } else {
7469               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
7470                   " for gama atom, expected 12", size);
7471             }
7472             break;
7473           }
7474           case FOURCC_SMI_:{
7475             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
7476               guint32 seqh_size;
7477               if (_seqh != NULL) {
7478                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
7479                     " found, ignoring");
7480               } else {
7481                 seqh_size = QT_UINT32 (data + 4);
7482                 if (seqh_size > 0) {
7483                   _seqh = gst_buffer_new_and_alloc (seqh_size);
7484                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
7485                 }
7486               }
7487             }
7488             break;
7489           }
7490           default:{
7491             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
7492                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
7493           }
7494         }
7495
7496         if (size <= length) {
7497           length -= size;
7498           stsd_data += size;
7499         }
7500       }
7501     } else {
7502       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
7503     }
7504   } else {
7505     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
7506         G_GUINT16_FORMAT, version);
7507     goto end;
7508   }
7509
7510 end:
7511   if (gamma) {
7512     *gamma = _gamma;
7513   }
7514   if (seqh) {
7515     *seqh = _seqh;
7516   } else if (_seqh) {
7517     gst_buffer_unref (_seqh);
7518   }
7519 }
7520
7521 static gchar *
7522 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
7523 {
7524   GNode *dinf;
7525   GstByteReader dref;
7526   gchar *uri = NULL;
7527
7528   /*
7529    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
7530    * atom that might contain a 'data' atom with the rtsp uri.
7531    * This case was reported in bug #597497, some info about
7532    * the hndl atom can be found in TN1195
7533    */
7534   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
7535   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
7536
7537   if (dinf) {
7538     guint32 dref_num_entries = 0;
7539     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
7540         gst_byte_reader_skip (&dref, 4) &&
7541         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
7542       gint i;
7543
7544       /* search dref entries for hndl atom */
7545       for (i = 0; i < dref_num_entries; i++) {
7546         guint32 size = 0, type;
7547         guint8 string_len = 0;
7548         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
7549             qt_atom_parser_get_fourcc (&dref, &type)) {
7550           if (type == FOURCC_hndl) {
7551             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
7552
7553             /* skip data reference handle bytes and the
7554              * following pascal string and some extra 4
7555              * bytes I have no idea what are */
7556             if (!gst_byte_reader_skip (&dref, 4) ||
7557                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
7558                 !gst_byte_reader_skip (&dref, string_len + 4)) {
7559               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
7560               break;
7561             }
7562
7563             /* iterate over the atoms to find the data atom */
7564             while (gst_byte_reader_get_remaining (&dref) >= 8) {
7565               guint32 atom_size;
7566               guint32 atom_type;
7567
7568               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
7569                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
7570                 if (atom_type == FOURCC_data) {
7571                   const guint8 *uri_aux = NULL;
7572
7573                   /* found the data atom that might contain the rtsp uri */
7574                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
7575                       "hndl atom, interpreting it as an URI");
7576                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
7577                           &uri_aux)) {
7578                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
7579                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
7580                     else
7581                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
7582                           "didn't contain a rtsp address");
7583                   } else {
7584                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
7585                         "atom contents");
7586                   }
7587                   break;
7588                 }
7589                 /* skipping to the next entry */
7590                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
7591                   break;
7592               } else {
7593                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
7594                     "atom header");
7595                 break;
7596               }
7597             }
7598             break;
7599           }
7600           /* skip to the next entry */
7601           if (!gst_byte_reader_skip (&dref, size - 8))
7602             break;
7603         } else {
7604           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
7605         }
7606       }
7607       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
7608     }
7609   }
7610   return uri;
7611 }
7612
7613 #define AMR_NB_ALL_MODES        0x81ff
7614 #define AMR_WB_ALL_MODES        0x83ff
7615 static guint
7616 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
7617 {
7618   /* The 'damr' atom is of the form:
7619    *
7620    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
7621    *    32 b       8 b          16 b           8 b                 8 b
7622    *
7623    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
7624    * represents the highest mode used in the stream (and thus the maximum
7625    * bitrate), with a couple of special cases as seen below.
7626    */
7627
7628   /* Map of frame type ID -> bitrate */
7629   static const guint nb_bitrates[] = {
7630     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
7631   };
7632   static const guint wb_bitrates[] = {
7633     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
7634   };
7635   GstMapInfo map;
7636   gsize max_mode;
7637   guint16 mode_set;
7638
7639   gst_buffer_map (buf, &map, GST_MAP_READ);
7640
7641   if (map.size != 0x11) {
7642     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
7643     goto bad_data;
7644   }
7645
7646   if (QT_FOURCC (map.data + 4) != GST_MAKE_FOURCC ('d', 'a', 'm', 'r')) {
7647     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
7648         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
7649     goto bad_data;
7650   }
7651
7652   mode_set = QT_UINT16 (map.data + 13);
7653
7654   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
7655     max_mode = 7 + (wb ? 1 : 0);
7656   else
7657     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
7658     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
7659
7660   if (max_mode == -1) {
7661     GST_DEBUG ("No mode indication was found (mode set) = %x",
7662         (guint) mode_set);
7663     goto bad_data;
7664   }
7665
7666   gst_buffer_unmap (buf, &map);
7667   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
7668
7669 bad_data:
7670   gst_buffer_unmap (buf, &map);
7671   return 0;
7672 }
7673
7674 static gboolean
7675 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
7676     GstByteReader * reader, guint32 * matrix, const gchar * atom)
7677 {
7678   /*
7679    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
7680    * [0 1 2]
7681    * [3 4 5]
7682    * [6 7 8]
7683    */
7684
7685   if (gst_byte_reader_get_remaining (reader) < 36)
7686     return FALSE;
7687
7688   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
7689   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
7690   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
7691   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
7692   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
7693   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
7694   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
7695   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
7696   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
7697
7698   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
7699   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
7700       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
7701       matrix[2] & 0xFF);
7702   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
7703       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
7704       matrix[5] & 0xFF);
7705   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
7706       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
7707       matrix[8] & 0xFF);
7708
7709   return TRUE;
7710 }
7711
7712 static void
7713 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
7714     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
7715 {
7716
7717 /* [a b c]
7718  * [d e f]
7719  * [g h i]
7720  *
7721  * This macro will only compare value abdegh, it expects cfi to have already
7722  * been checked
7723  */
7724 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
7725                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
7726
7727   /* only handle the cases where the last column has standard values */
7728   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
7729     const gchar *rotation_tag = NULL;
7730
7731     /* no rotation needed */
7732     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
7733       /* NOP */
7734     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
7735       rotation_tag = "rotate-90";
7736     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
7737       rotation_tag = "rotate-180";
7738     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
7739       rotation_tag = "rotate-270";
7740     } else {
7741       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
7742     }
7743
7744     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
7745         rotation_tag);
7746     if (rotation_tag != NULL) {
7747       if (*taglist == NULL)
7748         *taglist = gst_tag_list_new_empty ();
7749       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
7750           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
7751     }
7752   } else {
7753     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
7754   }
7755 }
7756
7757 /* parse the traks.
7758  * With each track we associate a new QtDemuxStream that contains all the info
7759  * about the trak.
7760  * traks that do not decode to something (like strm traks) will not have a pad.
7761  */
7762 static gboolean
7763 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
7764 {
7765   GstByteReader tkhd;
7766   int offset;
7767   GNode *mdia;
7768   GNode *mdhd;
7769   GNode *hdlr;
7770   GNode *minf;
7771   GNode *stbl;
7772   GNode *stsd;
7773   GNode *mp4a;
7774   GNode *mp4v;
7775   GNode *wave;
7776   GNode *esds;
7777   GNode *pasp;
7778   GNode *tref;
7779   GNode *udta;
7780   GNode *svmi;
7781
7782   QtDemuxStream *stream = NULL;
7783   gboolean new_stream = FALSE;
7784   gchar *codec = NULL;
7785   const guint8 *stsd_data;
7786   guint16 lang_code;            /* quicktime lang code or packed iso code */
7787   guint32 version;
7788   guint32 tkhd_flags = 0;
7789   guint8 tkhd_version = 0;
7790   guint32 fourcc;
7791   guint value_size, stsd_len, len;
7792   guint32 track_id;
7793
7794   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
7795
7796   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
7797       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
7798       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
7799     goto corrupt_file;
7800
7801   /* pick between 64 or 32 bits */
7802   value_size = tkhd_version == 1 ? 8 : 4;
7803   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
7804       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
7805     goto corrupt_file;
7806
7807   if (!qtdemux->got_moov) {
7808     if (qtdemux_find_stream (qtdemux, track_id))
7809       goto existing_stream;
7810     stream = _create_stream ();
7811     stream->track_id = track_id;
7812     new_stream = TRUE;
7813   } else {
7814     stream = qtdemux_find_stream (qtdemux, track_id);
7815     if (!stream) {
7816       GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
7817       goto skip_track;
7818     }
7819   }
7820
7821   if (stream->pending_tags == NULL)
7822     stream->pending_tags = gst_tag_list_new_empty ();
7823
7824   if ((tkhd_flags & 1) == 0)
7825     stream->disabled = TRUE;
7826
7827   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
7828       tkhd_version, tkhd_flags, stream->track_id);
7829
7830   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
7831     goto corrupt_file;
7832
7833   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
7834     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
7835     if (qtdemux->major_brand != FOURCC_mjp2 ||
7836         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
7837       goto corrupt_file;
7838   }
7839
7840   len = QT_UINT32 ((guint8 *) mdhd->data);
7841   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
7842   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
7843   if (version == 0x01000000) {
7844     if (len < 38)
7845       goto corrupt_file;
7846     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
7847     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
7848     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
7849   } else {
7850     if (len < 30)
7851       goto corrupt_file;
7852     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
7853     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
7854     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
7855   }
7856
7857   if (lang_code < 0x400) {
7858     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
7859   } else if (lang_code == 0x7fff) {
7860     stream->lang_id[0] = 0;     /* unspecified */
7861   } else {
7862     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
7863     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
7864     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
7865     stream->lang_id[3] = 0;
7866   }
7867
7868   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
7869       stream->timescale);
7870   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
7871       stream->duration);
7872   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
7873       lang_code, stream->lang_id);
7874
7875   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
7876     goto corrupt_file;
7877
7878   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
7879     /* chapters track reference */
7880     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
7881     if (chap) {
7882       gsize length = GST_READ_UINT32_BE (chap->data);
7883       if (qtdemux->chapters_track_id)
7884         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
7885
7886       if (length >= 12) {
7887         qtdemux->chapters_track_id =
7888             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
7889       }
7890     }
7891   }
7892
7893   /* fragmented files may have bogus duration in moov */
7894   if (!qtdemux->fragmented &&
7895       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
7896     guint64 tdur1, tdur2;
7897
7898     /* don't overflow */
7899     tdur1 = stream->timescale * (guint64) qtdemux->duration;
7900     tdur2 = qtdemux->timescale * (guint64) stream->duration;
7901
7902     /* HACK:
7903      * some of those trailers, nowadays, have prologue images that are
7904      * themselves vide tracks as well. I haven't really found a way to
7905      * identify those yet, except for just looking at their duration. */
7906     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
7907       GST_WARNING_OBJECT (qtdemux,
7908           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
7909           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
7910           "found, assuming preview image or something; skipping track",
7911           stream->duration, stream->timescale, qtdemux->duration,
7912           qtdemux->timescale);
7913       g_free (stream);
7914       return TRUE;
7915     }
7916   }
7917
7918   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
7919     goto corrupt_file;
7920
7921   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
7922       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
7923
7924   len = QT_UINT32 ((guint8 *) hdlr->data);
7925   if (len >= 20)
7926     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
7927   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
7928       GST_FOURCC_ARGS (stream->subtype));
7929
7930   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
7931     goto corrupt_file;
7932
7933   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
7934     goto corrupt_file;
7935
7936   /*parse svmi header if existing */
7937   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
7938   if (svmi) {
7939     len = QT_UINT32 ((guint8 *) svmi->data);
7940     version = QT_UINT32 ((guint8 *) svmi->data + 8);
7941     if (!version) {
7942       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
7943       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
7944       guint8 frame_type, frame_layout;
7945
7946       /* MPEG-A stereo video */
7947       if (qtdemux->major_brand == FOURCC_ss02)
7948         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
7949
7950       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
7951       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
7952       switch (frame_type) {
7953         case 0:
7954           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
7955           break;
7956         case 1:
7957           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
7958           break;
7959         case 2:
7960           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
7961           break;
7962         case 3:
7963           /* mode 3 is primary/secondary view sequence, ie
7964            * left/right views in separate tracks. See section 7.2
7965            * of ISO/IEC 23000-11:2009 */
7966           GST_FIXME_OBJECT (qtdemux,
7967               "Implement stereo video in separate streams");
7968       }
7969
7970       if ((frame_layout & 0x1) == 0)
7971         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
7972
7973       GST_LOG_OBJECT (qtdemux,
7974           "StereoVideo: composition type: %u, is_left_first: %u",
7975           frame_type, frame_layout);
7976       stream->multiview_mode = mode;
7977       stream->multiview_flags = flags;
7978     }
7979   }
7980
7981   /* parse stsd */
7982   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
7983     goto corrupt_file;
7984   stsd_data = (const guint8 *) stsd->data;
7985
7986   /* stsd should at least have one entry */
7987   stsd_len = QT_UINT32 (stsd_data);
7988   if (stsd_len < 24) {
7989     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
7990     if (stream->subtype == FOURCC_vivo) {
7991       g_free (stream);
7992       return TRUE;
7993     } else {
7994       goto corrupt_file;
7995     }
7996   }
7997
7998   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
7999
8000   /* and that entry should fit within stsd */
8001   len = QT_UINT32 (stsd_data + 16);
8002   if (len > stsd_len + 16)
8003     goto corrupt_file;
8004
8005   stream->fourcc = fourcc = QT_FOURCC (stsd_data + 16 + 4);
8006   GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
8007       GST_FOURCC_ARGS (stream->fourcc));
8008   GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
8009
8010   if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi) ||
8011       ((fourcc & 0x00FFFFFF) == GST_MAKE_FOURCC ('e', 'n', 'c', 0)))
8012     goto error_encrypted;
8013
8014   if (stream->subtype == FOURCC_vide) {
8015     guint32 w = 0, h = 0;
8016     gboolean gray;
8017     gint depth, palette_size, palette_count;
8018     guint32 matrix[9];
8019     guint32 *palette_data = NULL;
8020
8021     stream->sampled = TRUE;
8022
8023     /* version 1 uses some 64-bit ints */
8024     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
8025       goto corrupt_file;
8026
8027     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
8028       goto corrupt_file;
8029
8030     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
8031         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
8032       goto corrupt_file;
8033
8034     stream->display_width = w >> 16;
8035     stream->display_height = h >> 16;
8036
8037     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
8038         &stream->pending_tags);
8039
8040     offset = 16;
8041     if (len < 86)
8042       goto corrupt_file;
8043
8044     stream->width = QT_UINT16 (stsd_data + offset + 32);
8045     stream->height = QT_UINT16 (stsd_data + offset + 34);
8046     stream->fps_n = 0;          /* this is filled in later */
8047     stream->fps_d = 0;          /* this is filled in later */
8048     stream->bits_per_sample = QT_UINT16 (stsd_data + offset + 82);
8049     stream->color_table_id = QT_UINT16 (stsd_data + offset + 84);
8050
8051     GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
8052         stream->width, stream->height, stream->bits_per_sample,
8053         stream->color_table_id);
8054
8055     depth = stream->bits_per_sample;
8056
8057     /* more than 32 bits means grayscale */
8058     gray = (depth > 32);
8059     /* low 32 bits specify the depth  */
8060     depth &= 0x1F;
8061
8062     /* different number of palette entries is determined by depth. */
8063     palette_count = 0;
8064     if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
8065       palette_count = (1 << depth);
8066     palette_size = palette_count * 4;
8067
8068     if (stream->color_table_id) {
8069       switch (palette_count) {
8070         case 0:
8071           break;
8072         case 2:
8073           palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
8074           break;
8075         case 4:
8076           palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
8077           break;
8078         case 16:
8079           if (gray)
8080             palette_data = g_memdup (ff_qt_grayscale_palette_16, palette_size);
8081           else
8082             palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
8083           break;
8084         case 256:
8085           if (gray)
8086             palette_data = g_memdup (ff_qt_grayscale_palette_256, palette_size);
8087           else
8088             palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
8089           break;
8090         default:
8091           GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
8092               (_("The video in this file might not play correctly.")),
8093               ("unsupported palette depth %d", depth));
8094           break;
8095       }
8096     } else {
8097       gint i, j, start, end;
8098
8099       if (len < 94)
8100         goto corrupt_file;
8101
8102       /* read table */
8103       start = QT_UINT32 (stsd_data + offset + 86);
8104       palette_count = QT_UINT16 (stsd_data + offset + 90);
8105       end = QT_UINT16 (stsd_data + offset + 92);
8106
8107       GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
8108           start, end, palette_count);
8109
8110       if (end > 255)
8111         end = 255;
8112       if (start > end)
8113         start = end;
8114
8115       if (len < 94 + (end - start) * 8)
8116         goto corrupt_file;
8117
8118       /* palette is always the same size */
8119       palette_data = g_malloc0 (256 * 4);
8120       palette_size = 256 * 4;
8121
8122       for (j = 0, i = start; i <= end; j++, i++) {
8123         guint32 a, r, g, b;
8124
8125         a = QT_UINT16 (stsd_data + offset + 94 + (j * 8));
8126         r = QT_UINT16 (stsd_data + offset + 96 + (j * 8));
8127         g = QT_UINT16 (stsd_data + offset + 98 + (j * 8));
8128         b = QT_UINT16 (stsd_data + offset + 100 + (j * 8));
8129
8130         palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
8131             (g & 0xff00) | (b >> 8);
8132       }
8133     }
8134
8135     stream->caps =
8136         qtdemux_video_caps (qtdemux, stream, fourcc, stsd_data, &codec);
8137     if (G_UNLIKELY (!stream->caps)) {
8138       g_free (palette_data);
8139       goto unknown_stream;
8140     }
8141
8142     if (codec) {
8143       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
8144           GST_TAG_VIDEO_CODEC, codec, NULL);
8145       g_free (codec);
8146       codec = NULL;
8147     }
8148
8149
8150     if (palette_data) {
8151       GstStructure *s;
8152
8153       if (stream->rgb8_palette)
8154         gst_memory_unref (stream->rgb8_palette);
8155       stream->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
8156           palette_data, palette_size, 0, palette_size, palette_data, g_free);
8157
8158       s = gst_caps_get_structure (stream->caps, 0);
8159
8160       /* non-raw video has a palette_data property. raw video has the palette as
8161        * an extra plane that we append to the output buffers before we push
8162        * them*/
8163       if (!gst_structure_has_name (s, "video/x-raw")) {
8164         GstBuffer *palette;
8165
8166         palette = gst_buffer_new ();
8167         gst_buffer_append_memory (palette, stream->rgb8_palette);
8168         stream->rgb8_palette = NULL;
8169
8170         gst_caps_set_simple (stream->caps, "palette_data",
8171             GST_TYPE_BUFFER, palette, NULL);
8172         gst_buffer_unref (palette);
8173       }
8174     } else if (palette_count != 0) {
8175       GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
8176           (NULL), ("Unsupported palette depth %d", depth));
8177     }
8178
8179     GST_LOG_OBJECT (qtdemux, "frame count:   %u",
8180         QT_UINT16 (stsd_data + offset + 48));
8181
8182     esds = NULL;
8183     pasp = NULL;
8184     /* pick 'the' stsd child */
8185     mp4v = qtdemux_tree_get_child_by_type (stsd, fourcc);
8186     if (mp4v) {
8187       esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
8188       pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
8189     }
8190
8191     if (pasp) {
8192       const guint8 *pasp_data = (const guint8 *) pasp->data;
8193
8194       stream->par_w = QT_UINT32 (pasp_data + 8);
8195       stream->par_h = QT_UINT32 (pasp_data + 12);
8196     } else {
8197       stream->par_w = 0;
8198       stream->par_h = 0;
8199     }
8200
8201     if (esds) {
8202       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
8203     } else {
8204       switch (fourcc) {
8205         case FOURCC_H264:
8206         case FOURCC_avc1:
8207         case FOURCC_avc3:
8208         {
8209           gint len = QT_UINT32 (stsd_data) - 0x66;
8210           const guint8 *avc_data = stsd_data + 0x66;
8211
8212           /* find avcC */
8213           while (len >= 0x8) {
8214             gint size;
8215
8216             if (QT_UINT32 (avc_data) <= len)
8217               size = QT_UINT32 (avc_data) - 0x8;
8218             else
8219               size = len - 0x8;
8220
8221             if (size < 1)
8222               /* No real data, so break out */
8223               break;
8224
8225             switch (QT_FOURCC (avc_data + 0x4)) {
8226               case FOURCC_avcC:
8227               {
8228                 /* parse, if found */
8229                 GstBuffer *buf;
8230
8231                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
8232
8233                 /* First 4 bytes are the length of the atom, the next 4 bytes
8234                  * are the fourcc, the next 1 byte is the version, and the
8235                  * subsequent bytes are profile_tier_level structure like data. */
8236                 gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
8237                     avc_data + 8 + 1, size - 1);
8238                 buf = gst_buffer_new_and_alloc (size);
8239                 gst_buffer_fill (buf, 0, avc_data + 0x8, size);
8240                 gst_caps_set_simple (stream->caps,
8241                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
8242                 gst_buffer_unref (buf);
8243
8244                 break;
8245               }
8246               case FOURCC_strf:
8247               {
8248                 GstBuffer *buf;
8249
8250                 GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
8251
8252                 /* First 4 bytes are the length of the atom, the next 4 bytes
8253                  * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
8254                  * next 1 byte is the version, and the
8255                  * subsequent bytes are sequence parameter set like data. */
8256
8257                 size -= 40;     /* we'll be skipping BITMAPINFOHEADER */
8258                 if (size > 1) {
8259                   gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
8260                       avc_data + 8 + 40 + 1, size - 1);
8261
8262                   buf = gst_buffer_new_and_alloc (size);
8263                   gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
8264                   gst_caps_set_simple (stream->caps,
8265                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
8266                   gst_buffer_unref (buf);
8267                 }
8268                 break;
8269               }
8270               case FOURCC_btrt:
8271               {
8272                 guint avg_bitrate, max_bitrate;
8273
8274                 /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
8275                 if (size < 12)
8276                   break;
8277
8278                 max_bitrate = QT_UINT32 (avc_data + 0xc);
8279                 avg_bitrate = QT_UINT32 (avc_data + 0x10);
8280
8281                 if (!max_bitrate && !avg_bitrate)
8282                   break;
8283
8284                 /* Some muxers seem to swap the average and maximum bitrates
8285                  * (I'm looking at you, YouTube), so we swap for sanity. */
8286                 if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
8287                   guint temp = avg_bitrate;
8288
8289                   avg_bitrate = max_bitrate;
8290                   max_bitrate = temp;
8291                 }
8292
8293                 if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
8294                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
8295                       GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
8296                 }
8297                 if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
8298                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
8299                       GST_TAG_BITRATE, avg_bitrate, NULL);
8300                 }
8301
8302                 break;
8303               }
8304
8305               default:
8306                 break;
8307             }
8308
8309             len -= size + 8;
8310             avc_data += size + 8;
8311           }
8312
8313           break;
8314         }
8315         case FOURCC_H265:
8316         case FOURCC_hvc1:
8317         case FOURCC_hev1:
8318         {
8319           gint len = QT_UINT32 (stsd_data) - 0x66;
8320           const guint8 *hevc_data = stsd_data + 0x66;
8321
8322           /* find hevc */
8323           while (len >= 0x8) {
8324             gint size;
8325
8326             if (QT_UINT32 (hevc_data) <= len)
8327               size = QT_UINT32 (hevc_data) - 0x8;
8328             else
8329               size = len - 0x8;
8330
8331             if (size < 1)
8332               /* No real data, so break out */
8333               break;
8334
8335             switch (QT_FOURCC (hevc_data + 0x4)) {
8336               case FOURCC_hvcC:
8337               {
8338                 /* parse, if found */
8339                 GstBuffer *buf;
8340
8341                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
8342
8343                 /* First 4 bytes are the length of the atom, the next 4 bytes
8344                  * are the fourcc, the next 1 byte is the version, and the
8345                  * subsequent bytes are sequence parameter set like data. */
8346                 gst_codec_utils_h265_caps_set_level_tier_and_profile
8347                     (stream->caps, hevc_data + 8 + 1, size - 1);
8348
8349                 buf = gst_buffer_new_and_alloc (size);
8350                 gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
8351                 gst_caps_set_simple (stream->caps,
8352                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
8353                 gst_buffer_unref (buf);
8354                 break;
8355               }
8356               default:
8357                 break;
8358             }
8359             len -= size + 8;
8360             hevc_data += size + 8;
8361           }
8362           break;
8363         }
8364         case FOURCC_mp4v:
8365         case FOURCC_MP4V:
8366         case FOURCC_fmp4:
8367         case FOURCC_FMP4:
8368         {
8369           GNode *glbl;
8370
8371           GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
8372               GST_FOURCC_ARGS (fourcc));
8373
8374           /* codec data might be in glbl extension atom */
8375           glbl = mp4v ?
8376               qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
8377           if (glbl) {
8378             guint8 *data;
8379             GstBuffer *buf;
8380             gint len;
8381
8382             GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
8383             data = glbl->data;
8384             len = QT_UINT32 (data);
8385             if (len > 0x8) {
8386               len -= 0x8;
8387               buf = gst_buffer_new_and_alloc (len);
8388               gst_buffer_fill (buf, 0, data + 8, len);
8389               gst_caps_set_simple (stream->caps,
8390                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
8391               gst_buffer_unref (buf);
8392             }
8393           }
8394           break;
8395         }
8396         case FOURCC_mjp2:
8397         {
8398           /* see annex I of the jpeg2000 spec */
8399           GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
8400           const guint8 *data;
8401           const gchar *colorspace = NULL;
8402           gint ncomp = 0;
8403           guint32 ncomp_map = 0;
8404           gint32 *comp_map = NULL;
8405           guint32 nchan_def = 0;
8406           gint32 *chan_def = NULL;
8407
8408           GST_DEBUG_OBJECT (qtdemux, "found mjp2");
8409           /* some required atoms */
8410           mjp2 = qtdemux_tree_get_child_by_type (stsd, FOURCC_mjp2);
8411           if (!mjp2)
8412             break;
8413           jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
8414           if (!jp2h)
8415             break;
8416
8417           /* number of components; redundant with info in codestream, but useful
8418              to a muxer */
8419           ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
8420           if (!ihdr || QT_UINT32 (ihdr->data) != 22)
8421             break;
8422           ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
8423
8424           colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
8425           if (!colr)
8426             break;
8427           GST_DEBUG_OBJECT (qtdemux, "found colr");
8428           /* extract colour space info */
8429           if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
8430             switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
8431               case 16:
8432                 colorspace = "sRGB";
8433                 break;
8434               case 17:
8435                 colorspace = "GRAY";
8436                 break;
8437               case 18:
8438                 colorspace = "sYUV";
8439                 break;
8440               default:
8441                 colorspace = NULL;
8442                 break;
8443             }
8444           }
8445           if (!colorspace)
8446             /* colr is required, and only values 16, 17, and 18 are specified,
8447                so error if we have no colorspace */
8448             break;
8449
8450           /* extract component mapping */
8451           cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
8452           if (cmap) {
8453             guint32 cmap_len = 0;
8454             int i;
8455             cmap_len = QT_UINT32 (cmap->data);
8456             if (cmap_len >= 8) {
8457               /* normal box, subtract off header */
8458               cmap_len -= 8;
8459               /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
8460               if (cmap_len % 4 == 0) {
8461                 ncomp_map = (cmap_len / 4);
8462                 comp_map = g_new0 (gint32, ncomp_map);
8463                 for (i = 0; i < ncomp_map; i++) {
8464                   guint16 cmp;
8465                   guint8 mtyp, pcol;
8466                   cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
8467                   mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
8468                   pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
8469                   comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
8470                 }
8471               }
8472             }
8473           }
8474           /* extract channel definitions */
8475           cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
8476           if (cdef) {
8477             guint32 cdef_len = 0;
8478             int i;
8479             cdef_len = QT_UINT32 (cdef->data);
8480             if (cdef_len >= 10) {
8481               /* normal box, subtract off header and len */
8482               cdef_len -= 10;
8483               /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
8484               if (cdef_len % 6 == 0) {
8485                 nchan_def = (cdef_len / 6);
8486                 chan_def = g_new0 (gint32, nchan_def);
8487                 for (i = 0; i < nchan_def; i++)
8488                   chan_def[i] = -1;
8489                 for (i = 0; i < nchan_def; i++) {
8490                   guint16 cn, typ, asoc;
8491                   cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
8492                   typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
8493                   asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
8494                   if (cn < nchan_def) {
8495                     switch (typ) {
8496                       case 0:
8497                         chan_def[cn] = asoc;
8498                         break;
8499                       case 1:
8500                         chan_def[cn] = 0;       /* alpha */
8501                         break;
8502                       default:
8503                         chan_def[cn] = -typ;
8504                     }
8505                   }
8506                 }
8507               }
8508             }
8509           }
8510
8511           gst_caps_set_simple (stream->caps,
8512               "num-components", G_TYPE_INT, ncomp, NULL);
8513           gst_caps_set_simple (stream->caps,
8514               "colorspace", G_TYPE_STRING, colorspace, NULL);
8515
8516           if (comp_map) {
8517             GValue arr = { 0, };
8518             GValue elt = { 0, };
8519             int i;
8520             g_value_init (&arr, GST_TYPE_ARRAY);
8521             g_value_init (&elt, G_TYPE_INT);
8522             for (i = 0; i < ncomp_map; i++) {
8523               g_value_set_int (&elt, comp_map[i]);
8524               gst_value_array_append_value (&arr, &elt);
8525             }
8526             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
8527                 "component-map", &arr);
8528             g_value_unset (&elt);
8529             g_value_unset (&arr);
8530             g_free (comp_map);
8531           }
8532
8533           if (chan_def) {
8534             GValue arr = { 0, };
8535             GValue elt = { 0, };
8536             int i;
8537             g_value_init (&arr, GST_TYPE_ARRAY);
8538             g_value_init (&elt, G_TYPE_INT);
8539             for (i = 0; i < nchan_def; i++) {
8540               g_value_set_int (&elt, chan_def[i]);
8541               gst_value_array_append_value (&arr, &elt);
8542             }
8543             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
8544                 "channel-definitions", &arr);
8545             g_value_unset (&elt);
8546             g_value_unset (&arr);
8547             g_free (chan_def);
8548           }
8549
8550           /* some optional atoms */
8551           field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
8552           prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
8553
8554           /* indicate possible fields in caps */
8555           if (field) {
8556             data = (guint8 *) field->data + 8;
8557             if (*data != 1)
8558               gst_caps_set_simple (stream->caps, "fields", G_TYPE_INT,
8559                   (gint) * data, NULL);
8560           }
8561           /* add codec_data if provided */
8562           if (prefix) {
8563             GstBuffer *buf;
8564             gint len;
8565
8566             GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
8567             data = prefix->data;
8568             len = QT_UINT32 (data);
8569             if (len > 0x8) {
8570               len -= 0x8;
8571               buf = gst_buffer_new_and_alloc (len);
8572               gst_buffer_fill (buf, 0, data + 8, len);
8573               gst_caps_set_simple (stream->caps,
8574                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
8575               gst_buffer_unref (buf);
8576             }
8577           }
8578           break;
8579         }
8580         case FOURCC_SVQ3:
8581         case FOURCC_VP31:
8582         {
8583           GstBuffer *buf;
8584           GstBuffer *seqh = NULL;
8585           guint8 *gamma_data = NULL;
8586           gint len = QT_UINT32 (stsd_data);
8587
8588           qtdemux_parse_svq3_stsd_data (qtdemux, stsd, &gamma_data, &seqh);
8589           if (gamma_data) {
8590             gst_caps_set_simple (stream->caps, "applied-gamma", G_TYPE_DOUBLE,
8591                 QT_FP32 (gamma_data), NULL);
8592           }
8593           if (seqh) {
8594             /* sorry for the bad name, but we don't know what this is, other
8595              * than its own fourcc */
8596             gst_caps_set_simple (stream->caps, "seqh", GST_TYPE_BUFFER, seqh,
8597                 NULL);
8598           }
8599
8600           GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
8601           buf = gst_buffer_new_and_alloc (len);
8602           gst_buffer_fill (buf, 0, stsd_data, len);
8603           gst_caps_set_simple (stream->caps,
8604               "codec_data", GST_TYPE_BUFFER, buf, NULL);
8605           gst_buffer_unref (buf);
8606           break;
8607         }
8608         case FOURCC_rle_:
8609         case FOURCC_WRLE:
8610         {
8611           gst_caps_set_simple (stream->caps,
8612               "depth", G_TYPE_INT, QT_UINT16 (stsd_data + offset + 82), NULL);
8613           break;
8614         }
8615         case FOURCC_XiTh:
8616         {
8617           GNode *xith, *xdxt;
8618
8619           GST_DEBUG_OBJECT (qtdemux, "found XiTh");
8620           xith = qtdemux_tree_get_child_by_type (stsd, FOURCC_XiTh);
8621           if (!xith)
8622             break;
8623
8624           xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
8625           if (!xdxt)
8626             break;
8627
8628           GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
8629           /* collect the headers and store them in a stream list so that we can
8630            * send them out first */
8631           qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
8632           break;
8633         }
8634         case FOURCC_ovc1:
8635         {
8636           GNode *ovc1;
8637           guint8 *ovc1_data;
8638           guint ovc1_len;
8639           GstBuffer *buf;
8640
8641           GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
8642           ovc1 = qtdemux_tree_get_child_by_type (stsd, FOURCC_ovc1);
8643           if (!ovc1)
8644             break;
8645           ovc1_data = ovc1->data;
8646           ovc1_len = QT_UINT32 (ovc1_data);
8647           if (ovc1_len <= 198) {
8648             GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
8649             break;
8650           }
8651           buf = gst_buffer_new_and_alloc (ovc1_len - 198);
8652           gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
8653           gst_caps_set_simple (stream->caps,
8654               "codec_data", GST_TYPE_BUFFER, buf, NULL);
8655           gst_buffer_unref (buf);
8656           break;
8657         }
8658         case GST_MAKE_FOURCC ('v', 'c', '-', '1'):
8659         {
8660           gint len = QT_UINT32 (stsd_data) - 0x66;
8661           const guint8 *vc1_data = stsd_data + 0x66;
8662
8663           /* find dvc1 */
8664           while (len >= 8) {
8665             gint size;
8666
8667             if (QT_UINT32 (vc1_data) <= len)
8668               size = QT_UINT32 (vc1_data) - 8;
8669             else
8670               size = len - 8;
8671
8672             if (size < 1)
8673               /* No real data, so break out */
8674               break;
8675
8676             switch (QT_FOURCC (vc1_data + 0x4)) {
8677               case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
8678               {
8679                 GstBuffer *buf;
8680
8681                 GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
8682                 buf = gst_buffer_new_and_alloc (size);
8683                 gst_buffer_fill (buf, 0, vc1_data + 8, size);
8684                 gst_caps_set_simple (stream->caps,
8685                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
8686                 gst_buffer_unref (buf);
8687                 break;
8688               }
8689               default:
8690                 break;
8691             }
8692             len -= size + 8;
8693             vc1_data += size + 8;
8694           }
8695           break;
8696         }
8697         default:
8698           break;
8699       }
8700     }
8701
8702     GST_INFO_OBJECT (qtdemux,
8703         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
8704         GST_FOURCC_ARGS (fourcc), stream->caps);
8705
8706   } else if (stream->subtype == FOURCC_soun) {
8707     int version, samplesize;
8708     guint16 compression_id;
8709     gboolean amrwb = FALSE;
8710
8711     offset = 32;
8712     /* sample description entry (16) + sound sample description v0 (20) */
8713     if (len < 36)
8714       goto corrupt_file;
8715
8716     version = QT_UINT32 (stsd_data + offset);
8717     stream->n_channels = QT_UINT16 (stsd_data + offset + 8);
8718     samplesize = QT_UINT16 (stsd_data + offset + 10);
8719     compression_id = QT_UINT16 (stsd_data + offset + 12);
8720     stream->rate = QT_FP32 (stsd_data + offset + 16);
8721
8722     GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
8723     GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
8724         QT_UINT32 (stsd_data + offset + 4));
8725     GST_LOG_OBJECT (qtdemux, "n_channels:       %d", stream->n_channels);
8726     GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
8727     GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
8728     GST_LOG_OBJECT (qtdemux, "packet size:      %d",
8729         QT_UINT16 (stsd_data + offset + 14));
8730     GST_LOG_OBJECT (qtdemux, "sample rate:      %g", stream->rate);
8731
8732     if (compression_id == 0xfffe)
8733       stream->sampled = TRUE;
8734
8735     /* first assume uncompressed audio */
8736     stream->bytes_per_sample = samplesize / 8;
8737     stream->samples_per_frame = stream->n_channels;
8738     stream->bytes_per_frame = stream->n_channels * stream->bytes_per_sample;
8739     stream->samples_per_packet = stream->samples_per_frame;
8740     stream->bytes_per_packet = stream->bytes_per_sample;
8741
8742     offset = 52;
8743     switch (fourcc) {
8744         /* Yes, these have to be hard-coded */
8745       case FOURCC_MAC6:
8746       {
8747         stream->samples_per_packet = 6;
8748         stream->bytes_per_packet = 1;
8749         stream->bytes_per_frame = 1 * stream->n_channels;
8750         stream->bytes_per_sample = 1;
8751         stream->samples_per_frame = 6 * stream->n_channels;
8752         break;
8753       }
8754       case FOURCC_MAC3:
8755       {
8756         stream->samples_per_packet = 3;
8757         stream->bytes_per_packet = 1;
8758         stream->bytes_per_frame = 1 * stream->n_channels;
8759         stream->bytes_per_sample = 1;
8760         stream->samples_per_frame = 3 * stream->n_channels;
8761         break;
8762       }
8763       case FOURCC_ima4:
8764       {
8765         stream->samples_per_packet = 64;
8766         stream->bytes_per_packet = 34;
8767         stream->bytes_per_frame = 34 * stream->n_channels;
8768         stream->bytes_per_sample = 2;
8769         stream->samples_per_frame = 64 * stream->n_channels;
8770         break;
8771       }
8772       case FOURCC_ulaw:
8773       case FOURCC_alaw:
8774       {
8775         stream->samples_per_packet = 1;
8776         stream->bytes_per_packet = 1;
8777         stream->bytes_per_frame = 1 * stream->n_channels;
8778         stream->bytes_per_sample = 1;
8779         stream->samples_per_frame = 1 * stream->n_channels;
8780         break;
8781       }
8782       case FOURCC_agsm:
8783       {
8784         stream->samples_per_packet = 160;
8785         stream->bytes_per_packet = 33;
8786         stream->bytes_per_frame = 33 * stream->n_channels;
8787         stream->bytes_per_sample = 2;
8788         stream->samples_per_frame = 160 * stream->n_channels;
8789         break;
8790       }
8791       default:
8792         break;
8793     }
8794
8795     if (version == 0x00010000) {
8796       /* sample description entry (16) + sound sample description v1 (20+16) */
8797       if (len < 52)
8798         goto corrupt_file;
8799
8800       switch (fourcc) {
8801         case FOURCC_twos:
8802         case FOURCC_sowt:
8803         case FOURCC_raw_:
8804           break;
8805         default:
8806         {
8807           /* only parse extra decoding config for non-pcm audio */
8808           stream->samples_per_packet = QT_UINT32 (stsd_data + offset);
8809           stream->bytes_per_packet = QT_UINT32 (stsd_data + offset + 4);
8810           stream->bytes_per_frame = QT_UINT32 (stsd_data + offset + 8);
8811           stream->bytes_per_sample = QT_UINT32 (stsd_data + offset + 12);
8812
8813           GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
8814               stream->samples_per_packet);
8815           GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
8816               stream->bytes_per_packet);
8817           GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
8818               stream->bytes_per_frame);
8819           GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
8820               stream->bytes_per_sample);
8821
8822           if (!stream->sampled && stream->bytes_per_packet) {
8823             stream->samples_per_frame = (stream->bytes_per_frame /
8824                 stream->bytes_per_packet) * stream->samples_per_packet;
8825             GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
8826                 stream->samples_per_frame);
8827           }
8828           break;
8829         }
8830       }
8831     } else if (version == 0x00020000) {
8832       union
8833       {
8834         gdouble fp;
8835         guint64 val;
8836       } qtfp;
8837
8838       /* sample description entry (16) + sound sample description v2 (56) */
8839       if (len < 72)
8840         goto corrupt_file;
8841
8842       qtfp.val = QT_UINT64 (stsd_data + offset + 4);
8843       stream->rate = qtfp.fp;
8844       stream->n_channels = QT_UINT32 (stsd_data + offset + 12);
8845
8846       GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
8847       GST_LOG_OBJECT (qtdemux, "sample rate:        %g", stream->rate);
8848       GST_LOG_OBJECT (qtdemux, "n_channels:         %d", stream->n_channels);
8849       GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
8850           QT_UINT32 (stsd_data + offset + 20));
8851       GST_LOG_OBJECT (qtdemux, "format flags:       %X",
8852           QT_UINT32 (stsd_data + offset + 24));
8853       GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
8854           QT_UINT32 (stsd_data + offset + 28));
8855       GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
8856           QT_UINT32 (stsd_data + offset + 32));
8857     } else if (version != 0x00000) {
8858       GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x", version);
8859     }
8860
8861     stream->caps = qtdemux_audio_caps (qtdemux, stream, fourcc,
8862         stsd_data + 32, len - 16, &codec);
8863
8864     switch (fourcc) {
8865       case FOURCC_in24:
8866       {
8867         GNode *enda;
8868         GNode *in24;
8869
8870         in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
8871
8872         enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
8873         if (!enda) {
8874           wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
8875           if (wave)
8876             enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
8877         }
8878         if (enda) {
8879           int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
8880           gst_caps_set_simple (stream->caps,
8881               "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE", NULL);
8882         }
8883         break;
8884       }
8885       case FOURCC_owma:
8886       {
8887         GNode *owma;
8888         const guint8 *owma_data;
8889         const gchar *codec_name = NULL;
8890         guint owma_len;
8891         GstBuffer *buf;
8892         gint version = 1;
8893         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
8894         /* FIXME this should also be gst_riff_strf_auds,
8895          * but the latter one is actually missing bits-per-sample :( */
8896         typedef struct
8897         {
8898           gint16 wFormatTag;
8899           gint16 nChannels;
8900           gint32 nSamplesPerSec;
8901           gint32 nAvgBytesPerSec;
8902           gint16 nBlockAlign;
8903           gint16 wBitsPerSample;
8904           gint16 cbSize;
8905         } WAVEFORMATEX;
8906         WAVEFORMATEX *wfex;
8907
8908         GST_DEBUG_OBJECT (qtdemux, "parse owma");
8909         owma = qtdemux_tree_get_child_by_type (stsd, FOURCC_owma);
8910         if (!owma)
8911           break;
8912         owma_data = owma->data;
8913         owma_len = QT_UINT32 (owma_data);
8914         if (owma_len <= 54) {
8915           GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
8916           break;
8917         }
8918         wfex = (WAVEFORMATEX *) (owma_data + 36);
8919         buf = gst_buffer_new_and_alloc (owma_len - 54);
8920         gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
8921         if (wfex->wFormatTag == 0x0161) {
8922           codec_name = "Windows Media Audio";
8923           version = 2;
8924         } else if (wfex->wFormatTag == 0x0162) {
8925           codec_name = "Windows Media Audio 9 Pro";
8926           version = 3;
8927         } else if (wfex->wFormatTag == 0x0163) {
8928           codec_name = "Windows Media Audio 9 Lossless";
8929           /* is that correct? gstffmpegcodecmap.c is missing it, but
8930            * fluendo codec seems to support it */
8931           version = 4;
8932         }
8933
8934         gst_caps_set_simple (stream->caps,
8935             "codec_data", GST_TYPE_BUFFER, buf,
8936             "wmaversion", G_TYPE_INT, version,
8937             "block_align", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->nBlockAlign),
8938             "bitrate", G_TYPE_INT, GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec),
8939             "width", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
8940             "depth", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
8941             NULL);
8942         gst_buffer_unref (buf);
8943
8944         if (codec_name) {
8945           g_free (codec);
8946           codec = g_strdup (codec_name);
8947         }
8948         break;
8949       }
8950       case GST_MAKE_FOURCC ('w', 'm', 'a', ' '):
8951       {
8952         gint len = QT_UINT32 (stsd_data) - offset;
8953         const guint8 *wfex_data = stsd_data + offset;
8954         const gchar *codec_name = NULL;
8955         gint version = 1;
8956         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
8957         /* FIXME this should also be gst_riff_strf_auds,
8958          * but the latter one is actually missing bits-per-sample :( */
8959         typedef struct
8960         {
8961           gint16 wFormatTag;
8962           gint16 nChannels;
8963           gint32 nSamplesPerSec;
8964           gint32 nAvgBytesPerSec;
8965           gint16 nBlockAlign;
8966           gint16 wBitsPerSample;
8967           gint16 cbSize;
8968         } WAVEFORMATEX;
8969         WAVEFORMATEX wfex;
8970
8971         /* FIXME: unify with similar wavformatex parsing code above */
8972         GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
8973
8974         /* find wfex */
8975         while (len >= 8) {
8976           gint size;
8977
8978           if (QT_UINT32 (wfex_data) <= len)
8979             size = QT_UINT32 (wfex_data) - 8;
8980           else
8981             size = len - 8;
8982
8983           if (size < 1)
8984             /* No real data, so break out */
8985             break;
8986
8987           switch (QT_FOURCC (wfex_data + 4)) {
8988             case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
8989             {
8990               GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
8991
8992               if (size < 8 + 18)
8993                 break;
8994
8995               wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
8996               wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
8997               wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
8998               wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
8999               wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
9000               wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
9001               wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
9002
9003               GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
9004               GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
9005                   "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
9006                   "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
9007                   wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
9008                   wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
9009
9010               if (wfex.wFormatTag == 0x0161) {
9011                 codec_name = "Windows Media Audio";
9012                 version = 2;
9013               } else if (wfex.wFormatTag == 0x0162) {
9014                 codec_name = "Windows Media Audio 9 Pro";
9015                 version = 3;
9016               } else if (wfex.wFormatTag == 0x0163) {
9017                 codec_name = "Windows Media Audio 9 Lossless";
9018                 /* is that correct? gstffmpegcodecmap.c is missing it, but
9019                  * fluendo codec seems to support it */
9020                 version = 4;
9021               }
9022
9023               gst_caps_set_simple (stream->caps,
9024                   "wmaversion", G_TYPE_INT, version,
9025                   "block_align", G_TYPE_INT, wfex.nBlockAlign,
9026                   "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
9027                   "width", G_TYPE_INT, wfex.wBitsPerSample,
9028                   "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
9029
9030               if (size > wfex.cbSize) {
9031                 GstBuffer *buf;
9032
9033                 buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
9034                 gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
9035                     size - wfex.cbSize);
9036                 gst_caps_set_simple (stream->caps,
9037                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9038                 gst_buffer_unref (buf);
9039               } else {
9040                 GST_WARNING_OBJECT (qtdemux, "no codec data");
9041               }
9042
9043               if (codec_name) {
9044                 g_free (codec);
9045                 codec = g_strdup (codec_name);
9046               }
9047               break;
9048             }
9049             default:
9050               break;
9051           }
9052           len -= size + 8;
9053           wfex_data += size + 8;
9054         }
9055         break;
9056       }
9057       default:
9058         break;
9059     }
9060
9061     if (codec) {
9062       GstStructure *s;
9063       gint bitrate = 0;
9064
9065       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9066           GST_TAG_AUDIO_CODEC, codec, NULL);
9067       g_free (codec);
9068       codec = NULL;
9069
9070       /* some bitrate info may have ended up in caps */
9071       s = gst_caps_get_structure (stream->caps, 0);
9072       gst_structure_get_int (s, "bitrate", &bitrate);
9073       if (bitrate > 0)
9074         gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9075             GST_TAG_BITRATE, bitrate, NULL);
9076     }
9077
9078     mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4a);
9079     wave = NULL;
9080     esds = NULL;
9081     if (mp4a) {
9082       wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
9083       if (wave)
9084         esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
9085       if (!esds)
9086         esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
9087     }
9088
9089
9090     /* If the fourcc's bottom 16 bits gives 'sm', then the top
9091        16 bits is a byte-swapped wave-style codec identifier,
9092        and we can find a WAVE header internally to a 'wave' atom here.
9093        This can more clearly be thought of as 'ms' as the top 16 bits, and a
9094        codec id as the bottom 16 bits - but byte-swapped to store in QT (which
9095        is big-endian).
9096      */
9097     if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
9098       if (len < offset + 20) {
9099         GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
9100       } else {
9101         guint32 datalen = QT_UINT32 (stsd_data + offset + 16);
9102         const guint8 *data = stsd_data + offset + 16;
9103         GNode *wavenode;
9104         GNode *waveheadernode;
9105
9106         wavenode = g_node_new ((guint8 *) data);
9107         if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
9108           const guint8 *waveheader;
9109           guint32 headerlen;
9110
9111           waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
9112           if (waveheadernode) {
9113             waveheader = (const guint8 *) waveheadernode->data;
9114             headerlen = QT_UINT32 (waveheader);
9115
9116             if (headerlen > 8) {
9117               gst_riff_strf_auds *header = NULL;
9118               GstBuffer *headerbuf;
9119               GstBuffer *extra;
9120
9121               waveheader += 8;
9122               headerlen -= 8;
9123
9124               headerbuf = gst_buffer_new_and_alloc (headerlen);
9125               gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
9126
9127               if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
9128                       headerbuf, &header, &extra)) {
9129                 gst_caps_unref (stream->caps);
9130                 /* FIXME: Need to do something with the channel reorder map */
9131                 stream->caps = gst_riff_create_audio_caps (header->format, NULL,
9132                     header, extra, NULL, NULL, NULL);
9133
9134                 if (extra)
9135                   gst_buffer_unref (extra);
9136                 g_free (header);
9137               }
9138             }
9139           } else
9140             GST_DEBUG ("Didn't find waveheadernode for this codec");
9141         }
9142         g_node_destroy (wavenode);
9143       }
9144     } else if (esds) {
9145       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
9146     } else {
9147       switch (fourcc) {
9148 #if 0
9149           /* FIXME: what is in the chunk? */
9150         case FOURCC_QDMC:
9151         {
9152           gint len = QT_UINT32 (stsd_data);
9153
9154           /* seems to be always = 116 = 0x74 */
9155           break;
9156         }
9157 #endif
9158         case FOURCC_QDM2:
9159         {
9160           gint len = QT_UINT32 (stsd_data);
9161
9162           if (len > 0x4C) {
9163             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x4C);
9164
9165             gst_buffer_fill (buf, 0, stsd_data + 0x4C, len - 0x4C);
9166             gst_caps_set_simple (stream->caps,
9167                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
9168             gst_buffer_unref (buf);
9169           }
9170           gst_caps_set_simple (stream->caps,
9171               "samplesize", G_TYPE_INT, samplesize, NULL);
9172           break;
9173         }
9174         case FOURCC_alac:
9175         {
9176           GNode *alac, *wave = NULL;
9177
9178           /* apparently, m4a has this atom appended directly in the stsd entry,
9179            * while mov has it in a wave atom */
9180           alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
9181           if (alac) {
9182             /* alac now refers to stsd entry atom */
9183             wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
9184             if (wave)
9185               alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
9186             else
9187               alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
9188           }
9189           if (alac) {
9190             const guint8 *alac_data = alac->data;
9191             gint len = QT_UINT32 (alac->data);
9192             GstBuffer *buf;
9193
9194             if (len < 36) {
9195               GST_DEBUG_OBJECT (qtdemux,
9196                   "discarding alac atom with unexpected len %d", len);
9197             } else {
9198               /* codec-data contains alac atom size and prefix,
9199                * ffmpeg likes it that way, not quite gst-ish though ...*/
9200               buf = gst_buffer_new_and_alloc (len);
9201               gst_buffer_fill (buf, 0, alac->data, len);
9202               gst_caps_set_simple (stream->caps,
9203                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
9204               gst_buffer_unref (buf);
9205
9206               stream->bytes_per_frame = QT_UINT32 (alac_data + 12);
9207               stream->n_channels = QT_UINT8 (alac_data + 21);
9208               stream->rate = QT_UINT32 (alac_data + 32);
9209             }
9210           }
9211           gst_caps_set_simple (stream->caps,
9212               "samplesize", G_TYPE_INT, samplesize, NULL);
9213           break;
9214         }
9215         case FOURCC_sawb:
9216           /* Fallthrough! */
9217           amrwb = TRUE;
9218         case FOURCC_samr:
9219         {
9220           gint len = QT_UINT32 (stsd_data);
9221
9222           if (len > 0x34) {
9223             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x34);
9224             guint bitrate;
9225
9226             gst_buffer_fill (buf, 0, stsd_data + 0x34, len - 0x34);
9227
9228             /* If we have enough data, let's try to get the 'damr' atom. See
9229              * the 3GPP container spec (26.244) for more details. */
9230             if ((len - 0x34) > 8 &&
9231                 (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
9232               gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9233                   GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
9234             }
9235
9236             gst_caps_set_simple (stream->caps,
9237                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
9238             gst_buffer_unref (buf);
9239           }
9240           break;
9241         }
9242         case FOURCC_mp4a:
9243         {
9244           /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
9245           gint len = QT_UINT32 (stsd_data);
9246
9247           if (len >= 50) {
9248             guint16 sound_version = QT_UINT16 (stsd_data + 32);
9249
9250             if (sound_version == 1) {
9251               guint16 channels = QT_UINT16 (stsd_data + 40);
9252               guint32 time_scale = QT_UINT32 (stsd_data + 46);
9253               guint8 codec_data[2];
9254               GstBuffer *buf;
9255               gint profile = 2; /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
9256
9257               gint sample_rate_index =
9258                   gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
9259
9260               /* build AAC codec data */
9261               codec_data[0] = profile << 3;
9262               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
9263               codec_data[1] = (sample_rate_index & 0x01) << 7;
9264               codec_data[1] |= (channels & 0xF) << 3;
9265
9266               buf = gst_buffer_new_and_alloc (2);
9267               gst_buffer_fill (buf, 0, codec_data, 2);
9268               gst_caps_set_simple (stream->caps,
9269                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
9270               gst_buffer_unref (buf);
9271             }
9272           }
9273           break;
9274         }
9275         default:
9276           GST_INFO_OBJECT (qtdemux,
9277               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
9278           break;
9279       }
9280     }
9281     GST_INFO_OBJECT (qtdemux,
9282         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
9283         GST_FOURCC_ARGS (fourcc), stream->caps);
9284
9285   } else if (stream->subtype == FOURCC_strm) {
9286     if (fourcc == FOURCC_rtsp) {
9287       stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
9288     } else {
9289       GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
9290           GST_FOURCC_ARGS (fourcc));
9291       goto unknown_stream;
9292     }
9293     stream->sampled = TRUE;
9294   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
9295       || stream->subtype == FOURCC_sbtl) {
9296
9297     stream->sampled = TRUE;
9298     stream->sparse = TRUE;
9299
9300     stream->caps =
9301         qtdemux_sub_caps (qtdemux, stream, fourcc, stsd_data, &codec);
9302     if (codec) {
9303       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9304           GST_TAG_SUBTITLE_CODEC, codec, NULL);
9305       g_free (codec);
9306       codec = NULL;
9307     }
9308
9309     /* hunt for sort-of codec data */
9310     switch (fourcc) {
9311       case FOURCC_mp4s:
9312       {
9313         GNode *mp4s = NULL;
9314         GNode *esds = NULL;
9315
9316         /* look for palette in a stsd->mp4s->esds sub-atom */
9317         mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
9318         if (mp4s)
9319           esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
9320         if (esds == NULL) {
9321           /* Invalid STSD */
9322           GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
9323           break;
9324         }
9325
9326         gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
9327         break;
9328       }
9329       default:
9330         GST_INFO_OBJECT (qtdemux,
9331             "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
9332         break;
9333     }
9334     GST_INFO_OBJECT (qtdemux,
9335         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
9336         GST_FOURCC_ARGS (fourcc), stream->caps);
9337   } else {
9338     /* everything in 1 sample */
9339     stream->sampled = TRUE;
9340
9341     stream->caps =
9342         qtdemux_generic_caps (qtdemux, stream, fourcc, stsd_data, &codec);
9343
9344     if (stream->caps == NULL)
9345       goto unknown_stream;
9346
9347     if (codec) {
9348       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9349           GST_TAG_SUBTITLE_CODEC, codec, NULL);
9350       g_free (codec);
9351       codec = NULL;
9352     }
9353   }
9354
9355   /* promote to sampled format */
9356   if (stream->fourcc == FOURCC_samr) {
9357     /* force mono 8000 Hz for AMR */
9358     stream->sampled = TRUE;
9359     stream->n_channels = 1;
9360     stream->rate = 8000;
9361   } else if (stream->fourcc == FOURCC_sawb) {
9362     /* force mono 16000 Hz for AMR-WB */
9363     stream->sampled = TRUE;
9364     stream->n_channels = 1;
9365     stream->rate = 16000;
9366   } else if (stream->fourcc == FOURCC_mp4a) {
9367     stream->sampled = TRUE;
9368   }
9369
9370   /* collect sample information */
9371   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
9372     goto samples_failed;
9373
9374   if (qtdemux->fragmented) {
9375     guint32 dummy;
9376     guint64 offset;
9377
9378     /* need all moov samples as basis; probably not many if any at all */
9379     /* prevent moof parsing taking of at this time */
9380     offset = qtdemux->moof_offset;
9381     qtdemux->moof_offset = 0;
9382     if (stream->n_samples &&
9383         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
9384       qtdemux->moof_offset = offset;
9385       goto samples_failed;
9386     }
9387     qtdemux->moof_offset = 0;
9388     /* movie duration more reliable in this case (e.g. mehd) */
9389     if (qtdemux->segment.duration &&
9390         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
9391       stream->duration =
9392           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
9393     /* need defaults for fragments */
9394     qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
9395   }
9396
9397   /* configure segments */
9398   if (!qtdemux_parse_segments (qtdemux, stream, trak))
9399     goto segments_failed;
9400
9401   /* add some language tag, if useful */
9402   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
9403       strcmp (stream->lang_id, "und")) {
9404     const gchar *lang_code;
9405
9406     /* convert ISO 639-2 code to ISO 639-1 */
9407     lang_code = gst_tag_get_language_code (stream->lang_id);
9408     gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9409         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
9410   }
9411
9412   /* Check for UDTA tags */
9413   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
9414     qtdemux_parse_udta (qtdemux, stream->pending_tags, udta);
9415   }
9416
9417   /* now we are ready to add the stream */
9418   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
9419     goto too_many_streams;
9420
9421   if (!qtdemux->got_moov) {
9422     qtdemux->streams[qtdemux->n_streams] = stream;
9423     qtdemux->n_streams++;
9424     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
9425   }
9426
9427   return TRUE;
9428
9429 /* ERRORS */
9430 skip_track:
9431   {
9432     GST_INFO_OBJECT (qtdemux, "skip disabled track");
9433     if (new_stream)
9434       gst_qtdemux_stream_free (qtdemux, stream);
9435     return TRUE;
9436   }
9437 corrupt_file:
9438   {
9439     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9440         (_("This file is corrupt and cannot be played.")), (NULL));
9441     if (new_stream)
9442       gst_qtdemux_stream_free (qtdemux, stream);
9443     return FALSE;
9444   }
9445 error_encrypted:
9446   {
9447     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
9448     if (new_stream)
9449       gst_qtdemux_stream_free (qtdemux, stream);
9450     return FALSE;
9451   }
9452 samples_failed:
9453 segments_failed:
9454   {
9455     /* we posted an error already */
9456     /* free stbl sub-atoms */
9457     gst_qtdemux_stbl_free (stream);
9458     if (new_stream)
9459       gst_qtdemux_stream_free (qtdemux, stream);
9460     return FALSE;
9461   }
9462 existing_stream:
9463   {
9464     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
9465         track_id);
9466     if (new_stream)
9467       gst_qtdemux_stream_free (qtdemux, stream);
9468     return TRUE;
9469   }
9470 unknown_stream:
9471   {
9472     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
9473         GST_FOURCC_ARGS (stream->subtype));
9474     if (new_stream)
9475       gst_qtdemux_stream_free (qtdemux, stream);
9476     return TRUE;
9477   }
9478 too_many_streams:
9479   {
9480     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
9481         (_("This file contains too many streams. Only playing first %d"),
9482             GST_QTDEMUX_MAX_STREAMS), (NULL));
9483     return TRUE;
9484   }
9485 }
9486
9487 /* If we can estimate the overall bitrate, and don't have information about the
9488  * stream bitrate for exactly one stream, this guesses the stream bitrate as
9489  * the overall bitrate minus the sum of the bitrates of all other streams. This
9490  * should be useful for the common case where we have one audio and one video
9491  * stream and can estimate the bitrate of one, but not the other. */
9492 static void
9493 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
9494 {
9495   QtDemuxStream *stream = NULL;
9496   gint64 size, sys_bitrate, sum_bitrate = 0;
9497   GstClockTime duration;
9498   gint i;
9499   guint bitrate;
9500
9501   if (qtdemux->fragmented)
9502     return;
9503
9504   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
9505
9506   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
9507       || size <= 0) {
9508     GST_DEBUG_OBJECT (qtdemux,
9509         "Size in bytes of the stream not known - bailing");
9510     return;
9511   }
9512
9513   /* Subtract the header size */
9514   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
9515       size, qtdemux->header_size);
9516
9517   if (size < qtdemux->header_size)
9518     return;
9519
9520   size = size - qtdemux->header_size;
9521
9522   if (!gst_qtdemux_get_duration (qtdemux, &duration) ||
9523       duration == GST_CLOCK_TIME_NONE) {
9524     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
9525     return;
9526   }
9527
9528   for (i = 0; i < qtdemux->n_streams; i++) {
9529     switch (qtdemux->streams[i]->subtype) {
9530       case FOURCC_soun:
9531       case FOURCC_vide:
9532         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
9533             qtdemux->streams[i]->caps);
9534         /* retrieve bitrate, prefer avg then max */
9535         bitrate = 0;
9536         if (qtdemux->streams[i]->pending_tags) {
9537           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
9538               GST_TAG_MAXIMUM_BITRATE, &bitrate);
9539           GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
9540           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
9541               GST_TAG_NOMINAL_BITRATE, &bitrate);
9542           GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
9543           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
9544               GST_TAG_BITRATE, &bitrate);
9545           GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
9546         }
9547         if (bitrate)
9548           sum_bitrate += bitrate;
9549         else {
9550           if (stream) {
9551             GST_DEBUG_OBJECT (qtdemux,
9552                 ">1 stream with unknown bitrate - bailing");
9553             return;
9554           } else
9555             stream = qtdemux->streams[i];
9556         }
9557
9558       default:
9559         /* For other subtypes, we assume no significant impact on bitrate */
9560         break;
9561     }
9562   }
9563
9564   if (!stream) {
9565     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
9566     return;
9567   }
9568
9569   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
9570
9571   if (sys_bitrate < sum_bitrate) {
9572     /* This can happen, since sum_bitrate might be derived from maximum
9573      * bitrates and not average bitrates */
9574     GST_DEBUG_OBJECT (qtdemux,
9575         "System bitrate less than sum bitrate - bailing");
9576     return;
9577   }
9578
9579   bitrate = sys_bitrate - sum_bitrate;
9580   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
9581       ", Stream bitrate = %u", sys_bitrate, bitrate);
9582
9583   if (!stream->pending_tags)
9584     stream->pending_tags = gst_tag_list_new_empty ();
9585
9586   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9587       GST_TAG_BITRATE, bitrate, NULL);
9588 }
9589
9590 static GstFlowReturn
9591 qtdemux_prepare_streams (GstQTDemux * qtdemux)
9592 {
9593   gint i;
9594   GstFlowReturn ret = GST_FLOW_OK;
9595
9596   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
9597
9598   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
9599     QtDemuxStream *stream = qtdemux->streams[i];
9600     guint32 sample_num = 0;
9601
9602     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
9603         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
9604
9605     if (qtdemux->fragmented) {
9606       /* need all moov samples first */
9607       GST_OBJECT_LOCK (qtdemux);
9608       while (stream->n_samples == 0)
9609         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
9610           break;
9611       GST_OBJECT_UNLOCK (qtdemux);
9612     } else {
9613       /* discard any stray moof */
9614       qtdemux->moof_offset = 0;
9615     }
9616
9617     /* prepare braking */
9618     if (ret != GST_FLOW_ERROR)
9619       ret = GST_FLOW_OK;
9620
9621     /* in pull mode, we should have parsed some sample info by now;
9622      * and quite some code will not handle no samples.
9623      * in push mode, we'll just have to deal with it */
9624     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
9625       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
9626       gst_qtdemux_remove_stream (qtdemux, i);
9627       i--;
9628       continue;
9629     }
9630
9631     /* parse the initial sample for use in setting the frame rate cap */
9632     while (sample_num == 0 && sample_num < stream->n_samples) {
9633       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
9634         break;
9635       ++sample_num;
9636     }
9637     if (stream->n_samples > 0 && stream->stbl_index >= 0) {
9638       stream->first_duration = stream->samples[0].duration;
9639       GST_LOG_OBJECT (qtdemux, "stream %d first duration %u",
9640           stream->track_id, stream->first_duration);
9641     }
9642   }
9643
9644   return ret;
9645 }
9646
9647 static GstFlowReturn
9648 qtdemux_expose_streams (GstQTDemux * qtdemux)
9649 {
9650   gint i;
9651   GstFlowReturn ret = GST_FLOW_OK;
9652   GSList *oldpads = NULL;
9653   GSList *iter;
9654
9655   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
9656
9657   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
9658     QtDemuxStream *stream = qtdemux->streams[i];
9659     GstPad *oldpad = stream->pad;
9660     GstTagList *list;
9661
9662     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
9663         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
9664
9665     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
9666         stream->track_id == qtdemux->chapters_track_id) {
9667       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
9668          so that it doesn't look like a subtitle track */
9669       gst_qtdemux_remove_stream (qtdemux, i);
9670       i--;
9671       continue;
9672     }
9673
9674     /* now we have all info and can expose */
9675     list = stream->pending_tags;
9676     stream->pending_tags = NULL;
9677     if (oldpad)
9678       oldpads = g_slist_prepend (oldpads, oldpad);
9679     gst_qtdemux_add_stream (qtdemux, stream, list);
9680   }
9681
9682   gst_qtdemux_guess_bitrate (qtdemux);
9683
9684   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
9685
9686   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
9687     GstPad *oldpad = iter->data;
9688
9689     gst_pad_push_event (oldpad, gst_event_new_eos ());
9690     gst_pad_set_active (oldpad, FALSE);
9691     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
9692     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, oldpad);
9693     gst_object_unref (oldpad);
9694   }
9695
9696   /* check if we should post a redirect in case there is a single trak
9697    * and it is a redirecting trak */
9698   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
9699     GstMessage *m;
9700
9701     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
9702         "an external content");
9703     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
9704         gst_structure_new ("redirect",
9705             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
9706             NULL));
9707     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
9708     qtdemux->posted_redirect = TRUE;
9709   }
9710
9711   for (i = 0; i < qtdemux->n_streams; i++) {
9712     QtDemuxStream *stream = qtdemux->streams[i];
9713
9714     qtdemux_do_allocation (qtdemux, stream);
9715   }
9716
9717   qtdemux->exposed = TRUE;
9718   return ret;
9719 }
9720
9721 /* check if major or compatible brand is 3GP */
9722 static inline gboolean
9723 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
9724 {
9725   if (major) {
9726     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
9727         GST_MAKE_FOURCC ('3', 'g', 0, 0));
9728   } else if (qtdemux->comp_brands != NULL) {
9729     GstMapInfo map;
9730     guint8 *data;
9731     gsize size;
9732     gboolean res = FALSE;
9733
9734     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
9735     data = map.data;
9736     size = map.size;
9737     while (size >= 4) {
9738       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
9739           GST_MAKE_FOURCC ('3', 'g', 0, 0));
9740       data += 4;
9741       size -= 4;
9742     }
9743     gst_buffer_unmap (qtdemux->comp_brands, &map);
9744     return res;
9745   } else {
9746     return FALSE;
9747   }
9748 }
9749
9750 /* check if tag is a spec'ed 3GP tag keyword storing a string */
9751 static inline gboolean
9752 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
9753 {
9754   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
9755       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
9756       || fourcc == FOURCC_albm;
9757 }
9758
9759 static void
9760 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
9761     const char *tag, const char *dummy, GNode * node)
9762 {
9763   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
9764   int offset;
9765   char *name;
9766   gchar *data;
9767   gdouble longitude, latitude, altitude;
9768   gint len;
9769
9770   len = QT_UINT32 (node->data);
9771   if (len <= 14)
9772     goto short_read;
9773
9774   data = node->data;
9775   offset = 14;
9776
9777   /* TODO: language code skipped */
9778
9779   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
9780
9781   if (!name) {
9782     /* do not alarm in trivial case, but bail out otherwise */
9783     if (*(data + offset) != 0) {
9784       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
9785           "giving up", tag);
9786     }
9787   } else {
9788     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
9789         GST_TAG_GEO_LOCATION_NAME, name, NULL);
9790     offset += strlen (name);
9791     g_free (name);
9792   }
9793
9794   if (len < offset + 2 + 4 + 4 + 4)
9795     goto short_read;
9796
9797   /* +1 +1 = skip null-terminator and location role byte */
9798   offset += 1 + 1;
9799   /* table in spec says unsigned, semantics say negative has meaning ... */
9800   longitude = QT_SFP32 (data + offset);
9801
9802   offset += 4;
9803   latitude = QT_SFP32 (data + offset);
9804
9805   offset += 4;
9806   altitude = QT_SFP32 (data + offset);
9807
9808   /* one invalid means all are invalid */
9809   if (longitude >= -180.0 && longitude <= 180.0 &&
9810       latitude >= -90.0 && latitude <= 90.0) {
9811     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
9812         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
9813         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
9814         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
9815   }
9816
9817   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
9818
9819   return;
9820
9821   /* ERRORS */
9822 short_read:
9823   {
9824     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
9825     return;
9826   }
9827 }
9828
9829
9830 static void
9831 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
9832     const char *tag, const char *dummy, GNode * node)
9833 {
9834   guint16 y;
9835   GDate *date;
9836   gint len;
9837
9838   len = QT_UINT32 (node->data);
9839   if (len < 14)
9840     return;
9841
9842   y = QT_UINT16 ((guint8 *) node->data + 12);
9843   if (y == 0) {
9844     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
9845     return;
9846   }
9847   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
9848
9849   date = g_date_new_dmy (1, 1, y);
9850   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
9851   g_date_free (date);
9852 }
9853
9854 static void
9855 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
9856     const char *tag, const char *dummy, GNode * node)
9857 {
9858   int offset;
9859   char *tag_str = NULL;
9860   guint8 *entity;
9861   guint16 table;
9862   gint len;
9863
9864   len = QT_UINT32 (node->data);
9865   if (len <= 20)
9866     goto short_read;
9867
9868   offset = 12;
9869   entity = (guint8 *) node->data + offset;
9870   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
9871     GST_DEBUG_OBJECT (qtdemux,
9872         "classification info: %c%c%c%c invalid classification entity",
9873         entity[0], entity[1], entity[2], entity[3]);
9874     return;
9875   }
9876
9877   offset += 4;
9878   table = QT_UINT16 ((guint8 *) node->data + offset);
9879
9880   /* Language code skipped */
9881
9882   offset += 4;
9883
9884   /* Tag format: "XXXX://Y[YYYY]/classification info string"
9885    * XXXX: classification entity, fixed length 4 chars.
9886    * Y[YYYY]: classification table, max 5 chars.
9887    */
9888   tag_str = g_strdup_printf ("----://%u/%s",
9889       table, (char *) node->data + offset);
9890
9891   /* memcpy To be sure we're preserving byte order */
9892   memcpy (tag_str, entity, 4);
9893   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
9894
9895   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
9896
9897   g_free (tag_str);
9898
9899   return;
9900
9901   /* ERRORS */
9902 short_read:
9903   {
9904     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
9905     return;
9906   }
9907 }
9908
9909 static gboolean
9910 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
9911     const char *tag, const char *dummy, GNode * node)
9912 {
9913   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
9914   GNode *data;
9915   char *s;
9916   int len;
9917   guint32 type;
9918   int offset;
9919   gboolean ret = TRUE;
9920   const gchar *charset = NULL;
9921
9922   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
9923   if (data) {
9924     len = QT_UINT32 (data->data);
9925     type = QT_UINT32 ((guint8 *) data->data + 8);
9926     if (type == 0x00000001 && len > 16) {
9927       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
9928           env_vars);
9929       if (s) {
9930         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
9931         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
9932         g_free (s);
9933       } else {
9934         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
9935       }
9936     }
9937   } else {
9938     len = QT_UINT32 (node->data);
9939     type = QT_UINT32 ((guint8 *) node->data + 4);
9940     if ((type >> 24) == 0xa9) {
9941       gint str_len;
9942       gint lang_code;
9943
9944       /* Type starts with the (C) symbol, so the next data is a list
9945        * of (string size(16), language code(16), string) */
9946
9947       str_len = QT_UINT16 ((guint8 *) node->data + 8);
9948       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
9949
9950       /* the string + fourcc + size + 2 16bit fields,
9951        * means that there are more tags in this atom */
9952       if (len > str_len + 8 + 4) {
9953         /* TODO how to represent the same tag in different languages? */
9954         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
9955             "text alternatives, reading only first one");
9956       }
9957
9958       offset = 12;
9959       len = str_len + 8 + 4;    /* remove trailing strings that we don't use */
9960       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
9961
9962       if (lang_code < 0x800) {  /* MAC encoded string */
9963         charset = "mac";
9964       }
9965     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
9966             QT_FOURCC ((guint8 *) node->data + 4))) {
9967       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
9968
9969       /* we go for 3GP style encoding if major brands claims so,
9970        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
9971       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
9972           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
9973               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
9974         offset = 14;
9975         /* 16-bit Language code is ignored here as well */
9976         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
9977       } else {
9978         goto normal;
9979       }
9980     } else {
9981     normal:
9982       offset = 8;
9983       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
9984       ret = FALSE;              /* may have to fallback */
9985     }
9986     if (charset) {
9987       GError *err = NULL;
9988
9989       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
9990           charset, NULL, NULL, &err);
9991       if (err) {
9992         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
9993             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
9994             err->message);
9995         g_error_free (err);
9996       }
9997     } else {
9998       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
9999           len - offset, env_vars);
10000     }
10001     if (s) {
10002       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
10003       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
10004       g_free (s);
10005       ret = TRUE;
10006     } else {
10007       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
10008     }
10009   }
10010   return ret;
10011 }
10012
10013 static void
10014 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
10015     const char *tag, const char *dummy, GNode * node)
10016 {
10017   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
10018 }
10019
10020 static void
10021 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
10022     const char *tag, const char *dummy, GNode * node)
10023 {
10024   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
10025   guint8 *data;
10026   char *s, *t, *k = NULL;
10027   int len;
10028   int offset;
10029   int count;
10030
10031   /* first try normal string tag if major brand not 3GP */
10032   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
10033     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
10034       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
10035        * let's try it 3gpp way after minor safety check */
10036       data = node->data;
10037       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
10038         return;
10039     } else
10040       return;
10041   }
10042
10043   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
10044
10045   data = node->data;
10046
10047   len = QT_UINT32 (data);
10048   if (len < 15)
10049     goto short_read;
10050
10051   count = QT_UINT8 (data + 14);
10052   offset = 15;
10053   for (; count; count--) {
10054     gint slen;
10055
10056     if (offset + 1 > len)
10057       goto short_read;
10058     slen = QT_UINT8 (data + offset);
10059     offset += 1;
10060     if (offset + slen > len)
10061       goto short_read;
10062     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
10063         slen, env_vars);
10064     if (s) {
10065       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
10066       if (k) {
10067         t = g_strjoin (",", k, s, NULL);
10068         g_free (s);
10069         g_free (k);
10070         k = t;
10071       } else {
10072         k = s;
10073       }
10074     } else {
10075       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
10076     }
10077     offset += slen;
10078   }
10079
10080 done:
10081   if (k) {
10082     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
10083     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
10084   }
10085   g_free (k);
10086
10087   return;
10088
10089   /* ERRORS */
10090 short_read:
10091   {
10092     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
10093     goto done;
10094   }
10095 }
10096
10097 static void
10098 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
10099     const char *tag1, const char *tag2, GNode * node)
10100 {
10101   GNode *data;
10102   int len;
10103   int type;
10104   int n1, n2;
10105
10106   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
10107   if (data) {
10108     len = QT_UINT32 (data->data);
10109     type = QT_UINT32 ((guint8 *) data->data + 8);
10110     if (type == 0x00000000 && len >= 22) {
10111       n1 = QT_UINT16 ((guint8 *) data->data + 18);
10112       n2 = QT_UINT16 ((guint8 *) data->data + 20);
10113       if (n1 > 0) {
10114         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
10115         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
10116       }
10117       if (n2 > 0) {
10118         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
10119         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
10120       }
10121     }
10122   }
10123 }
10124
10125 static void
10126 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
10127     const char *tag1, const char *dummy, GNode * node)
10128 {
10129   GNode *data;
10130   int len;
10131   int type;
10132   int n1;
10133
10134   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
10135   if (data) {
10136     len = QT_UINT32 (data->data);
10137     type = QT_UINT32 ((guint8 *) data->data + 8);
10138     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
10139     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
10140     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
10141       n1 = QT_UINT16 ((guint8 *) data->data + 16);
10142       if (n1) {
10143         /* do not add bpm=0 */
10144         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
10145         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
10146             NULL);
10147       }
10148     }
10149   }
10150 }
10151
10152 static void
10153 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
10154     const char *tag1, const char *dummy, GNode * node)
10155 {
10156   GNode *data;
10157   int len;
10158   int type;
10159   guint32 num;
10160
10161   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
10162   if (data) {
10163     len = QT_UINT32 (data->data);
10164     type = QT_UINT32 ((guint8 *) data->data + 8);
10165     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
10166     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
10167     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
10168       num = QT_UINT32 ((guint8 *) data->data + 16);
10169       if (num) {
10170         /* do not add num=0 */
10171         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
10172         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
10173       }
10174     }
10175   }
10176 }
10177
10178 static void
10179 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
10180     const char *tag1, const char *dummy, GNode * node)
10181 {
10182   GNode *data;
10183   int len;
10184   int type;
10185   GstSample *sample;
10186
10187   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
10188   if (data) {
10189     len = QT_UINT32 (data->data);
10190     type = QT_UINT32 ((guint8 *) data->data + 8);
10191     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
10192     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
10193       if ((sample =
10194               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
10195                   len - 16, GST_TAG_IMAGE_TYPE_NONE))) {
10196         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
10197         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
10198         gst_sample_unref (sample);
10199       }
10200     }
10201   }
10202 }
10203
10204 static void
10205 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
10206     const char *tag, const char *dummy, GNode * node)
10207 {
10208   GNode *data;
10209   char *s;
10210   int len;
10211   int type;
10212
10213   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
10214   if (data) {
10215     len = QT_UINT32 (data->data);
10216     type = QT_UINT32 ((guint8 *) data->data + 8);
10217     if (type == 0x00000001 && len > 16) {
10218       guint y, m = 1, d = 1;
10219       gint ret;
10220
10221       s = g_strndup ((char *) data->data + 16, len - 16);
10222       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
10223       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
10224       if (ret >= 1 && y > 1500 && y < 3000) {
10225         GDate *date;
10226
10227         date = g_date_new_dmy (d, m, y);
10228         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
10229         g_date_free (date);
10230       } else {
10231         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
10232       }
10233       g_free (s);
10234     }
10235   }
10236 }
10237
10238 static void
10239 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
10240     const char *tag, const char *dummy, GNode * node)
10241 {
10242   GNode *data;
10243
10244   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
10245
10246   /* re-route to normal string tag if major brand says so
10247    * or no data atom and compatible brand suggests so */
10248   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
10249       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
10250     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
10251     return;
10252   }
10253
10254   if (data) {
10255     guint len, type, n;
10256
10257     len = QT_UINT32 (data->data);
10258     type = QT_UINT32 ((guint8 *) data->data + 8);
10259     if (type == 0x00000000 && len >= 18) {
10260       n = QT_UINT16 ((guint8 *) data->data + 16);
10261       if (n > 0) {
10262         const gchar *genre;
10263
10264         genre = gst_tag_id3_genre_get (n - 1);
10265         if (genre != NULL) {
10266           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
10267           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
10268         }
10269       }
10270     }
10271   }
10272 }
10273
10274 static void
10275 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
10276     const gchar * tag, guint8 * data, guint32 datasize)
10277 {
10278   gdouble value;
10279   gchar *datacopy;
10280
10281   /* make a copy to have \0 at the end */
10282   datacopy = g_strndup ((gchar *) data, datasize);
10283
10284   /* convert the str to double */
10285   if (sscanf (datacopy, "%lf", &value) == 1) {
10286     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
10287     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
10288   } else {
10289     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
10290         datacopy);
10291   }
10292   g_free (datacopy);
10293 }
10294
10295
10296 static void
10297 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
10298     const char *tag, const char *tag_bis, GNode * node)
10299 {
10300   GNode *mean;
10301   GNode *name;
10302   GNode *data;
10303   guint32 meansize;
10304   guint32 namesize;
10305   guint32 datatype;
10306   guint32 datasize;
10307   const gchar *meanstr;
10308   const gchar *namestr;
10309
10310   /* checking the whole ---- atom size for consistency */
10311   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
10312     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
10313     return;
10314   }
10315
10316   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
10317   if (!mean) {
10318     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
10319     return;
10320   }
10321
10322   meansize = QT_UINT32 (mean->data);
10323   if (meansize <= 12) {
10324     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
10325     return;
10326   }
10327   meanstr = ((gchar *) mean->data) + 12;
10328   meansize -= 12;
10329
10330   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
10331   if (!name) {
10332     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
10333     return;
10334   }
10335
10336   namesize = QT_UINT32 (name->data);
10337   if (namesize <= 12) {
10338     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
10339     return;
10340   }
10341   namestr = ((gchar *) name->data) + 12;
10342   namesize -= 12;
10343
10344   /*
10345    * Data atom is:
10346    * uint32 - size
10347    * uint32 - name
10348    * uint8  - version
10349    * uint24 - data type
10350    * uint32 - all 0
10351    * rest   - the data
10352    */
10353   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
10354   if (!data) {
10355     GST_WARNING_OBJECT (demux, "No data atom in this tag");
10356     return;
10357   }
10358   datasize = QT_UINT32 (data->data);
10359   if (datasize <= 16) {
10360     GST_WARNING_OBJECT (demux, "Data atom too small");
10361     return;
10362   }
10363   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
10364
10365   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
10366       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
10367     static const struct
10368     {
10369       const gchar name[28];
10370       const gchar tag[28];
10371     } tags[] = {
10372       {
10373       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
10374       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
10375       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
10376       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
10377       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
10378       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
10379       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
10380       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
10381     };
10382     int i;
10383
10384     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
10385       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
10386         switch (gst_tag_get_type (tags[i].tag)) {
10387           case G_TYPE_DOUBLE:
10388             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
10389                 ((guint8 *) data->data) + 16, datasize - 16);
10390             break;
10391           case G_TYPE_STRING:
10392             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
10393             break;
10394           default:
10395             /* not reached */
10396             break;
10397         }
10398         break;
10399       }
10400     }
10401     if (i == G_N_ELEMENTS (tags))
10402       goto unknown_tag;
10403   } else {
10404     goto unknown_tag;
10405   }
10406
10407   return;
10408
10409 /* errors */
10410 unknown_tag:
10411 #ifndef GST_DISABLE_GST_DEBUG
10412   {
10413     gchar *namestr_dbg;
10414     gchar *meanstr_dbg;
10415
10416     meanstr_dbg = g_strndup (meanstr, meansize);
10417     namestr_dbg = g_strndup (namestr, namesize);
10418
10419     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
10420         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
10421
10422     g_free (namestr_dbg);
10423     g_free (meanstr_dbg);
10424   }
10425 #endif
10426   return;
10427 }
10428
10429 static void
10430 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
10431     const char *tag_bis, GNode * node)
10432 {
10433   guint8 *data;
10434   GstBuffer *buf;
10435   guint len;
10436   GstTagList *id32_taglist = NULL;
10437
10438   GST_LOG_OBJECT (demux, "parsing ID32");
10439
10440   data = node->data;
10441   len = GST_READ_UINT32_BE (data);
10442
10443   /* need at least full box and language tag */
10444   if (len < 12 + 2)
10445     return;
10446
10447   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
10448   gst_buffer_fill (buf, 0, data + 14, len - 14);
10449
10450   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
10451   if (id32_taglist) {
10452     GST_LOG_OBJECT (demux, "parsing ok");
10453     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
10454     gst_tag_list_unref (id32_taglist);
10455   } else {
10456     GST_LOG_OBJECT (demux, "parsing failed");
10457   }
10458
10459   gst_buffer_unref (buf);
10460 }
10461
10462 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
10463     const char *tag, const char *tag_bis, GNode * node);
10464
10465 /* unmapped tags
10466 FOURCC_pcst -> if media is a podcast -> bool
10467 FOURCC_cpil -> if media is part of a compilation -> bool
10468 FOURCC_pgap -> if media is part of a gapless context -> bool
10469 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
10470 */
10471
10472 static const struct
10473 {
10474   guint32 fourcc;
10475   const gchar *gst_tag;
10476   const gchar *gst_tag_bis;
10477   const GstQTDemuxAddTagFunc func;
10478 } add_funcs[] = {
10479   {
10480   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
10481   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
10482   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
10483   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
10484   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
10485   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
10486   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
10487   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
10488   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
10489   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
10490   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
10491   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
10492   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
10493   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
10494   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
10495   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
10496   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
10497   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
10498   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
10499   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
10500   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
10501   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
10502   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
10503         qtdemux_tag_add_num}, {
10504   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
10505         qtdemux_tag_add_num}, {
10506   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
10507   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
10508   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
10509   FOURCC_covr, GST_TAG_PREVIEW_IMAGE, NULL, qtdemux_tag_add_covr}, {
10510   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
10511   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
10512   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
10513   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
10514   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
10515   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
10516   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
10517   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
10518   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
10519   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
10520   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
10521   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
10522   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
10523   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
10524         qtdemux_tag_add_classification}, {
10525   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
10526   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
10527   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
10528
10529     /* This is a special case, some tags are stored in this
10530      * 'reverse dns naming', according to:
10531      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
10532      * bug #614471
10533      */
10534   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
10535     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
10536   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
10537 };
10538
10539 struct _GstQtDemuxTagList
10540 {
10541   GstQTDemux *demux;
10542   GstTagList *taglist;
10543 };
10544 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
10545
10546 static void
10547 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
10548 {
10549   gint len;
10550   guint8 *data;
10551   GstBuffer *buf;
10552   gchar *media_type;
10553   const gchar *style;
10554   GstSample *sample;
10555   GstStructure *s;
10556   guint i;
10557   guint8 ndata[4];
10558   GstQTDemux *demux = qtdemuxtaglist->demux;
10559   GstTagList *taglist = qtdemuxtaglist->taglist;
10560
10561   data = node->data;
10562   len = QT_UINT32 (data);
10563   buf = gst_buffer_new_and_alloc (len);
10564   gst_buffer_fill (buf, 0, data, len);
10565
10566   /* heuristic to determine style of tag */
10567   if (QT_FOURCC (data + 4) == FOURCC_____ ||
10568       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
10569     style = "itunes";
10570   else if (demux->major_brand == FOURCC_qt__)
10571     style = "quicktime";
10572   /* fall back to assuming iso/3gp tag style */
10573   else
10574     style = "iso";
10575
10576   /* santize the name for the caps. */
10577   for (i = 0; i < 4; i++) {
10578     guint8 d = data[4 + i];
10579     if (g_ascii_isalnum (d))
10580       ndata[i] = g_ascii_tolower (d);
10581     else
10582       ndata[i] = '_';
10583   }
10584
10585   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
10586       ndata[0], ndata[1], ndata[2], ndata[3]);
10587   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
10588
10589   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
10590   sample = gst_sample_new (buf, NULL, NULL, s);
10591   gst_buffer_unref (buf);
10592   g_free (media_type);
10593
10594   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
10595       len, s);
10596
10597   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
10598       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
10599
10600   gst_sample_unref (sample);
10601 }
10602
10603 static void
10604 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
10605 {
10606   GNode *meta;
10607   GNode *ilst;
10608   GNode *xmp_;
10609   GNode *node;
10610   gint i;
10611   GstQtDemuxTagList demuxtaglist;
10612
10613   demuxtaglist.demux = qtdemux;
10614   demuxtaglist.taglist = taglist;
10615
10616   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
10617   if (meta != NULL) {
10618     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
10619     if (ilst == NULL) {
10620       GST_LOG_OBJECT (qtdemux, "no ilst");
10621       return;
10622     }
10623   } else {
10624     ilst = udta;
10625     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
10626   }
10627
10628   i = 0;
10629   while (i < G_N_ELEMENTS (add_funcs)) {
10630     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
10631     if (node) {
10632       gint len;
10633
10634       len = QT_UINT32 (node->data);
10635       if (len < 12) {
10636         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
10637             GST_FOURCC_ARGS (add_funcs[i].fourcc));
10638       } else {
10639         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
10640             add_funcs[i].gst_tag_bis, node);
10641       }
10642       g_node_destroy (node);
10643     } else {
10644       i++;
10645     }
10646   }
10647
10648   /* parsed nodes have been removed, pass along remainder as blob */
10649   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
10650       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
10651
10652   /* parse up XMP_ node if existing */
10653   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
10654   if (xmp_ != NULL) {
10655     GstBuffer *buf;
10656     GstTagList *xmptaglist;
10657
10658     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
10659         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
10660     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
10661     gst_buffer_unref (buf);
10662
10663     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
10664   } else {
10665     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
10666   }
10667 }
10668
10669 typedef struct
10670 {
10671   GstStructure *structure;      /* helper for sort function */
10672   gchar *location;
10673   guint min_req_bitrate;
10674   guint min_req_qt_version;
10675 } GstQtReference;
10676
10677 static gint
10678 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
10679 {
10680   GstQtReference *ref_a = (GstQtReference *) a;
10681   GstQtReference *ref_b = (GstQtReference *) b;
10682
10683   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
10684     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
10685
10686   /* known bitrates go before unknown; higher bitrates go first */
10687   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
10688 }
10689
10690 /* sort the redirects and post a message for the application.
10691  */
10692 static void
10693 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
10694 {
10695   GstQtReference *best;
10696   GstStructure *s;
10697   GstMessage *msg;
10698   GValue list_val = { 0, };
10699   GList *l;
10700
10701   g_assert (references != NULL);
10702
10703   references = g_list_sort (references, qtdemux_redirects_sort_func);
10704
10705   best = (GstQtReference *) references->data;
10706
10707   g_value_init (&list_val, GST_TYPE_LIST);
10708
10709   for (l = references; l != NULL; l = l->next) {
10710     GstQtReference *ref = (GstQtReference *) l->data;
10711     GValue struct_val = { 0, };
10712
10713     ref->structure = gst_structure_new ("redirect",
10714         "new-location", G_TYPE_STRING, ref->location, NULL);
10715
10716     if (ref->min_req_bitrate > 0) {
10717       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
10718           ref->min_req_bitrate, NULL);
10719     }
10720
10721     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
10722     g_value_set_boxed (&struct_val, ref->structure);
10723     gst_value_list_append_value (&list_val, &struct_val);
10724     g_value_unset (&struct_val);
10725     /* don't free anything here yet, since we need best->structure below */
10726   }
10727
10728   g_assert (best != NULL);
10729   s = gst_structure_copy (best->structure);
10730
10731   if (g_list_length (references) > 1) {
10732     gst_structure_set_value (s, "locations", &list_val);
10733   }
10734
10735   g_value_unset (&list_val);
10736
10737   for (l = references; l != NULL; l = l->next) {
10738     GstQtReference *ref = (GstQtReference *) l->data;
10739
10740     gst_structure_free (ref->structure);
10741     g_free (ref->location);
10742     g_free (ref);
10743   }
10744   g_list_free (references);
10745
10746   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
10747   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
10748   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
10749   qtdemux->posted_redirect = TRUE;
10750 }
10751
10752 /* look for redirect nodes, collect all redirect information and
10753  * process it.
10754  */
10755 static gboolean
10756 qtdemux_parse_redirects (GstQTDemux * qtdemux)
10757 {
10758   GNode *rmra, *rmda, *rdrf;
10759
10760   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
10761   if (rmra) {
10762     GList *redirects = NULL;
10763
10764     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
10765     while (rmda) {
10766       GstQtReference ref = { NULL, NULL, 0, 0 };
10767       GNode *rmdr, *rmvc;
10768
10769       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
10770         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
10771         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
10772             ref.min_req_bitrate);
10773       }
10774
10775       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
10776         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
10777         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
10778
10779 #ifndef GST_DISABLE_GST_DEBUG
10780         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
10781 #endif
10782         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
10783
10784         GST_LOG_OBJECT (qtdemux,
10785             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
10786             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
10787             bitmask, check_type);
10788         if (package == FOURCC_qtim && check_type == 0) {
10789           ref.min_req_qt_version = version;
10790         }
10791       }
10792
10793       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
10794       if (rdrf) {
10795         guint32 ref_type;
10796         guint8 *ref_data;
10797         guint ref_len;
10798
10799         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
10800         if (ref_len > 20) {
10801           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
10802           ref_data = (guint8 *) rdrf->data + 20;
10803           if (ref_type == FOURCC_alis) {
10804             guint record_len, record_version, fn_len;
10805
10806             if (ref_len > 70) {
10807               /* MacOSX alias record, google for alias-layout.txt */
10808               record_len = QT_UINT16 (ref_data + 4);
10809               record_version = QT_UINT16 (ref_data + 4 + 2);
10810               fn_len = QT_UINT8 (ref_data + 50);
10811               if (record_len > 50 && record_version == 2 && fn_len > 0) {
10812                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
10813               }
10814             } else {
10815               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
10816                   ref_len);
10817             }
10818           } else if (ref_type == FOURCC_url_) {
10819             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
10820           } else {
10821             GST_DEBUG_OBJECT (qtdemux,
10822                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
10823                 GST_FOURCC_ARGS (ref_type));
10824           }
10825           if (ref.location != NULL) {
10826             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
10827             redirects =
10828                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
10829           } else {
10830             GST_WARNING_OBJECT (qtdemux,
10831                 "Failed to extract redirect location from rdrf atom");
10832           }
10833         } else {
10834           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
10835         }
10836       }
10837
10838       /* look for others */
10839       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
10840     }
10841
10842     if (redirects != NULL) {
10843       qtdemux_process_redirects (qtdemux, redirects);
10844     }
10845   }
10846   return TRUE;
10847 }
10848
10849 static GstTagList *
10850 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
10851 {
10852   const gchar *fmt;
10853
10854   if (tags == NULL) {
10855     tags = gst_tag_list_new_empty ();
10856     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
10857   }
10858
10859   if (qtdemux->major_brand == FOURCC_mjp2)
10860     fmt = "Motion JPEG 2000";
10861   else if ((qtdemux->major_brand & 0xffff) == GST_MAKE_FOURCC ('3', 'g', 0, 0))
10862     fmt = "3GP";
10863   else if (qtdemux->major_brand == FOURCC_qt__)
10864     fmt = "Quicktime";
10865   else if (qtdemux->fragmented)
10866     fmt = "ISO fMP4";
10867   else
10868     fmt = "ISO MP4/M4A";
10869
10870   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
10871       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
10872
10873   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
10874       fmt, NULL);
10875
10876   return tags;
10877 }
10878
10879 /* we have read th complete moov node now.
10880  * This function parses all of the relevant info, creates the traks and
10881  * prepares all data structures for playback
10882  */
10883 static gboolean
10884 qtdemux_parse_tree (GstQTDemux * qtdemux)
10885 {
10886   GNode *mvhd;
10887   GNode *trak;
10888   GNode *udta;
10889   GNode *mvex;
10890   GstClockTime duration;
10891   guint64 creation_time;
10892   GstDateTime *datetime = NULL;
10893   gint version;
10894
10895   /* make sure we have a usable taglist */
10896   if (!qtdemux->tag_list) {
10897     qtdemux->tag_list = gst_tag_list_new_empty ();
10898     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
10899   } else {
10900     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
10901   }
10902
10903   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
10904   if (mvhd == NULL) {
10905     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
10906     return qtdemux_parse_redirects (qtdemux);
10907   }
10908
10909   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
10910   if (version == 1) {
10911     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
10912     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
10913     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
10914   } else if (version == 0) {
10915     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
10916     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
10917     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
10918   } else {
10919     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
10920     return FALSE;
10921   }
10922
10923   /* Moving qt creation time (secs since 1904) to unix time */
10924   if (creation_time != 0) {
10925     /* Try to use epoch first as it should be faster and more commonly found */
10926     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
10927       GTimeVal now;
10928
10929       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
10930       /* some data cleansing sanity */
10931       g_get_current_time (&now);
10932       if (now.tv_sec + 24 * 3600 < creation_time) {
10933         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
10934       } else {
10935         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
10936       }
10937     } else {
10938       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
10939       GDateTime *dt, *dt_local;
10940
10941       dt = g_date_time_add_seconds (base_dt, creation_time);
10942       dt_local = g_date_time_to_local (dt);
10943       datetime = gst_date_time_new_from_g_date_time (dt_local);
10944
10945       g_date_time_unref (base_dt);
10946       g_date_time_unref (dt);
10947     }
10948   }
10949   if (datetime) {
10950     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
10951     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
10952         datetime, NULL);
10953     gst_date_time_unref (datetime);
10954   }
10955
10956   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
10957   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
10958
10959   /* check for fragmented file and get some (default) data */
10960   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
10961   if (mvex) {
10962     GNode *mehd;
10963     GstByteReader mehd_data;
10964
10965     /* let track parsing or anyone know weird stuff might happen ... */
10966     qtdemux->fragmented = TRUE;
10967
10968     /* compensate for total duration */
10969     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
10970     if (mehd)
10971       qtdemux_parse_mehd (qtdemux, &mehd_data);
10972   }
10973
10974   /* set duration in the segment info */
10975   gst_qtdemux_get_duration (qtdemux, &duration);
10976   if (duration) {
10977     qtdemux->segment.duration = duration;
10978     /* also do not exceed duration; stop is set that way post seek anyway,
10979      * and segment activation falls back to duration,
10980      * whereas loop only checks stop, so let's align this here as well */
10981     qtdemux->segment.stop = duration;
10982   }
10983
10984   /* parse all traks */
10985   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
10986   while (trak) {
10987     qtdemux_parse_trak (qtdemux, trak);
10988     /* iterate all siblings */
10989     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
10990   }
10991
10992   if (!qtdemux->tag_list) {
10993     GST_DEBUG_OBJECT (qtdemux, "new tag list");
10994     qtdemux->tag_list = gst_tag_list_new_empty ();
10995     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
10996   } else {
10997     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
10998   }
10999
11000   /* find tags */
11001   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
11002   if (udta) {
11003     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
11004   } else {
11005     GST_LOG_OBJECT (qtdemux, "No udta node found.");
11006   }
11007
11008   /* maybe also some tags in meta box */
11009   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
11010   if (udta) {
11011     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
11012     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
11013   } else {
11014     GST_LOG_OBJECT (qtdemux, "No meta node found.");
11015   }
11016
11017   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
11018
11019   return TRUE;
11020 }
11021
11022 /* taken from ffmpeg */
11023 static int
11024 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
11025 {
11026   int count = 4;
11027   int len = 0;
11028
11029   while (count--) {
11030     int c;
11031
11032     if (ptr >= end)
11033       return -1;
11034
11035     c = *ptr++;
11036     len = (len << 7) | (c & 0x7f);
11037     if (!(c & 0x80))
11038       break;
11039   }
11040   *end_out = ptr;
11041   return len;
11042 }
11043
11044 /* this can change the codec originally present in @list */
11045 static void
11046 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
11047     GNode * esds, GstTagList * list)
11048 {
11049   int len = QT_UINT32 (esds->data);
11050   guint8 *ptr = esds->data;
11051   guint8 *end = ptr + len;
11052   int tag;
11053   guint8 *data_ptr = NULL;
11054   int data_len = 0;
11055   guint8 object_type_id = 0;
11056   const char *codec_name = NULL;
11057   GstCaps *caps = NULL;
11058
11059   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
11060   ptr += 8;
11061   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
11062   ptr += 4;
11063   while (ptr + 1 < end) {
11064     tag = QT_UINT8 (ptr);
11065     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
11066     ptr++;
11067     len = read_descr_size (ptr, end, &ptr);
11068     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
11069
11070     /* Check the stated amount of data is available for reading */
11071     if (len < 0 || ptr + len > end)
11072       break;
11073
11074     switch (tag) {
11075       case ES_DESCRIPTOR_TAG:
11076         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
11077         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
11078         ptr += 3;
11079         break;
11080       case DECODER_CONFIG_DESC_TAG:{
11081         guint max_bitrate, avg_bitrate;
11082
11083         object_type_id = QT_UINT8 (ptr);
11084         max_bitrate = QT_UINT32 (ptr + 5);
11085         avg_bitrate = QT_UINT32 (ptr + 9);
11086         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
11087         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
11088         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
11089         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
11090         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
11091         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
11092           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
11093               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
11094         }
11095         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
11096           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
11097               avg_bitrate, NULL);
11098         }
11099         ptr += 13;
11100         break;
11101       }
11102       case DECODER_SPECIFIC_INFO_TAG:
11103         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
11104         if (object_type_id == 0xe0 && len == 0x40) {
11105           guint8 *data;
11106           GstStructure *s;
11107           guint32 clut[16];
11108           gint i;
11109
11110           GST_DEBUG_OBJECT (qtdemux,
11111               "Have VOBSUB palette. Creating palette event");
11112           /* move to decConfigDescr data and read palette */
11113           data = ptr;
11114           for (i = 0; i < 16; i++) {
11115             clut[i] = QT_UINT32 (data);
11116             data += 4;
11117           }
11118
11119           s = gst_structure_new ("application/x-gst-dvd", "event",
11120               G_TYPE_STRING, "dvd-spu-clut-change",
11121               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
11122               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
11123               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
11124               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
11125               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
11126               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
11127               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
11128               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
11129               NULL);
11130
11131           /* store event and trigger custom processing */
11132           stream->pending_event =
11133               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
11134         } else {
11135           /* Generic codec_data handler puts it on the caps */
11136           data_ptr = ptr;
11137           data_len = len;
11138         }
11139
11140         ptr += len;
11141         break;
11142       case SL_CONFIG_DESC_TAG:
11143         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
11144         ptr += 1;
11145         break;
11146       default:
11147         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
11148             tag);
11149         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
11150         ptr += len;
11151         break;
11152     }
11153   }
11154
11155   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
11156    * in use, and should also be used to override some other parameters for some
11157    * codecs. */
11158   switch (object_type_id) {
11159     case 0x20:                 /* MPEG-4 */
11160       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
11161        * profile_and_level_indication */
11162       if (data_ptr != NULL && data_len >= 5 &&
11163           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
11164         gst_codec_utils_mpeg4video_caps_set_level_and_profile (stream->caps,
11165             data_ptr + 4, data_len - 4);
11166       }
11167       break;                    /* Nothing special needed here */
11168     case 0x21:                 /* H.264 */
11169       codec_name = "H.264 / AVC";
11170       caps = gst_caps_new_simple ("video/x-h264",
11171           "stream-format", G_TYPE_STRING, "avc",
11172           "alignment", G_TYPE_STRING, "au", NULL);
11173       break;
11174     case 0x40:                 /* AAC (any) */
11175     case 0x66:                 /* AAC Main */
11176     case 0x67:                 /* AAC LC */
11177     case 0x68:                 /* AAC SSR */
11178       /* Override channels and rate based on the codec_data, as it's often
11179        * wrong. */
11180       /* Only do so for basic setup without HE-AAC extension */
11181       if (data_ptr && data_len == 2) {
11182         guint channels, rateindex, rate;
11183
11184         /* FIXME: add gst_codec_utils_aac_get_{channels|sample_rate}()? */
11185         channels = (data_ptr[1] & 0x7f) >> 3;
11186         if (channels > 0 && channels < 7) {
11187           stream->n_channels = channels;
11188         } else if (channels == 7) {
11189           stream->n_channels = 8;
11190         }
11191
11192         rateindex = ((data_ptr[0] & 0x7) << 1) | ((data_ptr[1] & 0x80) >> 7);
11193         rate = gst_codec_utils_aac_get_sample_rate_from_index (rateindex);
11194         if (rate > 0)
11195           stream->rate = rate;
11196       }
11197
11198       /* Set level and profile if possible */
11199       if (data_ptr != NULL && data_len >= 2) {
11200         gst_codec_utils_aac_caps_set_level_and_profile (stream->caps,
11201             data_ptr, data_len);
11202       }
11203       break;
11204     case 0x60:                 /* MPEG-2, various profiles */
11205     case 0x61:
11206     case 0x62:
11207     case 0x63:
11208     case 0x64:
11209     case 0x65:
11210       codec_name = "MPEG-2 video";
11211       caps = gst_caps_new_simple ("video/mpeg",
11212           "mpegversion", G_TYPE_INT, 2,
11213           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
11214       break;
11215     case 0x69:                 /* MPEG-2 BC audio */
11216     case 0x6B:                 /* MPEG-1 audio */
11217       caps = gst_caps_new_simple ("audio/mpeg",
11218           "mpegversion", G_TYPE_INT, 1, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
11219       codec_name = "MPEG-1 audio";
11220       break;
11221     case 0x6A:                 /* MPEG-1 */
11222       codec_name = "MPEG-1 video";
11223       caps = gst_caps_new_simple ("video/mpeg",
11224           "mpegversion", G_TYPE_INT, 1,
11225           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
11226       break;
11227     case 0x6C:                 /* MJPEG */
11228       caps =
11229           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
11230           NULL);
11231       codec_name = "Motion-JPEG";
11232       break;
11233     case 0x6D:                 /* PNG */
11234       caps =
11235           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
11236           NULL);
11237       codec_name = "PNG still images";
11238       break;
11239     case 0x6E:                 /* JPEG2000 */
11240       codec_name = "JPEG-2000";
11241       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
11242       break;
11243     case 0xA4:                 /* Dirac */
11244       codec_name = "Dirac";
11245       caps = gst_caps_new_empty_simple ("video/x-dirac");
11246       break;
11247     case 0xA5:                 /* AC3 */
11248       codec_name = "AC-3 audio";
11249       caps = gst_caps_new_simple ("audio/x-ac3",
11250           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
11251       break;
11252     case 0xA9:                 /* AC3 */
11253       codec_name = "DTS audio";
11254       caps = gst_caps_new_simple ("audio/x-dts",
11255           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
11256       break;
11257     case 0xE1:                 /* QCELP */
11258       /* QCELP, the codec_data is a riff tag (little endian) with
11259        * 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). */
11260       caps = gst_caps_new_empty_simple ("audio/qcelp");
11261       codec_name = "QCELP";
11262       break;
11263     default:
11264       break;
11265   }
11266
11267   /* If we have a replacement caps, then change our caps for this stream */
11268   if (caps) {
11269     gst_caps_unref (stream->caps);
11270     stream->caps = caps;
11271   }
11272
11273   if (codec_name && list)
11274     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
11275         GST_TAG_AUDIO_CODEC, codec_name, NULL);
11276
11277   /* Add the codec_data attribute to caps, if we have it */
11278   if (data_ptr) {
11279     GstBuffer *buffer;
11280
11281     buffer = gst_buffer_new_and_alloc (data_len);
11282     gst_buffer_fill (buffer, 0, data_ptr, data_len);
11283
11284     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
11285     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
11286
11287     gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
11288         buffer, NULL);
11289     gst_buffer_unref (buffer);
11290   }
11291
11292 }
11293
11294 #define _codec(name) \
11295   do { \
11296     if (codec_name) { \
11297       *codec_name = g_strdup (name); \
11298     } \
11299   } while (0)
11300
11301 static GstCaps *
11302 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
11303     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
11304 {
11305   GstCaps *caps = NULL;
11306   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
11307
11308   switch (fourcc) {
11309     case GST_MAKE_FOURCC ('p', 'n', 'g', ' '):
11310       _codec ("PNG still images");
11311       caps = gst_caps_new_empty_simple ("image/png");
11312       break;
11313     case GST_MAKE_FOURCC ('j', 'p', 'e', 'g'):
11314       _codec ("JPEG still images");
11315       caps =
11316           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
11317           NULL);
11318       break;
11319     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
11320     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
11321     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
11322     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
11323       _codec ("Motion-JPEG");
11324       caps =
11325           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
11326           NULL);
11327       break;
11328     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
11329       _codec ("Motion-JPEG format B");
11330       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
11331       break;
11332     case GST_MAKE_FOURCC ('m', 'j', 'p', '2'):
11333       _codec ("JPEG-2000");
11334       /* override to what it should be according to spec, avoid palette_data */
11335       stream->bits_per_sample = 24;
11336       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
11337       break;
11338     case GST_MAKE_FOURCC ('S', 'V', 'Q', '3'):
11339       _codec ("Sorensen video v.3");
11340       caps = gst_caps_new_simple ("video/x-svq",
11341           "svqversion", G_TYPE_INT, 3, NULL);
11342       break;
11343     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
11344     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
11345       _codec ("Sorensen video v.1");
11346       caps = gst_caps_new_simple ("video/x-svq",
11347           "svqversion", G_TYPE_INT, 1, NULL);
11348       break;
11349     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
11350       caps = gst_caps_new_empty_simple ("video/x-raw");
11351       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
11352       _codec ("Windows Raw RGB");
11353       break;
11354     case GST_MAKE_FOURCC ('r', 'a', 'w', ' '):
11355     {
11356       guint16 bps;
11357
11358       bps = QT_UINT16 (stsd_data + 98);
11359       switch (bps) {
11360         case 15:
11361           format = GST_VIDEO_FORMAT_RGB15;
11362           break;
11363         case 16:
11364           format = GST_VIDEO_FORMAT_RGB16;
11365           break;
11366         case 24:
11367           format = GST_VIDEO_FORMAT_RGB;
11368           break;
11369         case 32:
11370           format = GST_VIDEO_FORMAT_ARGB;
11371           break;
11372         default:
11373           /* unknown */
11374           break;
11375       }
11376       break;
11377     }
11378     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
11379       format = GST_VIDEO_FORMAT_I420;
11380       break;
11381     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
11382     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
11383       format = GST_VIDEO_FORMAT_I420;
11384       break;
11385     case GST_MAKE_FOURCC ('2', 'v', 'u', 'y'):
11386     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
11387       format = GST_VIDEO_FORMAT_UYVY;
11388       break;
11389     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
11390       format = GST_VIDEO_FORMAT_v308;
11391       break;
11392     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
11393       format = GST_VIDEO_FORMAT_v216;
11394       break;
11395     case GST_MAKE_FOURCC ('v', '2', '1', '0'):
11396       format = GST_VIDEO_FORMAT_v210;
11397       break;
11398     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
11399       format = GST_VIDEO_FORMAT_r210;
11400       break;
11401       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
11402          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
11403          format = GST_VIDEO_FORMAT_v410;
11404          break;
11405        */
11406       /* Packed YUV 4:4:4:4 8 bit in 32 bits
11407        * but different order than AYUV
11408        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
11409        format = GST_VIDEO_FORMAT_v408;
11410        break;
11411        */
11412     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
11413     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
11414       _codec ("MPEG-1 video");
11415       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
11416           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
11417       break;
11418     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
11419     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
11420     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
11421     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
11422     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
11423     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
11424     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
11425     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
11426     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
11427     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
11428     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
11429     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
11430     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
11431     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
11432     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
11433     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
11434     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
11435     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
11436     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
11437     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
11438     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
11439     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
11440     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
11441     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
11442     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
11443     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
11444     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
11445     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
11446     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
11447     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
11448     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
11449     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
11450     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
11451     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
11452     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
11453     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
11454     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
11455     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
11456     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
11457     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
11458     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
11459     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
11460     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
11461     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
11462     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
11463     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
11464       _codec ("MPEG-2 video");
11465       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
11466           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
11467       break;
11468     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
11469       _codec ("GIF still images");
11470       caps = gst_caps_new_empty_simple ("image/gif");
11471       break;
11472     case GST_MAKE_FOURCC ('h', '2', '6', '3'):
11473     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
11474     case GST_MAKE_FOURCC ('s', '2', '6', '3'):
11475     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
11476       _codec ("H.263");
11477       /* ffmpeg uses the height/width props, don't know why */
11478       caps = gst_caps_new_simple ("video/x-h263",
11479           "variant", G_TYPE_STRING, "itu", NULL);
11480       break;
11481     case GST_MAKE_FOURCC ('m', 'p', '4', 'v'):
11482     case GST_MAKE_FOURCC ('M', 'P', '4', 'V'):
11483       _codec ("MPEG-4 video");
11484       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
11485           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
11486       break;
11487     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
11488     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
11489       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
11490       caps = gst_caps_new_simple ("video/x-msmpeg",
11491           "msmpegversion", G_TYPE_INT, 43, NULL);
11492       break;
11493     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
11494       _codec ("DivX 3");
11495       caps = gst_caps_new_simple ("video/x-divx",
11496           "divxversion", G_TYPE_INT, 3, NULL);
11497       break;
11498     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
11499     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
11500       _codec ("DivX 4");
11501       caps = gst_caps_new_simple ("video/x-divx",
11502           "divxversion", G_TYPE_INT, 4, NULL);
11503       break;
11504     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
11505       _codec ("DivX 5");
11506       caps = gst_caps_new_simple ("video/x-divx",
11507           "divxversion", G_TYPE_INT, 5, NULL);
11508       break;
11509
11510     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
11511     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
11512     case GST_MAKE_FOURCC ('X', 'V', 'I', 'D'):
11513     case GST_MAKE_FOURCC ('x', 'v', 'i', 'd'):
11514     case GST_MAKE_FOURCC ('F', 'M', 'P', '4'):
11515     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
11516       caps = gst_caps_new_simple ("video/mpeg",
11517           "mpegversion", G_TYPE_INT, 4, NULL);
11518       if (codec_name)
11519         *codec_name = g_strdup ("MPEG-4");
11520       break;
11521
11522     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
11523       _codec ("Cinepak");
11524       caps = gst_caps_new_empty_simple ("video/x-cinepak");
11525       break;
11526     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
11527       _codec ("Apple QuickDraw");
11528       caps = gst_caps_new_empty_simple ("video/x-qdrw");
11529       break;
11530     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
11531       _codec ("Apple video");
11532       caps = gst_caps_new_empty_simple ("video/x-apple-video");
11533       break;
11534     case GST_MAKE_FOURCC ('H', '2', '6', '4'):
11535     case GST_MAKE_FOURCC ('a', 'v', 'c', '1'):
11536       _codec ("H.264 / AVC");
11537       caps = gst_caps_new_simple ("video/x-h264",
11538           "stream-format", G_TYPE_STRING, "avc",
11539           "alignment", G_TYPE_STRING, "au", NULL);
11540       break;
11541     case GST_MAKE_FOURCC ('a', 'v', 'c', '3'):
11542       _codec ("H.264 / AVC");
11543       caps = gst_caps_new_simple ("video/x-h264",
11544           "stream-format", G_TYPE_STRING, "avc3",
11545           "alignment", G_TYPE_STRING, "au", NULL);
11546       break;
11547     case GST_MAKE_FOURCC ('H', '2', '6', '5'):
11548     case GST_MAKE_FOURCC ('h', 'v', 'c', '1'):
11549       _codec ("H.265 / HEVC");
11550       caps = gst_caps_new_simple ("video/x-h265",
11551           "stream-format", G_TYPE_STRING, "hvc1",
11552           "alignment", G_TYPE_STRING, "au", NULL);
11553       break;
11554     case GST_MAKE_FOURCC ('h', 'e', 'v', '1'):
11555       _codec ("H.265 / HEVC");
11556       caps = gst_caps_new_simple ("video/x-h265",
11557           "stream-format", G_TYPE_STRING, "hev1",
11558           "alignment", G_TYPE_STRING, "au", NULL);
11559       break;
11560     case GST_MAKE_FOURCC ('r', 'l', 'e', ' '):
11561       _codec ("Run-length encoding");
11562       caps = gst_caps_new_simple ("video/x-rle",
11563           "layout", G_TYPE_STRING, "quicktime", NULL);
11564       break;
11565     case GST_MAKE_FOURCC ('W', 'R', 'L', 'E'):
11566       _codec ("Run-length encoding");
11567       caps = gst_caps_new_simple ("video/x-rle",
11568           "layout", G_TYPE_STRING, "microsoft", NULL);
11569       break;
11570     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
11571     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
11572       _codec ("Indeo Video 3");
11573       caps = gst_caps_new_simple ("video/x-indeo",
11574           "indeoversion", G_TYPE_INT, 3, NULL);
11575       break;
11576     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
11577     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
11578       _codec ("Intel Video 4");
11579       caps = gst_caps_new_simple ("video/x-indeo",
11580           "indeoversion", G_TYPE_INT, 4, NULL);
11581       break;
11582     case GST_MAKE_FOURCC ('d', 'v', 'c', 'p'):
11583     case GST_MAKE_FOURCC ('d', 'v', 'c', ' '):
11584     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
11585     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
11586     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
11587     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
11588     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
11589     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
11590       _codec ("DV Video");
11591       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
11592           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
11593       break;
11594     case GST_MAKE_FOURCC ('d', 'v', '5', 'n'): /* DVCPRO50 NTSC */
11595     case GST_MAKE_FOURCC ('d', 'v', '5', 'p'): /* DVCPRO50 PAL */
11596       _codec ("DVCPro50 Video");
11597       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
11598           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
11599       break;
11600     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
11601     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
11602       _codec ("DVCProHD Video");
11603       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
11604           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
11605       break;
11606     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
11607       _codec ("Apple Graphics (SMC)");
11608       caps = gst_caps_new_empty_simple ("video/x-smc");
11609       break;
11610     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
11611       _codec ("VP3");
11612       caps = gst_caps_new_empty_simple ("video/x-vp3");
11613       break;
11614     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
11615       _codec ("VP6 Flash");
11616       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
11617       break;
11618     case GST_MAKE_FOURCC ('X', 'i', 'T', 'h'):
11619       _codec ("Theora");
11620       caps = gst_caps_new_empty_simple ("video/x-theora");
11621       /* theora uses one byte of padding in the data stream because it does not
11622        * allow 0 sized packets while theora does */
11623       stream->padding = 1;
11624       break;
11625     case GST_MAKE_FOURCC ('d', 'r', 'a', 'c'):
11626       _codec ("Dirac");
11627       caps = gst_caps_new_empty_simple ("video/x-dirac");
11628       break;
11629     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
11630       _codec ("TIFF still images");
11631       caps = gst_caps_new_empty_simple ("image/tiff");
11632       break;
11633     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
11634       _codec ("Apple Intermediate Codec");
11635       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
11636       break;
11637     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
11638       _codec ("AVID DNxHD");
11639       caps = gst_caps_from_string ("video/x-dnxhd");
11640       break;
11641     case GST_MAKE_FOURCC ('V', 'P', '8', '0'):
11642       _codec ("On2 VP8");
11643       caps = gst_caps_from_string ("video/x-vp8");
11644       break;
11645     case GST_MAKE_FOURCC ('a', 'p', 'c', 's'):
11646       _codec ("Apple ProRes LT");
11647       caps =
11648           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
11649           NULL);
11650       break;
11651     case GST_MAKE_FOURCC ('a', 'p', 'c', 'h'):
11652       _codec ("Apple ProRes HQ");
11653       caps =
11654           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
11655           NULL);
11656       break;
11657     case GST_MAKE_FOURCC ('a', 'p', 'c', 'n'):
11658       _codec ("Apple ProRes");
11659       caps =
11660           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
11661           "standard", NULL);
11662       break;
11663     case GST_MAKE_FOURCC ('a', 'p', 'c', 'o'):
11664       _codec ("Apple ProRes Proxy");
11665       caps =
11666           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
11667           "proxy", NULL);
11668       break;
11669     case GST_MAKE_FOURCC ('a', 'p', '4', 'h'):
11670       _codec ("Apple ProRes 4444");
11671       caps =
11672           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
11673           "4444", NULL);
11674       break;
11675     case GST_MAKE_FOURCC ('v', 'c', '-', '1'):
11676     case FOURCC_ovc1:
11677       _codec ("VC-1");
11678       caps = gst_caps_new_simple ("video/x-wmv",
11679           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
11680       break;
11681     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
11682     default:
11683     {
11684       char *s, fourstr[5];
11685
11686       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11687       s = g_strdup_printf ("video/x-gst-fourcc-%s", g_strstrip (fourstr));
11688       caps = gst_caps_new_empty_simple (s);
11689       break;
11690     }
11691   }
11692
11693   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
11694     GstVideoInfo info;
11695
11696     gst_video_info_init (&info);
11697     gst_video_info_set_format (&info, format, stream->width, stream->height);
11698
11699     caps = gst_video_info_to_caps (&info);
11700     *codec_name = gst_pb_utils_get_codec_description (caps);
11701
11702     /* enable clipping for raw video streams */
11703     stream->need_clip = TRUE;
11704   }
11705
11706   return caps;
11707 }
11708
11709 static GstCaps *
11710 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
11711     guint32 fourcc, const guint8 * data, int len, gchar ** codec_name)
11712 {
11713   GstCaps *caps;
11714   const GstStructure *s;
11715   const gchar *name;
11716   gint endian = 0;
11717
11718   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
11719
11720   switch (fourcc) {
11721     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
11722     case GST_MAKE_FOURCC ('r', 'a', 'w', ' '):
11723       _codec ("Raw 8-bit PCM audio");
11724       caps = gst_caps_new_simple ("audio/x-raw",
11725           "format", G_TYPE_STRING, "U8",
11726           "layout", G_TYPE_STRING, "interleaved", NULL);
11727       break;
11728     case GST_MAKE_FOURCC ('t', 'w', 'o', 's'):
11729       endian = G_BIG_ENDIAN;
11730       /* fall-through */
11731     case GST_MAKE_FOURCC ('s', 'o', 'w', 't'):
11732     {
11733       gchar *str;
11734       gint depth;
11735       GstAudioFormat format;
11736
11737       if (!endian)
11738         endian = G_LITTLE_ENDIAN;
11739
11740       depth = stream->bytes_per_packet * 8;
11741       format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
11742
11743       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
11744       _codec (str);
11745       g_free (str);
11746
11747       caps = gst_caps_new_simple ("audio/x-raw",
11748           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
11749           "layout", G_TYPE_STRING, "interleaved", NULL);
11750       break;
11751     }
11752     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
11753       _codec ("Raw 64-bit floating-point audio");
11754       caps = gst_caps_new_simple ("audio/x-raw",
11755           "format", G_TYPE_STRING, "F64BE",
11756           "layout", G_TYPE_STRING, "interleaved", NULL);
11757       break;
11758     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
11759       _codec ("Raw 32-bit floating-point audio");
11760       caps = gst_caps_new_simple ("audio/x-raw",
11761           "format", G_TYPE_STRING, "F32BE",
11762           "layout", G_TYPE_STRING, "interleaved", NULL);
11763       break;
11764     case FOURCC_in24:
11765       _codec ("Raw 24-bit PCM audio");
11766       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
11767        * endian later */
11768       caps = gst_caps_new_simple ("audio/x-raw",
11769           "format", G_TYPE_STRING, "S24BE",
11770           "layout", G_TYPE_STRING, "interleaved", NULL);
11771       break;
11772     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
11773       _codec ("Raw 32-bit PCM audio");
11774       caps = gst_caps_new_simple ("audio/x-raw",
11775           "format", G_TYPE_STRING, "S32BE",
11776           "layout", G_TYPE_STRING, "interleaved", NULL);
11777       break;
11778     case GST_MAKE_FOURCC ('u', 'l', 'a', 'w'):
11779       _codec ("Mu-law audio");
11780       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
11781       break;
11782     case GST_MAKE_FOURCC ('a', 'l', 'a', 'w'):
11783       _codec ("A-law audio");
11784       caps = gst_caps_new_empty_simple ("audio/x-alaw");
11785       break;
11786     case 0x0200736d:
11787     case 0x6d730002:
11788       _codec ("Microsoft ADPCM");
11789       /* Microsoft ADPCM-ACM code 2 */
11790       caps = gst_caps_new_simple ("audio/x-adpcm",
11791           "layout", G_TYPE_STRING, "microsoft", NULL);
11792       break;
11793     case 0x1100736d:
11794     case 0x6d730011:
11795       _codec ("DVI/IMA ADPCM");
11796       caps = gst_caps_new_simple ("audio/x-adpcm",
11797           "layout", G_TYPE_STRING, "dvi", NULL);
11798       break;
11799     case 0x1700736d:
11800     case 0x6d730017:
11801       _codec ("DVI/Intel IMA ADPCM");
11802       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
11803       caps = gst_caps_new_simple ("audio/x-adpcm",
11804           "layout", G_TYPE_STRING, "quicktime", NULL);
11805       break;
11806     case 0x5500736d:
11807     case 0x6d730055:
11808       /* MPEG layer 3, CBR only (pre QT4.1) */
11809     case GST_MAKE_FOURCC ('.', 'm', 'p', '3'):
11810       _codec ("MPEG-1 layer 3");
11811       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
11812       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
11813           "mpegversion", G_TYPE_INT, 1, NULL);
11814       break;
11815     case 0x20736d:
11816     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
11817       _codec ("EAC-3 audio");
11818       caps = gst_caps_new_simple ("audio/x-eac3",
11819           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
11820       stream->sampled = TRUE;
11821       break;
11822     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
11823     case GST_MAKE_FOURCC ('a', 'c', '-', '3'):
11824       _codec ("AC-3 audio");
11825       caps = gst_caps_new_simple ("audio/x-ac3",
11826           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
11827       stream->sampled = TRUE;
11828       break;
11829     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
11830     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
11831       _codec ("DTS audio");
11832       caps = gst_caps_new_simple ("audio/x-dts",
11833           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
11834       stream->sampled = TRUE;
11835       break;
11836     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
11837     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
11838       _codec ("DTS-HD audio");
11839       caps = gst_caps_new_simple ("audio/x-dts",
11840           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
11841       stream->sampled = TRUE;
11842       break;
11843     case GST_MAKE_FOURCC ('M', 'A', 'C', '3'):
11844       _codec ("MACE-3");
11845       caps = gst_caps_new_simple ("audio/x-mace",
11846           "maceversion", G_TYPE_INT, 3, NULL);
11847       break;
11848     case GST_MAKE_FOURCC ('M', 'A', 'C', '6'):
11849       _codec ("MACE-6");
11850       caps = gst_caps_new_simple ("audio/x-mace",
11851           "maceversion", G_TYPE_INT, 6, NULL);
11852       break;
11853     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
11854       /* ogg/vorbis */
11855       caps = gst_caps_new_empty_simple ("application/ogg");
11856       break;
11857     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
11858       _codec ("DV audio");
11859       caps = gst_caps_new_empty_simple ("audio/x-dv");
11860       break;
11861     case GST_MAKE_FOURCC ('m', 'p', '4', 'a'):
11862       _codec ("MPEG-4 AAC audio");
11863       caps = gst_caps_new_simple ("audio/mpeg",
11864           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
11865           "stream-format", G_TYPE_STRING, "raw", NULL);
11866       break;
11867     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
11868       _codec ("QDesign Music");
11869       caps = gst_caps_new_empty_simple ("audio/x-qdm");
11870       break;
11871     case GST_MAKE_FOURCC ('Q', 'D', 'M', '2'):
11872       _codec ("QDesign Music v.2");
11873       /* FIXME: QDesign music version 2 (no constant) */
11874       if (FALSE && data) {
11875         caps = gst_caps_new_simple ("audio/x-qdm2",
11876             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
11877             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
11878             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
11879       } else {
11880         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
11881       }
11882       break;
11883     case GST_MAKE_FOURCC ('a', 'g', 's', 'm'):
11884       _codec ("GSM audio");
11885       caps = gst_caps_new_empty_simple ("audio/x-gsm");
11886       break;
11887     case GST_MAKE_FOURCC ('s', 'a', 'm', 'r'):
11888       _codec ("AMR audio");
11889       caps = gst_caps_new_empty_simple ("audio/AMR");
11890       break;
11891     case GST_MAKE_FOURCC ('s', 'a', 'w', 'b'):
11892       _codec ("AMR-WB audio");
11893       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
11894       break;
11895     case GST_MAKE_FOURCC ('i', 'm', 'a', '4'):
11896       _codec ("Quicktime IMA ADPCM");
11897       caps = gst_caps_new_simple ("audio/x-adpcm",
11898           "layout", G_TYPE_STRING, "quicktime", NULL);
11899       break;
11900     case GST_MAKE_FOURCC ('a', 'l', 'a', 'c'):
11901       _codec ("Apple lossless audio");
11902       caps = gst_caps_new_empty_simple ("audio/x-alac");
11903       break;
11904     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
11905       _codec ("QualComm PureVoice");
11906       caps = gst_caps_from_string ("audio/qcelp");
11907       break;
11908     case GST_MAKE_FOURCC ('w', 'm', 'a', ' '):
11909     case FOURCC_owma:
11910       _codec ("WMA");
11911       caps = gst_caps_new_empty_simple ("audio/x-wma");
11912       break;
11913     case GST_MAKE_FOURCC ('l', 'p', 'c', 'm'):
11914     {
11915       guint32 flags = 0;
11916       guint32 depth = 0;
11917       guint32 width = 0;
11918       GstAudioFormat format;
11919       enum
11920       {
11921         FLAG_IS_FLOAT = 0x1,
11922         FLAG_IS_BIG_ENDIAN = 0x2,
11923         FLAG_IS_SIGNED = 0x4,
11924         FLAG_IS_PACKED = 0x8,
11925         FLAG_IS_ALIGNED_HIGH = 0x10,
11926         FLAG_IS_NON_INTERLEAVED = 0x20
11927       };
11928       _codec ("Raw LPCM audio");
11929
11930       if (data && len >= 56) {
11931         depth = QT_UINT32 (data + 40);
11932         flags = QT_UINT32 (data + 44);
11933         width = QT_UINT32 (data + 48) * 8 / stream->n_channels;
11934       }
11935       if ((flags & FLAG_IS_FLOAT) == 0) {
11936         if (depth == 0)
11937           depth = 16;
11938         if (width == 0)
11939           width = 16;
11940         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
11941             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
11942             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
11943         caps = gst_caps_new_simple ("audio/x-raw",
11944             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
11945             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
11946             "non-interleaved" : "interleaved", NULL);
11947       } else {
11948         if (width == 0)
11949           width = 32;
11950         if (width == 64) {
11951           if (flags & FLAG_IS_BIG_ENDIAN)
11952             format = GST_AUDIO_FORMAT_F64BE;
11953           else
11954             format = GST_AUDIO_FORMAT_F64LE;
11955         } else {
11956           if (flags & FLAG_IS_BIG_ENDIAN)
11957             format = GST_AUDIO_FORMAT_F32BE;
11958           else
11959             format = GST_AUDIO_FORMAT_F32LE;
11960         }
11961         caps = gst_caps_new_simple ("audio/x-raw",
11962             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
11963             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
11964             "non-interleaved" : "interleaved", NULL);
11965       }
11966       break;
11967     }
11968     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
11969       /* ? */
11970     default:
11971     {
11972       char *s, fourstr[5];
11973
11974       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11975       s = g_strdup_printf ("audio/x-gst-fourcc-%s", g_strstrip (fourstr));
11976       caps = gst_caps_new_empty_simple (s);
11977       break;
11978     }
11979   }
11980
11981   if (caps) {
11982     GstCaps *templ_caps =
11983         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
11984     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
11985     gst_caps_unref (caps);
11986     gst_caps_unref (templ_caps);
11987     caps = intersection;
11988   }
11989
11990   /* enable clipping for raw audio streams */
11991   s = gst_caps_get_structure (caps, 0);
11992   name = gst_structure_get_name (s);
11993   if (g_str_has_prefix (name, "audio/x-raw")) {
11994     stream->need_clip = TRUE;
11995     stream->max_buffer_size = 4096 * stream->bytes_per_frame;
11996     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
11997   }
11998   return caps;
11999 }
12000
12001 static GstCaps *
12002 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12003     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
12004 {
12005   GstCaps *caps;
12006
12007   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
12008
12009   switch (fourcc) {
12010     case GST_MAKE_FOURCC ('m', 'p', '4', 's'):
12011       _codec ("DVD subtitle");
12012       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
12013       stream->need_process = TRUE;
12014       break;
12015     case GST_MAKE_FOURCC ('t', 'e', 'x', 't'):
12016       _codec ("Quicktime timed text");
12017       goto text;
12018     case GST_MAKE_FOURCC ('t', 'x', '3', 'g'):
12019       _codec ("3GPP timed text");
12020     text:
12021       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
12022           "utf8", NULL);
12023       /* actual text piece needs to be extracted */
12024       stream->need_process = TRUE;
12025       break;
12026     default:
12027     {
12028       char *s, fourstr[5];
12029
12030       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12031       s = g_strdup_printf ("text/x-gst-fourcc-%s", g_strstrip (fourstr));
12032       caps = gst_caps_new_empty_simple (s);
12033       break;
12034     }
12035   }
12036   return caps;
12037 }
12038
12039 static GstCaps *
12040 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12041     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
12042 {
12043   GstCaps *caps;
12044
12045   switch (fourcc) {
12046     case GST_MAKE_FOURCC ('m', '1', 'v', ' '):
12047       _codec ("MPEG 1 video");
12048       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
12049           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12050       break;
12051     default:
12052       caps = NULL;
12053       break;
12054   }
12055   return caps;
12056 }